FeaturesPluginsDocs & SupportCommunityPartners

Advanced Free-Form Project Configuration

Contributed and maintained by and David Konecny

Free-form projects in NetBeans IDE 4.0 provide a very powerful tool for Java developers that build and run their applications using an Ant script. For a description of how to set up a basic free-form project, see this guide.

If you are comfortable working with Ant, you can edit your Ant script and the IDE project configuration file to achieve an even tighter integration between NetBeans IDE and your build process. This article covers the following information:


Mapping IDE Commands to Ant Targets

There are two ways to map an IDE command to a target in an Ant script:

  • By adjusting the settings in the Build and Run page of a project's Project Properties dialog box
  • By manually editing the project's project.xml file

Mapping IDE Commands in the Project Properties Dialog Box

The Project Properties dialog box is the main tool for configuring free-form projects in the IDE. To open the dialog box, right-click the free-form project node (icon) in the Projects window and choose Properties. In the Build and Run page, you can set the Ant target to run for the following commands:

  • Build Project
  • Clean Project
  • Generate Javadoc
  • Run Project (free-form Java projects)
  • Deploy Project (free-form Web projects)
  • Test Project
  • Debug Project

Note: If your Ant script uses an import statement to import targets from another Ant script, the targets do not show up in the drop-down lists in the Project Properties dialog box. To map commands to these targets, you have to type the names of the targets into the drop-down lists.

You can also add shortcuts for any target in your Ant script to the contextual menu of the project's node in the Custom Menu Items list.

Mapping IDE Commands in project.xml

Each IDE project has a project.xml file that contains important metadata about your project's contents, the location of the project's Ant script, which targets to run for IDE commands, and other information. If you want to map commands that work on the presently selected files in the IDE, or if you want to map a command to a target in a separate Ant script, you have to edit the project.xml file by hand. In the Files window, expand the root folder for your project and the nbproject folder, then double-click project.xml.

The ide-actions element holds the mappings for IDE commands. You enter an action element with the name for any of the standard IDE actions and define the script and target to which you want to map the command.

The standard IDE actions that are available are as follows:

  • build - Build project (F11)
  • rebuild - Clean and build project (Shift-F11)
  • compile.single - Compile selected file (F9)
  • clean - Clean project
  • run - Run project (F6)
  • run.single - Run selected file (Shift-F6)
  • redeploy - For Web application projects, build project, undeploy project from server, and deploy project to server
  • test - Run JUnit tests for project (Alt-F6)
  • test.single - Run the JUnit test for selected file (Ctrl-F6)
  • debug.test.single - Debug the JUnit test for selected file (Ctrl-Shift-F6)
  • debug - Run project in the debugger (F5)
  • debug.single - Debug selected file (Ctrl-Shift-F5)
  • debug.fix - Reload the selected file during a debugging session
  • debug.stepinto - Execute one line of the project main class in the debugger and pause (F7)
  • javadoc - Generate Javadoc for project

For example, the following maps the Debug Project to the debug-nb target of the project's Ant script:

  <action name="debug">
    <target>debug-nb</target>
  </action>

The Ant targets for NetBeans IDE commands do not have to live in the same Ant script that you use to build and run the project. This is useful for users who cannot alter their Ant script. The following maps the Debug Project to the debug-nb target in a separate Ant script:

  <action name="debug">
    <script>path/to/my/nbtargets.xml</script>
    <target>debug-nb</target>
  </action>

Note: <script> must precede <target>.

You can also configure a command to run multiple targets. The targets are run in the order they appear in the action. For example, the mapping for the Clean and Build Project command looks like this:

   <action name="rebuild">
        <target>clean</target>
        <target>compile</target>
    </action>

Adding Shortcuts to Project Node Contextual Menu

project.xml also has a context-menu element that controls the contents of a project node's contextual menu. If you manually add an action that is run on the project, make sure you register the action name in <context-menu> as well. If you use the Project Properties dialog box to configure a standard project command, the IDE automatically adds the command to the project's contextual menu.

