Tuesday May 31, 2005

Ant-Prompted Deployment from NetBeans IDE 4.1

Yesterday I found CoolBoy's blog, with an extremely interesting entry called "On the fly" deployment under NetBeans. Before coming across that blog entry, I never knew that Ant has its own input handler, as well as one or two conditional tags. So, using the input handler and the conditional tags, this is the dialog box that appears when I choose "Run Project" in a free-form project's contextual menu:

In standard projects, I could add the target that creates the above dialog box to the -post-dist target, as demonstrated in previous blog entries.

This is the Ant target that creates the dialog box and sets a property depending on which server I select:

<target name="Select-a-Server" description="Select One of 5 Servers">

  <input message="Where do you want to deploy to?"
          validargs="JBoss,Tomcat,SJS Application Server,WebLogic,WebSphere" 
        addproperty="server.name"
       defaultvalue="SJS Application Server"/> 
         
  <condition property="choose.JBoss">
       <equals arg1="JBoss" arg2="${server.name}"/>
  </condition>
         
  <condition property="choose.Tomcat">
       <equals arg1="Tomcat" arg2="${server.name}"/>
  </condition>
       
  <condition property="choose.SJS">
       <equals arg1="SJS Application Server" arg2="${server.name}"/>
  </condition>
         
  <condition property="choose.WebLogic">
       <equals arg1="WebLogic" arg2="${server.name}"/>
  </condition>
       
  <condition property="choose.WebSphere">
       <equals arg1="WebSphere" arg2="${server.name}"/>
  </condition>
                            
</target>
And here are two of the five targets for deployment, based on whether a property has been set or not. For example, if the choose.JBoss property is set in the previous target, then -- and only then -- will the Copy-to-JBoss target below be executed. This is all thanks to the if="choose.JBoss" attribute in the target declaration:

<target name="Copy-to-JBoss" depends="Select-a-Server" if="choose.JBoss" description="JBoss">
            
  <copy file="${dist.home}/${app.name}-${app.version}.war" todir="${build.dir.jboss}"/>
      
</target>
      
<target name="Copy-to-Tomcat" depends="Select-a-Server" if="choose.Tomcat" description="Tomcat">
            
  <copy file="${dist.home}/${app.name}-${app.version}.war" todir="${build.dir.tomcat4}"/>
      
</target>

Finally, to create a single target that bundles the targets above together -- so that they can all be invoked from the same menu item in a free-form project (or as part of the -post-dist target in standard projects) -- the following needs to be added:

<target name="Deploy" depends="Copy-to-Tomcat,Copy-to-JBoss" description="Deploy"/>

That's it. Of course, I haven't added the targets above to the current project's build.xml, but to a project-independent build.xml, which I import into the build.xml of any project that needs it. I think its all pretty cool because this way the same WAR file can be deployed wherever I want, based on a choice I make when prompted by Ant. And everything is invoked from one single menu item in NetBeans IDE 4.1. Or, I can just press F6 to invoke the dialog box. So now, when I set up the IDE as described in a recent blog entry, I just press F6 whenever I want to deploy, I choose my server from the input handler, and then I can view the result in the Favorites window right away (click to enlarge):

You could even go a step further -- append one extra statement to the Copy-to-XXX target and then you'll launch the IDE's default browser and open the deployed application in it. For example, for JBoss, you'd use a target as simple as the following:

<target name="Copy-to-JBoss" depends="Select-a-Server" if="choose.JBoss" description="JBoss">
            
  <copy file="${dist.home}/${app.name}-${app.version}.war" todir="${build.dir.jboss}"/>
  <nbbrowse url="http://localhost:${port.number.jboss}/${app.name}-${app.version}"/>
      
</target>

So, the above target is invoked as soon as you select 'JBoss' in Ant's input handler. And, as soon as you've deployed the application to JBoss, you can just go down the list in the input handler and deploy the same WAR file to another server. Each time, you'd see the result straight away because the browser is launched and the application is displayed. Ant rocks. So does NetBeans IDE. Thanks, CoolBoy, for your great tip.

Monday May 30, 2005

Create File Templates for NetBeans Module Development

There are several files that I've been creating over and over each time I make a new NetBeans Module. It's been slowing things down and been a little bit frustrating as well. I don't want to wait for the next NetBeans IDE release -- which will simplify module development in various ways -- so, instead, I've created a module that installs module-related templates in the New File wizard, as illustrated below (click to enlarge):

The key to templates is, as almost always with NetBeans Modules, the magical layer.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.0//EN" 
"http://www.netbeans.org/dtds/filesystem-1_0.dtd">
<filesystem>
  <folder name="Templates">
    <folder name="NetBeans Module Support">
      <file name="Action.java" url="../templates/Action.template">
        <attr name="template" boolvalue="true"/>
        <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.nbmtemplates.Bundle"/>
        <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/netbeans/modules/nbmtemplates/resources/class.gif"/>
        <attr name="templateWizardIterator" methodvalue="org.netbeans.modules.java.ui.wizard.JavaWizardIterator.singleton" />
        <attr name="templateWizardURL" urlvalue="nbresloc:/org/netbeans/modules/nbmtemplates/descriptions/DescForActionTemplate.html"/>
      </file>
   </folder>
  </folder>
</filesystem>

The above layer.xml file creates the category "NetBeans Module Support" in the New File wizard, with the file type "Action.java". Very importantly, I don't want my template to be blank. The only reason I will choose to create the Action.java template is because, unlike the normal Java Class file, it subclasses CallableSystemAction. Hence, after naming my template Action.java, I include a url attribute that points to the content of my template (which is created from an Empty File template in the New File wizard's Other category):

/\*
 \* __NAME__.java
 \*
 \* Created on __DATE__, __TIME__
 \*
 \* To change this template, choose Tools | Options and locate the template under
 \* the Source Creation and Management node. Right-click the template and choose
 \* Open. You can then make changes to the template in the Source Editor.
 \*/

package Templates.Classes;

/\*\*
 \*
 \* @author __USER__
 \*/

//TODO: Import packages from Open API Support (available in Update Center).

public class Class extends CallableSystemAction {

//TODO: Replace body of HelpCtx() with your own code.
    
    public HelpCtx getHelpCtx() {
        return HelpCtx.DEFAULT_HELP;
    }
    
//TODO: Replace body of getName() with your own code.

    public String getName() {
        return "Start Test";
    }
    
//TODO: Replace body of performAction() with your own code.

    public void performAction() {
        String msg = "Test succeeded...";
        JOptionPane.showMessageDialog(null,msg);
    }
}

As you can see, I've not only included all the methods that are required by a class that subclasses CallableSystemAction, but I've also added some sample code. This gives me an idea of what should go in the body of the methods -- and, thanks to the TODO comments, I know that the bodies should be replaced by my own code. Most importantly, the first TODO tells me to get the required JAR files for NetBeans Module development -- the Open API JARs that I can get from the Update Center. Importantly, when I create a template, the Class , User, Date, and Time in the template above will be replaced by my own settings and values.

In addition to the content of the template, the entries in the layer.xml file allow me to specify supporting files, such as an icon, an HTML file that contains the description displayed in the New File wizard's Description area (at the bottom of the New File wizard), and the location of the localizing bundle for the template's label.

So, at the end of the day, when you add templates for other classes that you frequently need in NetBeans Module development, this is the structure of the file templates module for NetBeans Modules (click to enlarge):

As shown above, you can even add a template for the manifest.mf file and the layer.xml file. It's kind of funny to add a template for the layer.xml file, because you're installing the template in the New File wizard via another layer.xml file. Anyway, I think it's all pretty cool and not all that difficult to set up.

