Sunday, May 15, 2005

Newbee NetBean Module Creation

Update 7/9/2005: Here is the link to running the module stand-alone.
Update 6/17/2005: Thanks to roxie for the comments that helped clean up the broken bits.

The following came about with the help of Charlie Hunt at Sun and Geertjan Wielenga, whose blog contained a series of posts about NetBean Module making for Dummies. The problem, however, was that I was below even the dummy level. So after a series of back and forth question-and-answer emails between the three of us, I was able to come up with a process as well as a series of steps for creating the NetBeans Module and for doing something with it after building the module. What follows is a distillation of that entire process.

It should be noted that it would make life much easier if there were additional support tools inside of Netbeans to take care of a lot of this, especially the hand-jamming of files. Geertjan talks about using Maven along with another NetBeans module. At the very least I certainly wish there were a more intelligent editor for build.xml files. Eclipse has something along those lines for building plug-ins, but I can't say that the Eclipse process is any clearer or easier than Netbeans. But now that I've cracked the code so to speak, I see the lack of such a super tool as an opportunity, not a problem. And so, without further hesitation, I give you:

Building NetBeans Modules for the Complete and Utter Idiot

The primary reason for creating a NetBeans module, or nbm file, is to extend the features and capabilities of the base IDE. The nbm file allows you to do this without having to touch a line of code in the IDE platform. What follows is a documented step-by-step process for the creation of a NetBeans module. There will be a part two showing how to run the module in the stand-along NetBeans Platform.
  1. Download NetBeans 4.1 IDE. http://www.netbeans.info/downloads/download.php?type=4.1
  2. Download the NetBeans 4.1 Platform binary archive. http://www.netbeans.info/downloads/download.php?a=b&p=2 If you want the version for Windows, select "OS Independent" in the drop-down box.
  3. Install NetBeans IDE. Extract the NetBeans Platform into a different directory from the IDE. You will create a plug-in with the NetBeans IDE and load the plug-in the NetBeans Platform. You could also load the plug-in in the NetBeans IDE. But, if you want a "true" NetBeans RCP, then you'll want to install the plug-in in the NetBean Platform. Obviously, this would be different if you would want to develop a plug-in to be with the NetBeans IDE.
  4. Start the NetBeans IDE and prepare to update the IDE from the Update Center. We need to do this to finish installation. It will prepare NetBeans IDE to fully support the rest of this how-to. Updating from the Update Center takes five steps.
    1. From the menu, select Tools | Update Center. The opening dialog allows you to select where to look for updates. The web is the default selection. Keep it, and click Next.
    2. The module needed for this how-to is "Ant Extensions for Open APIs Support." You can select others if you want, but be sure to select the Ant extensions. Press Next.
    3. The next dialog shows the progress of the download.
    4. When the download is finished you are presented with a list of all the modules you selected in Step 1. Click the checkbox under the Global column. When the Question dialog comes up asking if you want to install the modules globally, click the "Yes to All" button. Click every checkbox under the Global column. When done, click the Finish button.
    5. The IDE will install all the modules. When the modules are installed, allow the IDE to restart itself to completely finish installation. After restarting the IDE environment is now ready to continue.
  5. For this example we want to convert the Anagram Game, a sample application in the NetBean IDE, into a plug-in. Start by creating a J2SE Anagrams Game project. On the welcome page click the "Sample Project" button. Alternately, you can create a new project from the File menu: File | New Project | Samples | General | Anagram Game. When you've selected the Anagram game, click Next and Finish on the second step of the dialog.
  6. We need to modify the Anagram source file so that it can be used as a plug-in. Open the Anagrams.java file by double-clicking the file in the File view. When it first opens you'll be in form design mode. Click the Source button and find the two methods exitMenuItemActionPerformed and exitForm (they're close together in the source body). Instead of exiting the application by calling System.exit(0) when you close it, you want to dispose of the plug-in/module when you close it. Therefore replace the code body of these two methods with the following lines of code:
    setVisible(false);
    dispose();
  7. We've made our modifications to existing files. Now it's time to create new content. The first item to create is the Java file ShowAnagramsAction. In the Files tab, expand the src folder down to the anagrams folder, then right click on that folder and select New | File/Folder. When the dialog opens simple select Java Class under File Types, and click the Next button. In step 2 of the dialog file out the dialog as shown here and then click Finish. Creating classes on the File tab at the right level in the source tree keeps typing to a minimum. All you have to do is give it the class name.
  8. The source file is created and opened in a new editor on the right of the IDE. You'll have to add additional code as show next for it to function correctly. Added code is shown in red.
    /*
    * ShowAnagramsAction.java
    *
    * Created on May 12, 2005, 10:30 AM
    */

    package com.toy.anagrams;

    import com.toy.anagrams.ui.Anagrams;


    /**
    *
    * @author wbeebe
    */
    public class ShowAnagramsAction extends CallableSystemAction
    {
    public HelpCtx getHelpCtx()
    {
    return HelpCtx.DEFAULT_HELP;
    }

    public String getName()
    {
    return "Anagrams";
    }

    public void performAction()
    {
    Anagrams
    anagrams = new Anagrams();
    anagrams.setBounds(400, 200, 400, 220);
    anagrams.show();
    }

    public ShowAnagramsAction()
    {
    }
    }

  9. When the edits are finished the file should look like this. Note the red indicators in the left gutter of the editor. In order to remove these reference errors you need to reference the jars that hold these classes and then find and import the classes that contain these definitions. The first step is to add the jars to the project. In the Projects tab on the left, open the Libraries folder. It should be empty. Right click on the Libraries folder and select the Add Jar/Folder dialog. With the dialog you need to add three jar files (you'll need to do this three times): <NetBeansIDE-install-root>/platform5/core/openide.jar, <NetBeansIDE-install-root>/platform5/core/openide-loaders.jar, and <NetBeansIDE-install-root>/nb4.1/ant/extra/nbantext.jar. Once the jars are in the project set the focus on the editor and press the keys [Alt][Shift][F] to fix your imports, or right click in the editor and select Fix Imports from the pop-up menu. When it's finished, the correct imports will have been made like this.
  10. The next item to create is the layer file. This will add an entry to the IDE's menu so that we can execute Anagram module. In the Files tab open up the src folder down to the anagrams folder. Right click on the anagrams folder and select New | Xml Document. The dialog will open at step two. Type in 'resources/layer'. This will create both the resources directory where this file should reside as well as layer.xml. Don't add a file extension, or you'll wind up with layer.xml.xml for a file name. The final dialog asks what type of document. Select well-formed and then click Finish. When the XML editor opens up you'll have a root element to the file. Remove those and replace with the following:

    <!DOCTYPE filesystem
    PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN"
    " http://www.netbeans.org/dtds/filesystem-1_1.dtd">
    <filesystem>
    <folder name="Menu">
    <folder name="Games">
    <file name="com.toy.anagrams.ShowAnagramsAction.instance"/>
    </folder>
    </folder>
    </filesystem>


    When finished, your file should look like this.
  11. The next item to create is the manifest file. Once again, in the File tab, at the top-level anagrams folder, right click and select New | Empty File... The dialog will appear, and you should type in manifest.mf in the file name. Click Finish, and then go over to the manifest.mf editor. Edit the file with the following:
    Manifest-Version: 1.0
    OpenIDE-Module: anagrams/1
    OpenIDE-Module-IDE-Dependencies: IDE/1 > 4.0
    OpenIDE-Module-Layer: com/toy/anagrams/resources/layer.xml
    OpenIDE-Module-Specification-Version: 1.0

  12. At this point we need to stop and modify a properties file. In the Files tab open up anagrams/nbproject/project.properties. Add the following lines at the end of the file and save it.
    manifest.file=manifest.mf
    cluster.dir=anagrams
    modules.dir=${cluster.dir}/modules
    modulexml.dir=${cluster.dir}/config/Modules
    module.name=anagrams
    nb.system.dir=config
  13. We've reached the point where we need to build everything. In order to do this we need to modify the build.xml file. The purpose is to add build targets and actions that will create the necessary NetBeans assets and the final module. Open up the build.xml file and add the following before the end of the closing project tag:
    <target name="create-xml-file-for-module" description="Create XML File.">
    <!-- Create directory for JAR. -->
    <mkdir dir="netbeans/${modules.dir}"/>

    <!-- Create directory for JAR's XML file. -->
    <mkdir dir="netbeans/${modulexml.dir}"/>

    <!-- Copy the JAR after building it. -->
    <copy file="${dist.jar}" todir="netbeans/${modules.dir}"/>

    <!-- Create the XML for the JAR. -->
    <taskdef name="createmodulexml"
    classname="org.netbeans.nbbuild.CreateModuleXML"
    classpath="${javac.classpath}" />
    <createmodulexml xmldir="netbeans/${modulexml.dir}">
    <enabled dir="netbeans/${cluster.dir}">
    <include name="modules/${module.name}.jar"/>
    </enabled>
    </createmodulexml>
    </target>

    <target name="create-nbm" description="Create NBM File.">
    <taskdef name="genlist" classpath="${javac.classpath}"
    classname="org.netbeans.nbbuild.MakeListOfNBM"/>
    <genlist outputfiledir="netbeans/${cluster.dir}"
    module="modules/${module.name}.jar">
    <fileset dir="netbeans/${cluster.dir}">
    <include name="modules/${module.name}.jar"/>
    <include name="config/Modules/${module.name}.xml"/>
    </fileset>
    </genlist>

    <taskdef name="makenbm" classpath="${javac.classpath}"
    classname="org.netbeans.nbbuild.MakeNBM"/>
    <makenbm file="${module.name}.nbm" needsrestart="false"
    productdir="netbeans/${cluster.dir}"
    module="modules/${module.name}.jar"
    homepage="http://www.netbeans.org"
    distribution="http://www.netbeans.org"/>
    <target/>

    <target name="-post-jar" depends="create-xml-file-for-module,create-nbm" />

  14. To make it easier to build our module, a new Ant target was added to the build file. When you include the Ant target "-post-jar", you don't have to run its two dependent targets manually. The NetBeans IDE defines a number of Ant targets as placeholders, which you can fill in with whatever you like. Target post-jar, for example, is automatically run after a project is built (which means that the JAR is available and the JAR is what you need when creating the NBM plug-in/module).
  15. Now you are ready to build the project. Right-click the project in the Projects window and choose Build Project. Check that the build messages are the same as here. The messages will be at the bottom of the IDE in the output section. Note that the anagram.nbm file is now in the Files section. Congratulations! You've got an nbm file!

Next: Running Our Module in the NetBeans Platform