Advanced Free-Form Project Configuration

Free-form projects in NetBeans IDE provide a very powerful tool for Java developers that build and run their applications using an Ant script.

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 assumes that you have already completed the first steps in setting up a free-form project. See this guide for setting up a free-form standard project and this guide for setting up a free-form web project.

This article covers the following information:

You can also download Sample Ant Targets.

Mapping IDE Commands to Ant Targets

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

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:

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:

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:

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

Creating a Target to Debug Your Java SE Application

Similar to commands for compiling and running, debugging commands rely on various information, such as the location of your sources, the location of the compiled classes and other items on the classpath, and name of the project's main class.

In free-form projects, the IDE does not "know" about any of these things. When you run a command in the IDE (such as Build Project), the IDE simply calls a target in your build script and lets the script handle the command. Therefore, for debugging to work, you also have to have a build script target for debugging. The IDE provides some custom Ant tasks to work with the debugger and also can generate a basic debug target, which attempts to fill in important details based on other targets in your script.

To set up debugging in a free-form project, you need to do the following:

Creating the Debug Target

If you do not have a debug target written for your project, the IDE will offer to generate a basic target for you when you first try to debug the project. You can then inspect the target and customize it for the project's specific requirements.

Note:Before you have the debug target generated, it is a good idea to first make sure that you have a target mapped to the Run Project command. When the IDE generates a debug target, it looks for information in the target you have mapped to the Run Project command to determine such things such as the run classpath and the project's main class. If you have a target mapped to the Run Project command, there is a good chance that the generated debug target will work without further customization.

To create a debug target for a free-form project:

  1. In the Projects window, right-click the project's node and choose Set Main Project.
  2. Choose Run > Debug Main Project.
  3. In the Debug Project dialog box that appears, click Generate.

    A target called debug-nb is created in a file called ide-targets.xml. The generated ide-targets.xml file is a build script that imports your main build.xml file, so your debug target can take advantage of targets and properties set by or referenced by your main build script.

    In addition, a mapping for this target is created in the project.xml file so that the target is called whenever you choose the Debug Project command in the IDE. If you write the target from scratch, you need to also create this mapping yourself. See Manually Mapping a Target to a Menu Item.

  4. Verify that the generated debug-nb target properly takes into account all of the elements of your project. In particular, you might need to modify the <classpath> argument in the target if it does not include all of the items in your run classpath.

Once the target is created, you can start debugging. To start debugging:

  1. Set a breakpoint in your main class. You can do so by clicking in the left margin of the line where you want to set the breakpoint. The line with the breakpoint is highlighted in pink.
  2. Once again, right-click the project's node and choose Debug Project.

    The target should run and start execution of the program. Progress of the running target is shown in the Output window and the status of the debugger is shown in the status bar at the bottom of the Output window.

A Typical Free-Form Project Debug Target

The generated Ant target does the following:

Note: You can add any additional JVM arguments or program arguments in the java task as well.

A generated debug target where the IDE is able to guess the runtime classpath looks something like the following (where italicized items would have values specific to your project):