Sunday May 29, 2005

Easy Extension of a Node's Functionality in NetBeans IDE 4.1

I've found that it's really easy to extend a node's functionality. Starting with the System Properties sample (which is a module that I created and installed in the IDE's Runtime window as outlined here), it takes three easy steps to add a new menu to the parent node. Let's say, for example, that I want to create a new menu item called "My Own Action", as shown below:

To get the above menu item, I just need to do three things:

  1. Create MyOwnAction.java and subclass CallableSystemAction. Here you see an illustration that includes the new MyOwnAction.java:

  2. In AllPropsNode.java, modify getActions() to add an instance of MyOwnAction.class:

    public SystemAction[] getActions(boolean context) {
      return new SystemAction[] {
          SystemAction.get(MyOwnAction.class),
          null,
          SystemAction.get(RefreshPropsAction.class),
          null,
          SystemAction.get(OpenLocalExplorerAction.class),
          null,
          SystemAction.get(NewAction.class),
          null,
          SystemAction.get(ToolsAction.class),
          SystemAction.get(PropertiesAction.class),
      };
    }

  3. If MyOwnAction.java refers to Bundle.properties, add a localizing tag to Bundle.properties:

    LBL_MyOwnAction=My Own Action

    For example, getName() in MyOwnAction.java is probably as follows:

    public String getName() {
      return NbBundle.getBundle(RefreshPropsAction.class).getString("LBL_MyOwnAction");
    }

That's it. Now you can rebuild and reload the module. You've extended the node's functionality by adding a new menu item. It's a lot less painful than I would have thought.

Saturday May 28, 2005

Adding Nodes to the NetBeans IDE's Runtime Window

Using a sample I found on-line in an old (very very old) document, I achieved something that I've been hoping to achieve ever since I started learning about NetBeans Modules: I added some nodes to the IDE's Runtime window. And, finally, I have a working sample that I can play with and learn from, specifically in relation to the Nodes API. Here's the evidence:

The sample is actually pretty useful (i.e., it goes way beyond the 'Hello World' type examples that I've been building so far). It creates a node with a very large number of subnodes, each labeled according to a key for specific Java properties. It even lets me add new properties and modify existing ones. Because the sample was so old, several of the methods have been deprecated. However, fortunately, there's a very helpful Upgrade Guide, which told me how to replace TopManager and that a module is installed in the Runtime window via the following entry in the layer.xml (instead of via entries in manifest.mf, which is how you used to have to install a module in the Runtime window):

<folder name="UI">
    <folder name="Runtime">
       <file name="org.netbeans.modules.sysprops.AllPropsNode.instance">     
          <attr name="instanceClass" 
         stringvalue="org.netbeans.modules.sysprops.AllPropsNode"/>
       </file>
    </folder>
</folder>

And, by the way, this is the structure of my module in the Projects window:

(It's a pity that the Projects window doesn't display the files in the top-level directory, because that means that the Projects window doesn't display my manifest.mf file as well as the sysprops.nbm file -- i.e., the NetBeans Module itself -- which means I have to keep switching to the Files window whenever I want to modify the manifest.mf file or delete the NetBeans Module. I should probably add the module to the clean target, but in such a way that the manifest.mf isn't included. Still, it would be nice to be able to see the top-level directory in the Projects window.)

Now that I've got this working sample, I can play around with it and really begin to understand how each part works. I'll be blogging more about this sample and the Nodes API in the coming weeks.

Friday May 27, 2005

Who Found My Blog This Month?

Last month, in Lucky You: No Deleting of Projects in NetBeans IDE 4.1, I listed some of the queries that people who found my blog had typed into search engines. Here is another list of random queries, this time from the past few weeks:

  • jboss and reference
  • JBOSS IDE in NetBeans
  • netbeans jboss
  • how to use connection pooling in JBOSS
  • eclipse remote debugger misses breakpoints
  • maven webdoclet jbosswebxml
  • default tomcat password "netbeans 4.1"
  • change ide default password ide manager tomcat
  • orion netbeans
  • knowing jboss status
  • maven repository tld
  • how to make our context as the default one in Tomcat 5.5.7
  • netbeans 4.1 adding Tomcat Admin tool
  • tomcat4 server plugin for netbeans
  • JBoss plugin, netbeans
  • debugging in netbeans
  • howto jboss connection pooling
  • how to delete projects in netbeans
  • netbeans module development tutorial
  • taskdef class org.NetBeans.nbbuild.CreateModuleXML cannot be found
  • all jsp files syntax checking compilation
  • delete project in netbeans ide
  • JBOSS Connection Pooling
  • netbeans tomcat-users.xml
  • compile jsp file
  • what does localhost:8084 mean?

So, every now and again I've been checking my referers. Based on my occasional checks, I'd say that the following three things are the the most frequently searched-for issues in relation to NetBeans IDE: (a) how to delete projects, (b) how to set the Tomcat Manager's password, (c) how to work with JBoss from NetBeans.

And this month's award for the "Most Disappointed Searcher" is a tie. The prize is shared between the person who found my blog after typing "demi moore right click download" and someone else who (today!) stumbled across my blog after typing "demi moore work out". If they make themselves known by leaving a comment at the end of this blog entry, I'll send them a picture of Demi Moore.

Thursday May 26, 2005

Baking a First Cookie for a NetBeans Module's Data Object

In Adding an Item to a File's Pop-Up Menu in NetBeans IDE 4.1 I learnt, well, exactly what's described in the title of that blog entry. However, what I didn't mention is that the Open item, the View item, and the Edit item were disabled. So, while I was able to use the Cut and the Paste items, I wasn't able to open the HTML file, to view it, or to edit it. Cutting and pasting are standard actions -- there's only one conceivable reason why you'd choose those items; this is not the case for Open, Edit, and View. There are different ways of viewing and different editors in which you'd maybe like to open and edit a file. Hence, you need to tell the IDE (or the Platform) exactly what should happen when these items are chosen. For this reason, they're disabled by default (click the enlarge):

To enable them, you need to create a cookie. In the context of NetBeans Modules, a cookie has nothing to do with the message sent from a web server to a web browser. It's a completely different concept. (I don't know why it's the same word, but there are probably entirely logical historical reasons for it.) Reading and browsing through various documents, I've come across the following handy definition of what a cookie is: "Cookies are design patterns that you attach to a data object or a node to add functionality to the data object or the node. Cookies provide information to the the IDE or Platform about the types of operations that data objects or nodes are capable of supporting."

There are various ways to create cookies. The simplest (and hence the one that I'm most drawn to!) is to modify the data object by providing an ad-hoc implementation of a cookie interface (such as OpenCookie, ViewCookie, or EditCookie) and adding it to the CookieSet instance. So, it's best to show this in a screenshot:

As can be seen in the above screenshot, the OpenCookie interface has been implemented and added to the CookieSet instance. As a result (after rebuilding and reloading the module) the Open item is now enabled. Nothing can be done with it yet (it currently provides a JoptionPane with the text "Open Sesame!") but at least the item is now enabled. And... I've finally managed to bake my first cookie!

Tuesday May 24, 2005

Quickly Navigate through the NetBeans IDE Source Editor

One way of dealing with a cluttered Source Editor is to unclutter it. Another way is to keep the clutter but navigate through it more efficiently. (Kind of like not cleaning your room, but working out how to make the mess work to your advantage.) Not sure if the whole NetBeans world knows about this, but if you click the Tab key while holding down the Ctrl key in the Source Editor, NetBeans gives you a little list containing all the open documents:

You can navigate through this list by holding down the Ctrl key while clicking the Tab key through the list. When you release the Ctrl key, the last document selected in the list opens in the Source Editor. Reading through this cool article about Mac OS X, Mac users seem to need to use the mouse wheel to get the same functionality.

Monday May 23, 2005

Docking a NetBeans Module in the IDE (Part 4)

In Docking a NetBeans Module in the IDE (Part 2), I listed the files that are necessary for docking a NetBeans Module. Now, in this blog entry, here is some actual sample code as well. This sample code turns the Anagrams sample, available in the IDE when you click Ctrl-Shift-N and go to the Samples category, into a NetBeans Module that can be docked in one of the IDE's (or the Platform's) modes. (Don't know what "docking" means and how it can make your module fit really snugly in the IDE or Platform? Click here for a little bit of background.) The structure of the module should be as illustrated below (click to enlarge):

Note that the build and dist folders in the illustration above are generated when you build the application. The netbeans folder and the .nbm file are generated when you build the module. Targets for all of these activities are provided in the build.xml referred to below.

So, here is the list of files needed, but this time with a link to a file containing the code in question:

On top of that, you need to change Anagrams.java because the Anagrams sample wasn't made to be a dockable NetBeans Module. So, there are a few things that don't work within the context of a dockable NetBeans Module. For example, the sample extends JFrame, and it has a menubar, which are not things that you'd find in modules that are dockable. For example, look at the Projects window -- a tree hierarchy is used there. The Output window just has a big text field. So, click here to get the restructured Anagrams.java file.

Finally, you need a build.xml file that contains the Ant scripts used for creating and loading the NetBeans module. Click here to get the build.xml file generated by the IDE for standard projects, together with the relevant Ant targets. Note that it imports nbproject/build-impl.xml, which you can get for yourself by creating a new web application from scratch. (You also need some module-specific properties in a project.properties file, so click here to get it.)

That's it. Now you have everything you need to transform the Anagrams sample into a dockable NetBeans Module. Take a look at Docking a NetBeans Module in the IDE (Part 3) for some of the possibilities.

Sunday May 22, 2005

Orion Server and NetBeans IDE 4.1

Now that there are server plugins available for JBoss, WebLogic, and WebSphere, there's not really much point in using Ant to start a server. After all, virtually every popular server is somehow already integrated in the IDE and, in addition to the functionality offered by the abovementioned plugins, the IDE comes bundled with the Sun Java System Application Server 8.1 and Tomcat Web Server 5.5.7. So there's no point in Ant-based server deployment. Right? Wrong. First of all, if you're familiar with Ant you might still be inclined to want to start servers via Ant scripts, even though they're also available as plugins. And there's nothing to stop you. Secondly, however, only one version of a server is supported in the IDE, either via bundling or plugins. (Note that in Tomcat's case two versions ae supported in 4.1 -- 5.0 and 5.5). Thirdly, there are several cool server vendors that are currently not supported via plugins in the IDE. One of them is JRun (discussed in detail elsewhere in this blog). Another is the Orion Server, which is an application server made in Sweden.

Currently I know almost nothing about Orion. (One thing I do know is that they have great documentation -- their information on data sources and tag libraries, for example, is very very detailed and extensive.) However, according to their website, the following things are a few of the "many things" that "sets Orion apart from other application servers":

  • Superb performance. Orion is easily the fastest J2EE-based Aplication Server
  • Orion was the first commercially available application server with full J2EE support
  • Unique development features like auto-deploy and full hot-swap.
  • Very affordable pricing

(One can question the first point -- seems like a matter of opinion to me and quite hard to prove on top of that. The second point is a bit of a turn-off when you consider how many free application servers are currently available. On top of that, "auto-deploy" isn't really unique at all -- every server that I know of supports that. Not sure what "full hot-swap" means, but I wonder whether it's not just as unique as auto-deploy. In fact, while something can be said about each of the things that "sets Orion apart from other servers", something else that sets it apart is that it isn't J2EE 1.4 compliant -- they're on J2EE 1.3.)

Integrating the Orion Server in NetBeans IDE 4.1 doesn't require much knowledge of the Orion Server. I only need to know how to work with it from Ant -- and once I know that, integration is a piece of cake because NetBeans IDE 4.1 provides shortcuts (like menu items, toolbar buttons, and keyboard shortcuts) to Ant scripts. So, this is how I start the Orion Server:

<target name="Start-Serv-Orion">
  <java jar="c:\\orion\\orion\\orion.jar" fork="true" dir="c:\\orion\\orion" /> 
</target>

And this is how I invoke the Server Console:

<target name="Start-Serv-Orion">
 <java jar="c:\\orion\\orion\\orion.jar" fork="true" dir="c:\\orion\\orion" >
    <arg value="-console"/>   
 </java> 
</target>

When I create a new web application in the IDE, I get a build.xml file for free. This build.xml file contains Ant scripts. I just need to add the above targets to the Ant scripts (I'd probably change all the variables in the scripts above to properties) and then, when I right-click on a target's node in the Files window, I can assign menu items, toolbar buttons, and keyboard shortcuts. For example, I could add the menu items to a menu that is dedicated to Orion:

(Have a look at the Ant script in the illustration above. You see syntax highlighting. What you don't see is code completion. So even if you don't know Ant (on top of not knowing Orion), when you press Ctrl-Space in the IDE, you'll get some suggestions for what to add to the target.)

Once these things have been set up, I can deploy to the Orion Server, either by drag-and-dropping my application's output (WAR or EAR or whatever) into the Favorites window or by using an Ant script:

<target name="orion-deploy" description="Deploy to Orion">
      <copy file="${dist.dir}/${jar.name}" todir="${orion.deploy.dir}"/>
</target>

The above target could be hooked up to a free-form project so that it appears in its right-click contextual menu. For standard projects, it could be included in the -post-jar target so that it runs as soon as the JAR file has completed building. Furthermore, I can set up the debugger to step through code on the Orion Server, I can set up the HTTP Monitor to analyze HTTP requests on the Orion Server, and the Orion Server will behave exactly as if it had been "officially" supported by NetBeans IDE 4.1. That says as much for the power of NetBeans IDE 4.1 as it does for Ant -- which is why they really complement each other very well. In short, every conceivable server vendor is supported by the IDE, because the IDE is so well-integrated with Ant.

Saturday May 21, 2005

Adding an Item to a File's Pop-Up Menu in NetBeans IDE 4.1

In Playing with File Types in NetBeans IDE 4.1, I learnt how to create a module that identifies a file by its extension. In that particular blog entry, the module I ended up with was able to distinguish between different JSP Objects. By default, the IDE lumps tag files and JSP files together as "JSP Objects". My module made a distinction between them and proved it by showing a different icon and menu selection for tag files. However, the menu selection was provided by the org.openide.actions package. In other words, the menu items were predefined. This is what the relevant part of my TagExtensionsDataNode class looked like:

public Action[] getActions(boolean context) {
 Action[] result = new Action[] {
    SystemAction.get(EditAction.class),
    SystemAction.get(CutAction.class),
    SystemAction.get(CopyAction.class),
    SystemAction.get(RenameAction.class),
    SystemAction.get(DeleteAction.class),
 };
 return result;
}
And the following are some of the import statements that were included at the top of the file:

import org.openide.actions.CopyAction;
import org.openide.actions.CutAction;
import org.openide.actions.DeleteAction;
import org.openide.actions.EditAction;
import org.openide.actions.RenameAction;

So, clearly, these were all predefined menu items. What if I wanted to add my own menu item? For example, I'd like to -- at some stage -- be able to add a menu item that adds XDoclet tags to a tag handler. I'd also like to be able to open an HTML file in DreamWeaver. Well, to those ends, I've worked out what is probably pretty much the simplest implementation of a menu item (it is found within the class that extends DataNode):

private final class TestAction extends AbstractAction {
        
 private final DataObject obj;
       
 public TestAction(DataObject obj) {
   this.obj = obj;
   putValue(Action.NAME, "Send a Greeting to the World");
 }
        
 public void actionPerformed(ActionEvent ae) {
   String msg = "Hello World!";
   JOptionPane.showMessageDialog(null,msg);
 }
}

From the above, you can see that the menu item will be named "Send a Greeting to the World" and that, when you click it, the highly original greeting "Hello World!" will appear in a JOptionPane. To include an instance of TestAction in my menu selection, I would add it to the existing menu items as follows (note that the null, represents a separator in the menu):

public Action[] getActions(boolean context) {
 Action[] result = new Action[] {
    SystemAction.get(EditAction.class),
    SystemAction.get(CutAction.class),
    SystemAction.get(CopyAction.class),
    SystemAction.get(RenameAction.class),
    SystemAction.get(DeleteAction.class),
    null,
    new TestAction(getDataObject()),
 };
 return result;
}

I've changed the DataLoader that I created in Playing with File Types in NetBeans IDE 4.1 so that HTML files are recognized (instead of tag files). Having made the changes above (i.e., added an implementation of a menu item and then added an instance of it to the getActions() method), I rebuilt the module and ended up with the following when right-clicking an HTML file in the IDE:

Note that, to make it all work, you need to override the HTML object type's org.netbeans.modules.html.HtmlDataObject representation class, in the same way that you overrode the JSP object's representation class (i.e., in the manifest.mf file) in Playing with File Types in NetBeans IDE 4.1. This means that if you -- like me -- don't provide an icon in the class that extends DataNode, you'll end up -- just like me -- with an HTML file that doesn't have an icon.

For more in depth information on this subject, see Tim Boudreau's Module Building: Module Coupling - Implementing SetMainFileAction.

Thursday May 19, 2005

Docking a NetBeans Module in the IDE (Part 3)

To "dock" a module means embedding it in one of the IDE's (or the Platform's) modes. There are several modes to chose from. For example, by default the Favorites window's module (org.netbeans.modules.favorites) is docked in the 'Explorer' mode. This mode is on the left side of the IDE where the Projects window and Files window are displayed by default. Each module can have an opened state of 'true' or 'false'. By default, the Favorites window, for example, has an opened state of 'false', so that by default it is not displayed when you open the IDE. The modes and their modules' settings are stored in the IDE's user directory. By default, you should have the following modes:

Within each of the subfolders within the 'Modes' folder above, a reference file is found for every module that is docked in the mode. For example, the reference file for the Favorites module is found in the 'explorer' folder above. These reference files have a .wstcref extension. This stands for Windows System Top Component Reference. For example, this is the complete content of the favorites.wstcref file:

<?xml version="1.0" encoding="UTF-8"?>
<tc-ref version="2.1">
    <module name="org.netbeans.modules.favorites/1" spec="1.1" />
    <tc-id id="favorites" />
    <state opened="false" />
</tc-ref>

The effect of docking a module can best be described visually. Below is the Anagrams module created over the last few blog entries, but -- unlike previous blog entries -- it can now be docked in various modes in the IDE (click to enlarge each of the screenshots below).

Explorer mode:

Editor mode:

Output mode:

Properties mode:

Navigator mode:

Many thanks to Petr Blaha for restructuring the Anagrams sample so that it works as a docked module. Next blog entries will talk about this as well as step-by-step instructions for putting everything together.

Wednesday May 18, 2005

Interesting Conversations at the NetBeans IDE 4.1 Release Party

Last night was the NetBeans IDE 4.1 Release Party. It was held at a bobsled track here in Prague. I arrived quite late and never got to try the bobsled (okay, so maybe I was chicken) but I can report that the beer was excellent. Even more excellent were all the fascinating conversations I had about NetBeans -- with the actual people who make NetBeans. Apart from the fact that I met several people for the first time (including a few who work in the same building, who I've e-mailed with on a regular basis, but who I'd never actually met), the things we talked about were truly cool. In between, I jotted down some notes on the back of a beermat (disappointingly, the backs of Czech beermats are not white, like they are in Holland, where I'm from, so I had to write across a Budweiser advertisement). By the way, I'm not sure whether the 'correct' word is 'beermat' or 'beer mat' (I've also heard it being called a 'beer filter') but I guess that's not really relevant. So anyway, here are my notes, exactly as written on my beermat (and more or less in the order that I wrote them), together with some notes to explain them:

  • code Java in mobile phone. While walking from the bobsled track to the next pub, I had a really interesting conversation with John Treacy about Mobility (i.e. J2ME MIDP Development in NetBeans IDE). (By the way, John Treacy is something like the main architect in the Mobility area.) There were actually two things that came out of that little talk, for me:

    1. NetBeans for Pubcrawlers. Just imagine you're sitting in the pub and you suddenly think 'Is my server running?' How cool would it be if you could press a button on your mobile phone that would check the status of the server and display a text saying 'Running' or 'Stopped'? I think that would be pretty cool and completely doable. It just means combining the Mobility pack with NetBeans IDE. You could even start/stop a server from your mobile phone.
    2. It would be pretty cool if I could do some coding while on the way to work, sitting in the metro. Sure, as John pointed out, the display is small and that would inhibit your programming. But what if we made the font really really small and provided a big bunch of templates? You wouldn't necessarily be making big applications, but you could test a few things out, right? Anyway, I think it could be a cool thing.
  • minimum project.xml for Mevenide. I met Milos Kleint for the first time! He was really cool and we had interesting conversations throughout the evening about Mevenide. (Milos is something like the main architect for Mevenide.) I pointed out to him that the only reason I hadn't been using Mevenide in my blog (as much as I had first thought) is because I've been working on transforming existing J2SE applications into modules. These existing J2SE applications do not have their own POM (a Mavenized project.xml file), so I can't open them in Mevenide and so I haven't been using Mevenide at all -- because Mevenide assumes that you already have a POM. But Milos pointed out that one could create a "minimum project.xml file". This minimum file would have only a few details, like the name of the project etc., and you could then just drop it into your application's root directory. And then you should be able to open a J2SE application in Mevenide. Once you've done that, you can just run the Maven commands in the IDE and quickly create your module. However, what I don't like about Mevenide (and Maven), which I also talked about to Milos, is that you don't know what's going on when you run Maven goals (a "goal" is the Maven term for what a "target" is in Ant). Everything is "under the hood" in Maven. No thinking. (That's why it's really a methodology for people who don't want to think about the build-side of their module -- they just want to build.) Anyway, so what I want to do is work out what that minimum project.xml file consists of.
  • Mevenide 0.7. Not out yet, but coming soon. I heard this from the source -- i.e., Milos himself! Exciting stuff.
  • Ant script for branding. One of the first conversations I had last night was with Charles Beckham (he's something like the main project manager for Java Enterprise Tools). He had a cool idea for some kind of Ant script that would pull out all product-specific texts in the IDE (like titles in dialog boxes etc.) and replace them with something else. Since the IDE is built from an Ant script, this shouldn't be hard to do -- assuming that the IDE is really normalized so that this is possible. It's an interesting idea anyway. It would mean hooking up some Ant scripts to the existing script that builds the IDE and then, when running the script, everything would be rebranded for whatever product is being built from the IDE's sources.
  • Software architecture for NBMS. Charlie Hunt (a NetBeans evangelist) has been a great source of information for me recently -- also, NetBeans user William Beebe seems to have profited from his input a week or so ago and wrote Building NetBeans Modules for the Complete and Utter Idiot. I asked Charlie what he'll be working on in the coming period and he said 'software architecture for NetBeans Modules'. That sounds really cool. Not sure my interpretation of the term is the same as his, but it got me thinking about 'what are the basic things needed for a module'? (Yesterday's blog entry goes into this for just one of the API's, but each API should have a basic set of 'things' needed for it.) It also got me thinking about this -- how cool would it be if the IDE provided a sample for each API? Or, better still, two samples per API: one sample that is the simplest possible implementation of the API (for beginners) and another that shows a really advanced implementation of the API. For example, there'd be a simple application that extends TopComponent. This application would dock a 'Hello World' message somewhere in the IDE. That's all. Then there'd be another sample for TopComponent that stretches the API to it's most extreme point so that more advanced users can be inspired to think about other implementations of the API for themselves. And, of course, all the samples would be documented very clearly, simply, and directly. A final point on NBMs: I've realized, from teaching myself about NBMs recently, that there is more documentation on NBMs than on any other area of NetBeans. The only problem is that it is scattered and disjointed. But it's there. It really is.
  • XDoclet for all servers, then deploy to all servers. Now that Weblogic, WebSphere, and JBoss are all available as plug-ins, it shouldn't be difficult at all to write Ant scripts (1) that use XDoclet to generate server-specific deployment descriptors (such as jboss-web.xml) and (2) that copy the resulting WAR or EAR file to each of the servers' autodeploy directories. (By the way, Ludo Champenois -- the J2EE Engineering Manager -- told me some interesting things about Annotations in relation to XDoclet. That's definitely something I want to look into.) Once the application is in each server's autodeploy directory, they are automatically deployed by the server in question. And then there'd be an Ant script that opens 5 browsers, each pointing to the URL (which would be the same for each, except for the port number) of the server in question. I remember talking to somebody last night (I think it was the NetBeans evangelist Brian Leonard) about the recent trip of several evangelists to Brazil, after which Charlie Hunt wrote a report that says that people down there are testing J2EE 1.4 compliance by deploying to both the Sun Java System Application Server and to JBoss. (And this is the reason why they wanted NetBeans IDE to support JBoss.) Charlie pointed out to them that the Verifier tool (which is integrated into NetBeans IDE 4.1) has exactly that function -- it tells you whether your application is J2EE 1.4 compliant or not. However, seeing is believing, right? People want to see that their application is portable, they want to see that it runs on any J2EE 1.4 compliant server. So that's exactly why these Ant scripts would be so useful. (But there's another reason, and that's the next bullet in this list.)
  • The wow effect. While talking to Brian, Milos, and Patrick Keegan (the principal author of NetBeans IDE Field Guide) about the above scenario, Milos used the term "the wow effect". That's really cool and exactly what the above bullet is all about -- okay, so you can use the Verifier to test J2EE 1.4 compliance. That's all you should need. But it's just cool to be able to deploy to 5 servers simultaneously (all from the Deploy Project menu item, bacause all the above Ant scripts would be hooked up to the web application's version of the J2SE -post-jar target in standard projects or to a project-level menu item in free-form projects). The "wow effect" is really important -- regardless of whether anyone is actually going to use it, it's just cool to know that you are able to... (And all thanks to Ant integration in NetBeans IDE 4.x!)

  • Server plugins as education. Anyone learning about NetBeans Modules (see previous blog entries on this subject) should check out (in both senses of the term) the sources of the new plugins for WebLogic, WebSphere, and JBoss. Then compare the sources and look at what's common to them and what's different. Look at the layer file, for example. Install the plugins and look at how everything looks in the IDE and then go back to the layer file and see what impact each of the entries has. Also look at the Action classes. Also (this is what I am most interested in right now) look at how the server is started. There's something going on there with Cookies that I want to learn about. In short, those plugins are fantastic learning opportunities.

Apart from the above things, I had a lot of other interesting conversations. For example, I met Roumen for the first time (even though he works two floors above me)! He's so enthusiastic about NetBeans. And his blog is fantastic. (Also, see the current 'Spotlight Feature' on Javalobby.) Also, Brian Leonard (who I first learnt about after reading this great article) had some interesting things to say about his eBay article as well as pointing out (it seemed like a confession!) that the JBoss deployment descriptors in his Integrating NetBeans with other J2EE Server Vendors aren't actually needed. I'd kind of guessed that (and that's why I wrote Easy JBoss Connection Pooling with NetBeans IDE 4.1 and XDoclet) because you only need server-specific deployment descriptors when you're dealing with server-specific things like connection pools and CMP beans. At least, that's the case with JBoss. Defaults are provided, which means that JBoss will deploy an application that has descriptors for Tomcat or the Sun Java System Application Server (or anything else), except when its own resources (e.g., connection pools) are needed. That's when you need deployment descriptors like jboss-web.xml.

So, anyway, that release party was a very productive time and I'll be blogging about some or all of the above points in the coming weeks and months.

Docking a NetBeans Module in the IDE (Part 2)

I've been working on docking the Anagrams module that I created in NetBeans Modules for Dummies (Part 6). When docking a module, the following files are necessary:
  • A Java class that extends TopComponent
  • A Java class that extends CallableSystemAction
  • A layer file (.xml extension)
  • A manifest file (.mf extension)
  • A mode settings file (.settings extension)
  • A windows system top component reference file (.wstcref extension)

On top of that, there's also got to be some way to actually build the module. For that, I'm using the Ant scripts referred to in previous blog entries. So this is what everything looks like when fitted together in the IDE:

Of course, Rich Unger's FeedReader, A NetBeans Platform Sample and Tutorial is the document which goes into this whole area in quite a lot of detail. In fact, that document is the only tutorial currently available (as far as I'm aware anyway) on this topic. And so that's the document that I've been working through, together with this document that I referred to yesterday.

Tuesday May 17, 2005

Docking a NetBeans Module in the IDE (Part 1)

My first skirmishes with org.openide.windows.TopComponent have been quite fruitful. At least now, for the first time, I have managed to dock a module into the IDE's Properties mode. Here's the evidence (click to enlarge):

I've found this technical document quite helpful. It describes the Windows API -- including topics such as "TopComponent", "Docking", and "Modes". NetBeans developer Petr Blaha has been very helpful too (he provided the basis of the sample and a lot of guidance). Thanks Petr! I intend to experiment with this API a lot more.

Sunday May 15, 2005

Plug JBoss, WebLogic, and WebSphere into NetBeans IDE 4.1

Following the instructions on the Server Plugins Project page, I downloaded the NetBeans IDE 4.1 sources and the serverplugins module. I then built the JBoss, WebLogic, and WebSphere plugins. (Just make sure, as specified on the page, that you don't build the sources using Ant 1.6.1. As I tried to do.) And, after everything had built successfully, I opened the IDE, registered my local installations of JBoss, WebLogic, and WebSphere, went to the Runtime window, started two of them (as well as Tomcat, but not the Sun Java System Application Server, which was already registered in the IDE) and this is what I saw:

The three new plugins are still at a very early experimental stage, as indicated on the page referenced above (for example, I didn't get any server-specific deployment descriptors when I selected JBoss, WebLogic, or WebSphere as my target server), but it's cool to see that there's already something there. And, even at this stage, the advantage of starting the server as a plugin versus starting it from an Ant script is clear: You can see the server's status! The text [running] in the illustration above looks really trivial, but it's not. When you start a server from an Ant script (whether it's hooked up to a menu item or not), there's no way of knowing whether the server is stopped or started. Especially when it's been running for a while and you've been doing a whole bunch of things in between, it's more than likely that you'll be asking yourself: "Now, is that server running? Did I even start it? Hmmm. Let's stop it, just to make sure. And then I'll start it again." But now, with the plugins, this is not a question you'll need to ask anymore because the server's status is easy to determine -- just look in the Runtime window. Remember that all three of these new plugins are in a very early development stage, though.

Adding More Power to Menus in NetBeans IDE 4.1

One things I've missed in standard projects is that you can't create contextual menus and attach Ant targets to them. This is possible for free-form projects. The difference is, I guess, because the philosophy behind these projects is different. When working with a standard project, you don't have your own Ant scripts and so the IDE provides them for you. The assumption is that you have no intention of extending these IDE-given Ant scripts too much, otherwise you'd be using a free-form project. However, there's more flexibility in standard projects than I thought. It's all documented in the build.xml template: "There exist several targets which are by default empty and which can be used for execution of your tasks. These targets are usually executed before and after some main targets."

Here is a complete list of these targets:

-pre-init:                 called before initialization of project propertie
-post-init:                called after initialization of project properties
-pre-compile:              called before javac compilation
-post-compile:             called after javac compilation
-pre-compile-single:       called before javac compilation of single file
-post-compile-single:      called after javac compilation of single file
-pre-compile-test:         called before javac compilation of JUnit tests
-post-compile-test:        called after javac compilation of JUnit tests
-pre-compile-test-single:  called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar:                  called before JAR building
-post-jar:                 called after JAR building
-post-clean:               called after cleaning build products

The one I've found most useful so far is -post-jar. In so many situations, such as when developing NetBeans Modules, one needs a JAR file before going any further. And for these situations this target is really useful. You can just refer to any of your own targets in this target, and it will be executed after the JAR is created, which happens when the Build Project menu is used. This means that you've actually added your own targets to the Build Project menu. For example, this is how I build NetBeans Modules:

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

So, the revelation for me was that even though standard projects are limited in that they don't allow for customized contextual menus, the existing contextual menus can be extended, to the extent that my not being able to create my own contextual menus for standard projects doesn't make much difference.

Thursday May 12, 2005

NetBeans IDE 4.1: Great Test Environment for Modules

Developing a NetBeans Module (NBM) can be a surprisingly smooth process. For example, the illustration below shows the state of my TagExtension module yesterday. At the top of the Projects window you see the module project (which is actually just a plain old J2SE project). Beneath it is a random web application project that I'm using to test the module. In the illustration, you see a tag called abc.tag with an icon and menu items provided by the TagExtension module (click to enlarge):

Now lets say I want to add some more menu items. This means modifying the TagExtensionNode class. So let's add a whole bunch of new menu items, all defaults provided by the system -- none provided by ourselves yet. So we change the code to look as shown in the illustration below (interestingly, a line consisting of null, represents a separator in the list).

After we've rebuilt the NBM using the same Ant scripts as before, we simply go to the Options window, find the module, delete it, after which we go to the Update Center, browse for the updated NBM, and install it. Right? Wrong. That's just far too much work. Instead, get yourself an org-netbeans-modules-apisupport-ant.jar. (If you don't have it locally, go to the Update Center and install the Open Ant API Extensions. Make sure you install them globally, otherwise you might not find the JAR, especially if you're a Linux user. When you install a module globally -- it's an option somewhere in the Update Center process -- it ends up in the nb41 folder of your NetBeans IDE installation directory instead of in your user directory.) Once you have the org-netbeans-modules-apisupport-ant.jar attached to the module project (right-click the Libraries node and browse to the JAR), add the following to your build.xml file:

<target name="reload" description="Reload NBM File.">
  <nbinstaller module="${dist.jar}" action="reinstall"/>
</target>

And then, this is where the magic really comes together: add the reload target to the -post-jar target:

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

Now this is all really cool -- and really only because the -post-jar target is really cool. It is called whenever the jar target is called. And guess where the jar target is? It is hooked up to the project's Build Project menu item. So, whenever you right-click the TagExtensions module and choose Build Project, the NBM is rebuilt and reloaded into the IDE. This means that you can see the results immediately. Great for testing your module, right? After I added a whole bunch of new menu items to the TagExtensions module, I just right-clicked the project, chose Build Project, waited 2 seconds for the whole process to unfold, and then right-clicked my abc.tag again. And this is what I saw (click to enlarge):

Not bad, huh? As far as I'm concerned, the IDE together with Ant is a fantastic NBM development environment. Sure, there are a few things to figure out, but isn't that fun? I feel really good whenever I discover some new way to hook things up to the IDE. I'd hate to have someone do everything for me. As a developer, it's really cool to be creating applications while simultaneously looking for ways to improve the IDE that I'm using and then being empowered to do it by the very same IDE. Cool stuff.


Wednesday May 11, 2005

Playing with File Types in NetBeans IDE 4.1

I've blogged quite a lot about menus -- about creating IDE-level menus in the Options window, about creating contextual menus for free-form projects, and about hooking Ant targets to both of the above. However, I'd never considered the possibility of manipulating menus on file level. This is where it really gets interesting. I found out about it all thanks to a great tutorial by Tim Boudreau: Module Building: Basic Support for a File Type. Initially, I must admit, the whole procedure seemed quite daunting -- but when I realized that most of it was really an extension on what I'd been doing before (with Action classes and Layer XML files), things began falling into place. Yes, another NetBeans Module (NBM) is coming your way! As I worked through this process, with the help of Tim's tutorial, I learnt quite a lot of interesting things -- such as how the order in which NBMs are loaded can be set.

Related to the load order, I've learnt how to override file extensions. It's easier -- and less obscure -- than it sounds. In his tutorial, Tim creates a module that recognizes two file types that are not recognized by the IDE by default. What I'm going to do, in the steps that follow, is show how you can force the IDE to distinguish between recognized JSP Objects. By default, the IDE doesn't distinguish between certain file extensions -- several are lumped together. For example, "JSP Objects" are documents that have any of the following extensions: .jsf, .jsp, .jspf, .jspx, .tag, .tagf, and .tagx. So, the IDE treats these all in the same way -- when you right-click on any of them, for example, the same menu items are available to you for each. This may not always be desirable, especially when you consider that tag files (.tag, .tagf, and .tagx) are pretty different to JSP files (.jsf, .jsp, .jspf, .jspx). For example, maybe you'd like to add a menu item to a tag file that would register the tag file in a TLD (this is possible, even though it isn't a tag handler). This menu item could be pretty useful for tag files but very annoying if it was made available to the contextual menus for JSP files. So, let's set things straight and distinguish between these two types of JSP Objects. Observant readers will notice that the code that follows is identical to that used in Tim's tutorial -- it is only structured, presented, and applied in a slightly different way (and probably explained erroneously here and there).

The general procedure to follow can be summed up in two sentences: "Create a DataLoader subclass that will recognize the file, a DataObject subclass to represent the file's contents and a Node subclass to represent those files in the UI. Register the DataLoader in the module's manifest." (From the NetBeans Developer's Guide.) The step-by-step process is as follows:

  1. Let the IDE create the NBM structure. Click Ctrl-Shift-N. In the New Project wizard, select the "General" category and then the "Java Application" project. Name the project as follows:

    tagextension

    Before clicking Finish, specify that the following main class should be created:

    org.netbeans.modules.tagextension.TagExtensionDataLoader

    Click Finish.

  2. Select the file types you want to manipulate. In a similar way to how you used the Layer XML file in previous blog entries to specify which menus (and/or toolbars and/or actions) you wanted to manipulate, you use the DataLoader class to specify which files you'd like to manipulate. Here, we select all files with extensions that denote a tag file. So, create the TagExtensionDataLoader class in org.netbeans.modules.tagextension, with the following content:

    package org.netbeans.modules.tagextension;
    
    public class TagExtensionDataLoader extends UniFileLoader {
        
     public TagExtensionDataLoader() {
       super ("org.netbeans.modules.tagextension.TagExtensionDataObject"); 
       ExtensionList list = new ExtensionList();
       list.addExtension("tag");
       list.addExtension("tagf");
       list.addExtension("tagx");
       setExtensions(list);
       setDisplayName("Tag Files"); 
     }
          
     protected MultiDataObject createMultiObject(FileObject primaryFile) 
       throws DataObjectExistsException, java.io.IOException {
       return new TagExtensionDataObject(primaryFile, this);
     }
    }

    Understanding the code. In the code above, the methods do the following:

    • TagExtensionDataLoader(). Recognizes tag files whenever the system encounters one. This could be in situations such as when you click on the tag file's node or when you right-click it to access its contextual menu. The DataLoader class is a factory for the DataObject, which is defined in step 4 below. Notice that we also set a display name in the code above. After you install the module, you can go to the Options window, then IDE Configuration > System > Object Types and there you will see the new File Type listed as "Tag Files".
    • createMultiObject(). Creates a single DataObject out of the multiple file extensions assigned to it. So, in this case, the tag file extensions are wrapped into a MultiDataObject.

    Fixing the Import statements. Click Alt-Shift-F in the Source Editor to generate import statements. After that, you'll notice that some packages are still needed. Right-click the project's Libraries node and add the following JARs:

    • netbeans-installation-directory/platform5/core/openide.jar
    • netbeans-installation-directory/platform5/core/openide-loader.jar

    Now click Alt-Shift-F again. The following import statements should be automatically added to your file:

    import org.openide.filesystems.FileObject;
    import org.openide.loaders.DataObjectExistsException;
    import org.openide.loaders.ExtensionList;
    import org.openide.loaders.MultiDataObject;
    import org.openide.loaders.UniFileLoader;
  3. Manipulate the file types. In a similar way to how the Action class can insert new actions in the IDE's menubar, toolbar, and action list, so the Node class can insert new actions in a specified file's contextual menu. The Node class extends DataNode and therefore has certain requirements. So, create the TagExtensionNode class in org.netbeans.modules.jspextension, with the following content:

    package org.netbeans.modules.tagextension;
    
    public class TagExtensionDataNode extends DataNode {
        
     public TagExtensionDataNode(TagExtensionDataObject obj) {
        super(obj, Children.LEAF);     
     }
           
     public Image getIcon(int type) {
        return Utilities.loadImage("org/netbeans/modules/tagextension/resources/TagFileIcon.jpg");
     }
         
     public Action[] getActions(boolean context) {
        Action[] result = new Action[] {
        SystemAction.get(EditAction.class),
        SystemAction.get(CutAction.class),
        SystemAction.get(CopyAction.class),
        SystemAction.get(RenameAction.class),
        SystemAction.get(DeleteAction.class),
        };
        return result;
     }
            
     public Action getPreferredAction() {
       return SystemAction.get(EditAction.class);
     }
    }

    Understanding the code. In the code above, the methods do the following:

    • TagExtensionNode(). Passes Children.LEAF to the Constructor because the file types that we are interested in are leaves and not branches, unlike directories or JAR files which have files within them.
    • getIcon(). Defines the icon that will replace the JSP Objects icon for the file types we want to manipulate. Make sure you get one and put it in the specified place!!!
    • getActions(). Defines the contextual menu items that you want to make available for the file type.
    • getPreferredAction(). Defines the default action for when a file of the specified type is selected.

    Fixing the Import statements. Click Alt-Shift-F in the Source Editor to generate import statements. It's quite hard to know which import statements to select, so here they are to make it easier for you:

    import java.awt.Image;
    import javax.swing.Action;
    import org.openide.actions.CopyAction;
    import org.openide.actions.CutAction;
    import org.openide.actions.DeleteAction;
    import org.openide.actions.EditAction;
    import org.openide.actions.RenameAction;
    import org.openide.loaders.DataNode;
    import org.openide.nodes.Children;
    import org.openide.util.Utilities;
    import org.openide.util.actions.SystemAction;

  4. Create the object. And now we need to create an object each time that the IDE encounters a tag file. So, create the TagExtensionDataObject class in org.netbeans.modules.jspextension, with the following content:

    public class TagExtensionDataObject extends MultiDataObject {
        public TagExtensionDataObject(FileObject file, MultiFileLoader ldr) 
            throws DataObjectExistsException {
            super(file, ldr);
        }
        
        public Node createNodeDelegate() {
            return new TagExtensionDataNode(this);
        }
    }

    Fixing the Import statements. Click Alt-Shift-F in the Source Editor to generate import statements. Select org.openide.nodes.Node so that the following import statements are created for you:

    import org.openide.filesystems.FileObject;
    import org.openide.loaders.DataObjectExistsException;
    import org.openide.loaders.MultiDataObject;
    import org.openide.loaders.MultiFileLoader;
    import org.openide.nodes.Node;

  5. Register the module and the loader and specify the load order. Replace the content of manifest.mf with the following content, making sure that there is a line before and after the second section:

    Manifest-Version: 1.0
    OpenIDE-Module: org.netbeans.modules/1
    OpenIDE-Module-IDE-Dependencies: IDE/1 > 4.0 
    OpenIDE-Module-Specification-Version: 1.0
    
    Name: org/netbeans/modules/tagextension/TagExtensionDataLoader.class
    OpenIDE-Module-Class: Loader
    Install-Before: org.netbeans.modules.web.core.jsploader.JspDataObject
    
    

    Now, the Install-Before line is really interesting -- and its not from Tim's tutorial! When you go to Tools > Options, and then select IDE Configuration, System, Object Types, you see all the IDE's file types listed. If you click on the JSP Objects node, you see all the extensions that are associated with the node by default. However, you also see the Representation Class. To override a file type's associations, create a new module to manipulate the file extension -- as we are doing -- and specify in the manifest.mf that you want to load the new module after the representation class associated with the file type in the IDE (as shown above). In this way you override the default association for the selected file type.

Now you are ready to build and install the module. Your Files window should display the following structure, right at the end, after you have created the module:

There's no point in repeating something that's as close to hand as my previous blog entry -- just follow steps 4 and 5 in the final part of the NetBeans Modules for Dummies series (when you add properties to the project.properties file, replace the value of module.dir and cluster.dir with tagextension) and everything should be fine. In addition, before building the module, you will need to add nbantext.jar separately. If you don't have a copy in the NetBeans IDE's nb4.1/ant/extra directory, go to the NetBeans Update Center by using Tools > Update Center. Make sure to tell NetBeans to check the NetBeans Update Center, the first option. In the Available Updates and New Modules, select the NetBeans Update Center > Libraries > Ant Extensions for Open APIs Support and add it to the Include to Install. Proceed through the rest of the Update Center wizard to install the additional module. Unless you selected the "global" option as the location to install the Ant Extensions for Open APIs Support module, the nbantext.jar will be placed in your $HOME/.netbeans/nb4.1/ant/extra directory. If you select "global", the nbantext.jar will in the NetBeans IDE's nb4.1/ant/ext directory. Traverse to the directory where nbantext.jar resides and add that jar to the project as you did above for the openide.jar and openide-loaders.jar. It can be difficult to add the nbantext.jar if it is located in $HOME/.netbeans/nb4.1/ant/extra since the Add Jar/Folder does not see ".netbeans" as a directory on Linux.

After you build and install the module, create a web application (Ctrl-Shift-N) and then create a tag file (Ctrl-N and then go to the Web category). The first sign of success is that you'll see your new icon alongside the tag file! When you see that new icon, your heart will pitter-patter slightly faster... and then you will know that it was all worth it. For example, this is what my list of File Types for the Web category (in the New File wizard) looks like:

Do you see how the tag file has a different icon to the JSP? That's my doing. Now, after I've created the tag file, I'm able to right-click the node in the Projects, Files, or Favorites window and see that I have less menu items available than I normally would. And that's because I successfully manipulated the IDE and made it do my bidding. Yet again.


Tuesday May 10, 2005

NetBeans Modules for Dummies (Part 6)

In this final installment of the unofficial "NetBeans Modules for Dummies" guide, we're going to apply the principles of yesterday's installment to the Anagrams sample that is distributed with the NetBeans IDE. We'll start with a standard J2SE application and finish with an NBM. The NBM will give us a new menu called "Games" with a submenu called "Anagrams". Clicking on "Anagrams" will pop up the Anagrams sample. Of course, we could choose to install the NBM either in the NetBeans IDE or in the NetBeans Platform. (Maybe we could even make a whole bunch of games, then turn them into NBMs and install them in the NetBeans Platform and end up with our very own Games Center.)

  1. Get the J2SE sample. Choose File > New Project > Samples > General > Anagram Game. Click Next and Finish.
  2. Modulerize the sample. In Anagrams.java, two methods need to be changed: exitMenuItemActionPerformed and exitForm. Instead of closing the system when you close the module (which is the behavior of an application), you just want to dispose of the module when you close it. Hence, replace the content of these two methods with the following:

    setVisible(false);
    dispose();
  3. Create the module's supporting files.

    • The Action class. Right-click the Source Packages node and choose New Java Class. Name your class ShowAnagramsAction and type com.toy.anagrams in the Package field. Click Finish. Replace the code with the following:

      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();
          }
      }

      Click Alt-Shift-F in the Source Editor. You'll get error messages. Right-click the Libraries node, choose Add Library, and create a library that contains three jars: openide.jar, openide-loaders.jar, and nbantext.jar. (We don't need the latter in this step, but it's good to have it available already.) Once you've added these libraries, which you should be able to find in your distribution or in the Update Center (in the case of nbantext.jar), and click Alt-Shift-F again, the error messages disappear.

    • The Layer XML file. Right-click the Source Packages node and create an XML Document called layer. Put it in a package called com.toy.anagrams.resources. Click Finish. Replace the code with the following:

      <?xml version="1.0" encoding="UTF-8"?>
      <!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>
      

    • The Manifest file. Right-click the Project node and choose New > File/Folder > Other > Empty File. Call the file manifest.mf and click Finish. Replace the code 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

      Now add the following line to the nbproject/project.properties file:

      manifest.file=manifest.mf
  4. Build the module.

    • Get the Ant scripts. Add the following two scripts to your build.xml file:

      <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 (therefore, you must build the JAR first!). -->
        <copy file="${dist.jar}"
              todir="netbeans/${modules.dir}"/>
      
        <!-- Create the XML for the JAR (therefore, must have an appropriate manifest.mf first!). -->
        <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> 
    • Define target properties. In part 4 of this series, the strict requirements of some versions of the nbantext.jar were described. So, some of the properties below -- not all -- are only there to prevent build errors occurring (when nb.system.dir isn't set, for example). Define them in the nbproject/project.properties file:

      cluster.dir=Anagrams
      modules.dir=${cluster.dir}/modules
      modulexml.dir=${cluster.dir}/config/Modules
      module.name=Anagrams
      nb.system.dir=config
    • Add the Ant scripts to the build process. When you include the little target below, you don't have to run the above two targets yourself. This is because the IDE has a number of targets as placeholders, which you can fill in with whatever you like. This target, for example, is automatically run after a project is built (which means that the JAR is available, which is what you need when creating an NBM). Here it is. Just add it to the build.xml file:

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

    • Build the project. Right-click the project and choose Build Project. The messages in the Output window should end with something like the following:

      Enabled modules: [anagrams/1]
      create-nbm:
      Generating information for Auto Update...
      Building jar: C:\\IDEModules\\AnagramGame2\\anagrams.nbm
      jar:
      BUILD SUCCESSFUL (total time: 0 seconds)

  5. Install the module. Choose Tools > Update Center (either in the IDE or in the Platform), click the radiobutton at the bottom of the dialog box, and browse to your NBM. After some more clicking, your NBM will be installed and in the menubar you will see the following:

    You can re-order the menu and the menu item as discussed in previous blog entries. When you click the menu item, the Anagrams sample appears. (And you are able to close it, because of what you did in step 2 above.) Congratulations.

So now, since you know the basics of NetBeans Modules, you can no longer be called a dummy. Therefore, this series of short tips and articles aimed at NBM beginners has now come to an end. I will blog more about the things I discover in the NBM area, because it's all really interesting and relatively straightforward. Of course, the modules discussed here have been quite simple -- I'd like to find out more complex things such as, for example, how to create a node in the Runtime window, how to write a module to start a server, how to write a template and install it via a module, and the many other magical things the Layer XML file can do for me. But that's also one of the really cool things about NetBeans -- there's always something more to learn...

Monday May 09, 2005

NetBeans Modules for Dummies (Part 5)

Now that I can create a NetBeans Module -- albeit a very simple one -- I'd like to be able to transform an existing J2SE application into a NetBeans Module. What would I have to do to make this possible? Here's a short list:

  1. Specify the changes that you want to make to the filesystem. Do you want to access the module from a menu item? A toolbar button? Or some other way? Create a layer.xml file for this purpose.
  2. Create an Action class that extends CallableSystemAction. What's very important is the performAction method, which provides the entry point to the module.
  3. Make sure that the IDE interprets the application as a module. To do this, add module entries to the manifest.mf file.
  4. Modify the application so that it works as a module. Many things to be considered here -- the more complex the application, the more intricate the considerations. Sandip Chitale has given me the following tips:

    • You should not set the "defaultCloseOperation" property of a Frame to "EXIT_ON_CLOSE". Although this works for simple applications with one frame, you do not want the whole NetBeans JVM to exit when the user closes the Frame. Therefore, change the property to "DISPOSE_ON_CLOSE" instead.
    • You should not hook the low level event MouseClicked to perform an action. Instead, you should hook the abstract event ActionPerformed. That is because you want your code to be invoked not only when the user does a mouse click but also when the user presses the spacebar or return key from the keyboard. (This comment not necessarily related to modules specifically, but useful comment nonetheless!)

  5. Generate the XML file that describes the module, as well as some related files (for update tracking purposes). Use the cluster harness or your own Ant script for this. Refer to the previous blog entry for details on the Ant script as well as on the properties that need to be set if you use a non-standard nbantext.jar file.
  6. Finally, generate the NBM itself. The method is the same as above -- use the cluster harness or your own Ant script. Refer to the previous blog entry for details on the Ant script as well as on the properties that need to be set if you use a non-standard nbantext.jar file.
About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« May 2005 »
SunMonTueWedThuFriSat
6
8
13
14
16
20
25
    
       
Today