Back to top


Editing the project.xml File

Each IDE project has a project.xml file that includes important information about the project, such as:

  • Mappings between project commands and targets in an Ant script
  • Information about the project's contents, classpath, and target Java platform. This information is used to visualize the project and enable code completion and refactoring

Using Properties in the project.xml File

You can define properties inside the project.xml file itself or store them in a separate .properties file. One way of keeping your project.xml file synchronized with the information in your Ant script is to import properties into project.xml from the same .properties file that is used by your Ant script.

Note, however, that all file paths in project.xml are by default relative to the project folder. If your Ant script is not located in the project folder, a classdir property that points to build/classes/ does not point to the same directory for the Ant script and for the project.xml file. (The project folder is the folder that contains your nbproject folder, not the nbproject folder itself. By default, the new free-form project wizard makes your Ant script's parent folder the project folder.)

You can solve this problem by defining properties for important paths (like project.dir) and using these properties to be more exact (for example, classdir=${project.dir}/build/classes).

To create and import properties in project.xml, enter the following between the name element and the folders element:

<properties>
  <property name="name">value</property>
  <property-file>my-properties-file.properties</property-file>
  <property-file>another-properties-file.properties</property-file>
</properties> 

Note that the syntax is different than the syntax used in Ant scripts. Also note that you while you can add properties in any order, properties can only refer to other properties that have been defined previously in project.xml. The properties file path itself can also use property substitutions.

Validating the project.xml File

The IDE comes bundled with the XML schemas for free-form project.xml files and automatically validates a free-form project.xml file every time you edit and save it. You can view the XML schemas for the free-form project.xml file at the following locations:

Back to top


Writing a Target to Debug Your J2SE Application

Let's look at a target that runs the project in the debugger. To view all of the targets discussed below, see these sample NetBeans IDE targets. Of course, you have to change the names of the properties and the target dependencies to match the properties and targets in your Ant script.

First, make sure everything is set to run the program in the debugger:

<target name="debug" depends="compile" if="netbeans.home" description="Debug Project">  
  • if="netbeans.home" checks whether Ant is running inside NetBeans IDE. This condition should be specified on all Ant targets that can only run inside the IDE, like debugging targets.

Now start the debugger:

  <nbjpdastart name="My App" addressproperty="jpda.address" transport="dt_socket">
     <classpath refid="run.classpath"/>
     <!-- Optional - If source roots are properly declared in project, should
	      work without setting source path.
     <sourcepath refid="debug.sourcepath"/> -->
  </nbjpdastart>
  • The name attribute in nbjpdastart is the display name given in the Sessions window when you debug the project.
  • addressproperty can be any property name. The debugger saves the port it is listening on in this property. The application being debugged then uses this address to connect to the debugger.
  • classpath should specify the same classpath used for project execution. In this case, we reuse the Ant script's run.classpath property, which holds the execution classpath.
  • sourcepath is optional. If your JAR files all have associated source files (they come from an IDE project or have been registered in the Library Manager), the target should work without providing this information. If the debugger can't find your sources, you can use sourcepath to explicitly specify their location. Again, the IDE does not define this property. You have to define this property yourself.
    Then run the project in the debugger:
  <java fork="true" classname="com.me.myapp.Main">
    <jvmarg value="-Xdebug"/>
    <jvmarg value="-Xnoagent"/>
    <jvmarg value="-Djava.compiler=none"/>
    <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
    <classpath refid="run.classpath"/>
  </java>
</target>
  • Set fork="true" to ensure the process is launched in a separate VM.
  • Set any necessary JVM arguments or program arguments in the java task as well.
    Note: The IDE does not define any of the path elements or properties in this target for you. You have to define all path elements, like run.classpath, and properties, like jpda.address, either in the Ant script or in a separate .properties file.

Now let's map the debug target to the Debug Project command. If the debug target is in the same Ant script that is used to build and run the project, open the project's Project Properties dialog box, go to Build and Run, and set Debug Project to the debug target.

If you keep this target in a separate Ant script, open the project's project.xml file and enter the following under ide-actions:

  <action name="debug">
    <script>path/to/my/nbtargets.xml</script>
    <target>debug</target>
  </action>

Of course, you have to point the script element to your Ant script.

Back to top


Writing a Target to Debug Your Web Application

Now let's look at a target to attach a debugger to a web application.

First, start the web server in debug mode. For example, use the following command to start an external Tomcat server in debug mode:

  catalina jpda start 

Now run a target to deploy the application. For example, use the following target to use the Tomcat Manager to deploy your web application:

  <target name="deploy" depends="compile" description="Deploy application to servlet container">
     <deploy url="${manager.url}"
	     username="${manager.username}"
	     password="${manager.password}"
		 path="${app.path}"
	     localWar="file://${build.home}"/>
  </target>

Next, run a target to start the debugger and open the IDE's default browser:

    <target name="debug" depends="compile, deploy" if="netbeans.home" description="Debug Project">
<nbjpdaconnect name="${app.name}" host="${jpda.host}" address="${jpda.address}" transport="dt_socket"> <classpath refid="${run.classpath}"/> <sourcepath refid="${debug.sourcepath}"/> </nbjpdaconnect>
<nbbrowse url="${client.url}"/>
</target>
  • if="netbeans.home" checks whether Ant is running inside NetBeans IDE. This condition should be specified on all Ant targets that can only run inside the IDE, like debugging targets.
  • The name attribute in nbjpdaconnect is the display name given in the Sessions window when you debug the project.
  • host and address are the host and port number that the application to be debugged uses to connect to the debugger.
  • classpath should specify the same classpath used for project execution. In this case, we reuse the Ant script's run.classpath property, which holds the execution classpath.
  • sourcepath explicitly specifies the location of your source files.
  • <nbbrowse url="${client.url}"/> opens the specified URL in the IDE's default browser.

    Note: The IDE does not define any of the path elements or properties in this target for you. You have to define all path elements, like run.classpath, debug.sourcepath, and properties, like jpda.address, either in the Ant script or in a separate .properties file.

Finally, map the debug target to the Debug Project command. If the debug target is in the same Ant script that is used to build and run the project, open the project's Project Properties dialog box, go to Build and Run, and set Debug Project to the debug target.

If you keep this target in a separate Ant script, open the project's project.xml file and enter the following under ide-actions:

  <action name="debug">
    <script>path/to/my/nbtargets.xml</script>
    <target>debug</target>
  </action>

Of course, you have to point the script element to your Ant script.

Back to top


Writing a Target to Compile/Run/Debug a Single File

The IDE provides a simple mechanism for running targets on the currently selected file in the IDE. The IDE has the following predefined actions that you can map to Ant targets:

  • compile.single - Compile selected file (F9)
  • run.single - Run selected file (Shift-F6)
  • debug.single - Debug selected file (Ctrl-Shift-F5)
  • test.single - Run the JUnit test for selected file (Ctrl-F6)
  • debug.test.single - Debug the JUnit test for selected file (Ctrl-Shift-F6)

Each of these actions contains a context element that gets a reference to the currently selected files and stores it in a property of your choice. You use this property in your Ant targets to specify which files to process.

Compiling the Selected Files

Let's demonstrate how this works with compilation. A typical target for compiling all project sources usually looks something like the following:

  <target name="compile" depends="...">
    <mkdir dir="${classes.dir}"/>
    <javac srcdir="${src.dir}" destdir="${classes.dir}">
      <classpath refid="javac.classpath"/>
    </javac>
  </target>

The target compiles all files from src.dir. To compile a single file (or the list of selected files), you need to modify the above target to the following:

  <target name="compile-selected-files" depends="...">
    <fail unless="files">Must set property 'files'</fail>
    <mkdir dir="${classes.dir}"/>
    <javac srcdir="${src.dir}" destdir="${classes.dir}" includes="${files}">
      <classpath refid="javac.classpath"/>
    </javac>
  </target>

The files property is a newly defined property that holds the file (or files) that you want to compile. The javac task accepts a comma-separated list of file names. The file names are specified relative to the directory specified in the srcdir attribute (for example, org/nb/Foo.java,org/nb/Bar.java).

Getting a Reference to the Currently Selected File in the IDE

Once you have an Ant script that supports single file compilation, you have to get a reference to the currently selected file in the IDE and store it in a property. For example, the compile-selected-files target above looks for the currently selected files in the files property.

You store this reference in the same place where you map the build target (compile-selected-files) to the IDE action. First we will look at how to do this and then we will explain it in detail:

  <ide-actions>
    <action name="compile.single">
      <target>compile-selected-files</target>
      <context>
        <property>files</property>
        <folder>${src.dir}</folder>
        <pattern>\.java$</pattern>
        <format>relative-path</format>
        <arity>
          <separated-files>,</separated-files>
        </arity>
      </context>
    </action>

Now let's take a look at how it works.

<action name="compile.single">
      <target>compile-selected-files</target>
  • Maps the Compile File command and the F9 shortcut to the compile-selected-files target.
      <context>
        <property>files</property>
  • <context> sets the context on which the Ant target is executed. In this case, it is the name of files that you want to compile.
  • files is the name of the property that holds the context. You can choose any unique name for this property. This property must be set by the IDE before the target can be run.

        <folder>${src.dir}</folder>
        <pattern>\.java$</pattern>
        <format>relative-path</format>
        <arity>
          <separated-files>,</separated-files>
        </arity>
      </context>
    </action>

  • <arity> specifies that files can hold multiple files and that the separator is a comma. If your target accepts only one file at time then change the declaration to:
    <arity>
      <one-file-only/>
    </arity>
  • <format>relative-path</format> specifies that instead of passing the selected file's absolute file name to the Ant target, the IDE should pass the relative file name. Other formatting options are:
    • relative-path-noext - Same as relative-path, but the file's extension is removed
    • absolute-path - Absolute file name
    • absolute-path-noext - Same as absolute-path, but the file's extension is removed
    • java-name - Same as relative-path-noext, but a dot character (.) is used instead of a slash (/)
  • <folder>${src.dir}</folder> specifies that the file name should be relative to the src.dir directory and that this action is only enabled for the src.dir directory.
    Note: The IDE does not define the ${src.dir} property for you. You have to define the property or import the .properties file that the Ant is using in project.xml. See Using Properties in the project.xml File for more information.
  • <pattern>\.java$</pattern> is the regular expression which the file names must pass. You use <pattern> to limit which files can be passed to the Ant target. In this case, you want the target be executed only with files that end in .java.

Note: You can configure multiple compile.single actions to overload the F9 shortcut and menu command with different functionality depending on what file is selected. For example, you could set up a separate compile-selected-files target for JUnit test classes, then map compile.single to that target for all sources in JUnit test directories. Or you could change the pattern to \.xml$ and map F9 to a Validate XML target for all XML files.

Debugging the Selected File

The process is basically the same for writing targets to debug and run a single file. The debug-selected-files target looks something like this:

    <target name="debug-selected-files" depends="compile" if="netbeans.home" description="Debug a Single File">
       <fail unless="classname">Must set property 'classname'</fail>
       <nbjpdastart name="${classname}" addressproperty="jpda.address" transport="dt_socket">
          <classpath refid="run.classpath"/>
          <!-- Optional - If source roots are properly declared in project, should
          work without setting source path.
          <sourcepath refid="debug.sourcepath"/> -->
       </nbjpdastart>
       <java classname="${classname}" fork="true">
          <jvmarg value="-Xdebug"/>
          <jvmarg value="-Xnoagent"/>
          <jvmarg value="-Djava.compiler=none"/>
          <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
          <classpath refid="run.classpath"/>
       </java>
     </target>
  • This is basically the same as the debug target. Instead of passing the program main class to java, you pass the classname property, which is set by the IDE to the currently selected file.

Then you map the debug-selected-files target to the debug.single action:

   <action name="debug.single">
      <target>debug-selected-files</target>
      <context>
         <property>classname</property>
         <folder>${src.dir}</folder>
         <pattern>\.java$</pattern>
         <format>java-name</format>
         <arity>
            <one-file-only/>
         </arity>
      </context>
   </action>
  • <property> now stores the context in the classname property.
  • Since java can only take single file, you set <arity> to <one-file-only>.
  • Setting <format> to java-name and making it relative to src.dir creates a fully-qualified class name for the currently selected file.
    Note: The IDE does not define the ${src.dir} property for you. You have to define the property or import the .properties file that the Ant is using in project.xml. See Using Properties in the project.xml File for more information.

Running the Selected File

The run-selected-files target looks something like this:

   <target name="run-selected-files" depends="compile" description="Run Single File">
      <fail unless="classname">Must set property 'classname'</fail>
      <java classname="${classname}">
         <classpath refid="run.classpath"/>
      </java>
   </target>

And you hook it up to the Run File command and the Shift-F6 shortcut with the following action:

    <action name="run.single">
        <target>run-single</target>
        <context>
            <property>classname</property>
            <folder>${src.dir}</folder>
            <pattern>\.java$</pattern>
            <format>java-name</format>
            <arity>
                <one-file-only/>
            </arity>
        </context>
    </action>

Back to top


Writing a Target for the Fix Command

The Fix command allows you to make changes to your code during a debugging session and continue debugging with the changed code without restarting your program. The IDE contains a nbjpdareload task that you can use to write a target for the Fix command.

A typical target for the fix command looks something like this:

  <target name="debug-fix">
    <javac srcdir="${src.dir}" destdir="${classes.dir}" debug="true" >
      <classpath refid="javac.classpath"/>
      <include name="${fix.file}.java"/>
    </javac>
    <nbjpdareload>
      <fileset dir="${classes.dir}">
        <include name="${fix.file}.class"/>
      </fileset>
    </nbjpdareload>
  </target>
  • The target compiles the currently selected file using the ${fix.file} property. (In the next section you will set up the IDE to store the name of the currently selected file in this property.)
  • The nbjpdareload task reloads the corrected file in the application.

To hook this target up to the Fix command, define the following action in <ide-actions> in project.xml:

  <action name="debug.fix">
    <target>debug-fix</target>
    <context>
      <property>fix.file</property>
      <folder>${src.dir}</folder>
      <pattern>\.java$</pattern>
      <format>relative-path-noext</format>
      <arity>
        <one-file-only/>
      </arity>
    </context>
  </action>
  • <property> now stores the context in the fix.file property.
  • Since you can only run the Fix command on one file at a time, you set <arity> to <one-file-only>.
  • You have to pass the full path to the .java file to the javac task and the full path to the .class file to the nbjpdareload task. You therefore set the <format> to rel-path-noext, then append .class or .java in the debug-fix target as necessary.
    Note: The IDE does not define the ${src.dir} property for you. You have to define the property or import the .properties file that the Ant is using in project.xml. See Using Properties in the project.xml File for more information.

Back to top

Bookmark this page

del.icio.us furl simpy slashdot technorati digg
Companion
Projects:
MySQL Database Server   Open JDK: an Open SourceJDK   GlassFish Community: an Open Source Application Server    Mobile & Embedded Community    Open Solaris   java.net - The Source for Java Technology Collaboration   Open ESB - The Open Enterprise Service Bus Powered by