<?xml version="1.0" encoding="UTF-8"?>
    <project basedir=".." name="YourProjectName">
    <import file="../build.xml"/>
    <!-- TODO: edit the following target according to your needs -->
    <!-- (more info: http://www.netbeans.org/kb/articles/freeform-config.html#debugj2se) -->
    <target name="debug-nb">
    <nbjpdastart addressproperty="jpda.address" name="NameOfProject" transport="dt_socket">
    <classpath path="ClasspathSpecifiedInYourRunTarget"/>
    </nbjpdastart>
    <java classname="MainClassSpecifiedInRunTarget" classpath="ClasspathSpecifiedInYourRunTarget" fork="true">
    <jvmarg value="-Xdebug"/>
    <jvmarg value="-Xnoagent"/>
    <jvmarg value="-Djava.compiler=none"/>
    <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
    </java>
    </target>
    </project>

If you do not have a run target mapped or the IDE otherwise can not determine the project's classpath or main class, the generated debug target includes "TODO" placeholders for you to fill in these values as in the example below.

<?xml version="1.0" encoding="UTF-8"?>
    <project basedir=".." name="YourProjectName">
    <!-- TODO: edit the following target according to your needs -->
    <!-- (more info: http://www.netbeans.org/kb/articles/freeform-config.html#debugj2se) -->
    <target name="debug-nb">
    <path id="cp">
    <!-- TODO configure the runtime classpath for your project here: -->
    </path>
    <nbjpdastart addressproperty="jpda.address" name="NameOfProject" transport="dt_socket">
    <classpath refid="cp"/>
    </nbjpdastart>
    <!-- TODO configure the main class for your project here: -->
    <java classname="some.main.Class" fork="true">
    <classpath refid="cp"/>
    <jvmarg value="-Xdebug"/>
    <jvmarg value="-Xnoagent"/>
    <jvmarg value="-Djava.compiler=none"/>
    <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
    </java>
    </target>
    </project>

To specify the runtime classpath, insert pathelement elements within the path element and point them to the directories that contain the items in your classpath. For example, you can use the location attribute of pathelement to specify the location of the classpath items relative to your project directory. The project directory is usually the one that contains the project's build.xml file. Below is an example:

<path id="cp">
    <pathelement location="libs">  
    <pathelement location="build">
</path>

Manually Mapping a Target to a Menu Item

When you have the IDE generate a target, the IDE automatically provides the mapping between the target and the IDE command's menu item. However, if you have created the target manually, you need to also create the mapping manually.

To map the Debug Project command to a target in an external Ant script:

  1. Open the project's project.xml file and add the following to <ide-actions>:
      <action name="debug">
            <script>path_to_Ant_script</script>
            <target>target_name</target>
            </action> 
  2. Add the command to the project node's contextual menu, by adding the following line to the <context-menu> target:

      <ide-action name="debug"/>

    The IDE maps the Debug Project action to the specified target in the project's Ant script.

Creating a Target to Debug Your Web Application

Now let's look at a target to attach a debugger to a web application. First, choose Run > Debug Main Project (F5). If you do not have a target mapped to the Debug command, you are prompted to let the IDE generate an IDE-specific debug target for you in the nbproject/ide-targets.xml file. When you click Generate, the debug-nb target is generated, together with the -load-props, -check-props, -init, and debug-display-browser targets, which support the debug target. The targets are displayed in the Source Editor as follows:

(Note: These targets are not generated in the IDE. Therefore, you need to change the generated code so that it looks as follows.)

    <target name="-load-props">
       <property file="nbproject/project.properties"/>
    </target>
   
    <target name="-check-props">
       <fail unless="session.name"/>
       <fail unless="jpda.host"/>
       <fail unless="jpda.address"/>
       <fail unless="jpda.transport"/>
       <fail unless="web.docbase.dir"/>
       <fail unless="debug.sourcepath"/>
       <fail unless="client.url"/>
    </target>

    <target depends="-load-props, -check-props" name="-init"/>

    <target depends="-init" name="debug-nb" description="Debug Project">
       <nbjpdaconnect address="${jpda.address}" host="${jpda.host}" 
        name="${session.name}" transport="${jpda.transport}">
            <sourcepath>
		<path path="${debug.sourcepath}"/>
            </sourcepath>
       </nbjpdaconnect>
       <antcall target="debug-display-browser"/>
    </target>

    <target name="debug-display-browser">
       <nbbrowse url="${client.url}"/>
    </target>

There's no need for you to customize the generated targets. All you have to do is set the properties that the IDE requires to use the targets it generated. For example, you need to tell the IDE where your application's sources are. To do this, you will set properties in the nbproject/debug.properties file that the IDE created for you when it generated the debug-nb target above. Using the -load-props target above, the IDE will load the properties when you run the debug-nb target

(Note: This file is not generated in the IDE. You need to go to the Files window, expand the project node, right-click the nbproject folder, and choose New > File/Folder. Choose Other > Properties File, name the file debug, and click Finish. In the new debug.properties file, add the following properties.)

  jpda.session.name=MyProject
  jpda.host=localhost

  # Sun Java System Application Server using shared memory (on Windows)
  # jpda.address=localhost4848
  # jpda.transport=dt_shmem

  # Sun Java System Application Server using a socket
  # jpda.address=9009
  # jpda.transport=dt_socket

  # Tomcat using shared memory (on Windows)
   jpda.address=tomcat_shared_memory_id
   jpda.transport=dt_shmem

  # Tomcat using a socket
  #jpda.address=11555
  #jpda.transport=dt_socket

  src.folders=src
  web.docbase.dir=web

  # you can change this property to a list of your source folders
  debug.sourcepath=${src.folders}:${web.docbase.dir}

  # Client URL for Tomcat
  client.url=http://localhost:8084/MyProject

  # Client URL for Sun Java System Application Server 
  # client.url=http://localhost:8080

The table below explains the properties defined above.

Property Value Notes
jpda.session.name The display name given in the Sessions window when you debug the project.
jpda.host The host that the application to be debugged uses to connect to the debugger, such as localhost.
jpda.address The bundled Tomcat Web Server defaults are 11555 for socket connections and tomcat_shared_memory_id for shared memory connections. To set a different address, right-click the Tomcat node in the Runtime window and choose Properties. In the Properties sheet, change the Debugging Port property (for socket connections) or Name property (for shared memory connections). Then close the Properties sheet. Now stop and restart the Tomcat Web Server, if you had already started it.
jpda.transport dt_socket (for socket connections) or shmem (for shared memory connections) To set a different transport, right-click the Tomcat node in the Runtime window and choose Properties. In the Properties sheet, change the Debugging Type. Then close the Properties sheet. Now stop and restart the Tomcat Web Server, if you had already started it.
web.docbase.dir
src.folders
The location of your web root (web.docbase.dir) and Java source files (src.folders). Multiple source roots can be included in the sourcepath by means of the ":" delimiter. Note that the Java source folders must be specified as Source Package Folders in the Java Sources panel of the Project Properties dialog box. (Right click the project, choose Properties, then click Java Sources in the Project Properties dialog box.)
client.url The URL that should be opened in the IDE's default browser, such as http://localhost:8084/MyProject.

For some example values, see the "Debugging the application" section of the Importing Existing Web Applications into NetBeans IDE 5.0 document.

Note that the debug-nb target is automatically mapped to the Debug Project command. However, if you keep this target in a different Ant script, open the project's project.xml file and change the script element in the ide-actions section:

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

Using the Debug Target

Before you can use your debug target, you need to deploy your application. Therefore, start the server and run deploy the application. Note that the first time that you run the application per session, the Tomcat Web Server asks you for a username and password. The only acceptable username and password is that of a user with a "manager" role. This is defined in the conf/tomcat-users.xml file in the Tomcat Web Server's base directory. To identify the location of this directory, right-click the Tomcat Web Server instance node in the Runtime window and select Properties. In the Properties dialog box, the Base Directory property points to the Tomcat Web Server's base directory.

Once the application is deployed, stop the server and restart it in debug mode. The way this is done depends on the server:

Once the server has started in debug mode, choose Run > Debug Main Project (F5). The application is deployed and is attached to the debugger. The debugger stops at the first breakpoint, after which you can step into (F7) or over (F8) the code.

Troubleshooting the Debug Target

Even though the IDE does its best to generate a complete debug target for you, with properties that are tailored to your specific environment, you should always analyze and fine tune the debug process. Work through the questions below when you encounter problems while using an Ant debug target from the NetBeans IDE.

Has the web application been correctly deployed?

Check that the web application has been deployed:

  1. In the Runtime window, expand the Servers node, start the server (if not started), expand the server's instance node, and expand the Web Applications node.
  2. If you do not see your application's context (/MyProject, for the application in this document), it has not been correctly deployed.
  3. Deploy the application.

Are you behind a firewall?

Check that your proxy settings are correct. Depending on your proxy type do the following:

Is the server running in debug mode?

Check that the server has been started in debug mode:

  1. In the Runtime window, expand the Servers node and check that the server is running. Note that even if it is running, it may not be running in debug mode.
  2. If it is not running, right-click it, choose Start/Stop Server, and click Start Server (Debug). If it is running, but you are not sure that it is running in debug mode, stop the server and restart it in debug mode.

Are the server's port and address set correctly?

Check that the jpda.address set in debug.properties matches the server's settings:

  1. Right-click the server's node in the Runtime window and choose Properties.
  2. In the Properties sheet:
    • Check the Debugging Port property (for socket connections). By default, it should be 9009 for the SJS Application Server or 11555 for the Tomcat Web Server.
    • Check the Name property (for shared memory connections). By default, it should be localhost4848 for the SJS Application Server or tomcat_shared_memory_id for the Tomcat Web Server.
    If you change the server's Debugging Port property or Name property, make sure that it matches the related property in the debug.properties file.
  3. Close the Properties sheet and stop and restart the server, if you had already started it.

Check that the jpda.transport set in debug.properties matches the server's settings:

  1. Right-click the server's node in the Runtime window and choose Properties.
  2. In the Properties sheet, check the Debugging Type property:
    • dt_socket for socket connections
    • dt_shmem for shared memory (Windows)
    If you change the server's Debugging Type property, make sure that it matches the related property in the debug.properties file.
  3. Close the Properties sheet and stop and restart the server, if you had already started it.

Unable to step through your code?

If you are unable to step from line to line in your code, but only from breakpoint to breakpoint, the IDE has not been able to find your sources. This is because you have not specified your sources correctly.

Also make sure that the sources are correctly specified in the debug.properties file and in the debug-nb target. Note that if your nbproject folder is not housed within the folder that houses your sources folder, you should set the following properties for your src.folder and web.docbase.folders properties:

Back to top

Creating a Target to Compile a Single File

If you want to be able to select files in the IDE and compile them individually, you need an Ant target for the Compile File command. The IDE offers to generate a target the first time you choose the command. The generated target looks something like this:
 <?xml version="1.0" encoding="UTF-8"?>
<project basedir=".." name="MyProjectName">
    <!-- TODO: edit the following target according to your needs -->
    <!-- (more info: http://www.netbeans.org/kb/freeform-config.html#compilesingle) -->
    <target name="compile-selected-files-in-src">
        <fail unless="files">Must set property 'files'</fail>
        <!-- TODO decide on and define some value for ${build.classes.dir} -->
        <mkdir dir="${build.classes.dir}"/>
        <javac destdir="${build.classes.dir}" includes="${files}" source="1.5" srcdir="src"/>
    </target>
</project>
In the generated target, you need to specify the directory where to put the compiled class or classes. You can do so by specifying a value for the build.classes.dir property in the generated target. For example, you might add the following line to the line above the <target name="compile-selected-files-in-src"> entry:
<property name="build.classes.dir"  value="build"/>

Alternatively, you can replace the value of the provided build.classes.dir or rewrite the target entirely.

The value of the includestt> parameter is the value of the generated files property. The IDE uses this property to store the name of the currently selected file (or files).

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.

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

The IDE does not generate targets for the Run File, Debug File, Test File, and Debug Test for File commands, but you can create your own targets and map them to the following predefined actions:

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.

Running the Selected File

Let's demonstrate how this works when you run a class. A typical target for running a project looks something like the following:

  
    <target name="run2" depends="...">
        <java fork="true" classname="MyMainClass" classpath="MyRunClasspath" />
    </target>
 

The target runs the file specified by classname. To run the currently selected file in the IDE, you need to modify the above target to something like the following:

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

Getting a Reference to the Currently Selected File in the IDE

Once you have an Ant target for running the selected file, you have to get a reference to that file in the IDE and store it in a property. For example, the run-selected-file target above looks for the currently selected file in the runclass property.

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

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

The runclass property is a newly defined property that holds the file that you want to run and is referenced by the java task.

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

<action name="run.single">
      <target>run-selected-file</target>
      <context>
        <property>runclass</property>

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>

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>

Back to top

Writing a Target for the Apply Code Changes Command

The Apply Code Changes 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 Apply Code Changes 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>

To hook this target up to the Apply Code Changes command (the same as the Fix command in previous versions of the IDE), 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>

Back to top


Copyright and Trademark Notice