Archive

Archive for the ‘NetBeans Platform’ Category

NetBeans Platform – Duplicate pair in treePair error

March 5, 2011 Leave a comment

I have previously written about the NetBeans Platform
I’ve been using a lot recently at work and so have found a lot of pain points when using the APIs. I’ll try to document some of the more vexing problems here for other programmers who might be facing the same problem.

One problem you will probably face while using the NetBeans Platform is an inscrutable error message when you start up your application, something to the effect of:

java.lang.IllegalStateException: Duplicate pair in treePair1: java.lang.Object pair2: java.lang.Object index1: 55 index2: 55 item1: null item2: null id1: 16309239 id2: 4ecfe790

    at org.openide.util.lookup.ALPairComparator.compare(ALPairComparator.java:83)
    at org.openide.util.lookup.ALPairComparator.compare(ALPairComparator.java:54)
    at java.util.TreeMap.put(TreeMap.java:530)
    at java.util.TreeSet.add(TreeSet.java:238)
    at org.openide.util.lookup.AbstractLookup.getPairsAsLHS(AbstractLookup.java:322)
    at org.openide.util.lookup.MetaInfServicesLookup.beforeLookup(Met…

While it’s impossible to know from this error message, this really indicates that you had some sort of exception in the initializer of one or more of your TopComponents, leading to duplicate null entries in some internal set that NetBeans Platform maintains, leading to this error message. Fortunately, there is usually a “Previous” button on the exception window so you can see what caused the real problem.

NetBeans Platform – how to register a class as a provider of multiple services

January 24, 2011 2 comments
In NetBeans Platform, there is an annotation called ‘ServiceProvider‘, which allows you to declare that your class provides a certain service (i.e., implements a given interface).   This ties directly into the previously blogged about topic of Lookups, as the class thus annotated is added to the global, default lookup.  Recall that a lookup is a nice wrapper around a Map<Class<E>, Collection<? extends E>>, and allows modules to decouple themselves from the service they request from the actual concrete implementation that they receive.  (A much more in-depth discussion can be found on the Dev FAQ section on lookups).

The issue I ran into is that the documentation is not very clear how you can register your class as providing more than one service (again, implementing more than one interface).  For instance, say I have two interfaces I want a class to fulfill:

public interface Foo {
    public String getFoo();
}

public interface Bar {
    public String getBar();
}

public class FooBar implements Foo, Bar {
    public String getFoo() { return "foo"; }

    public String getBar() { return "bar"; }
}
Since you cannot annotate a class twice, the naive solution fails:
// This is a mistake; you can't declare two annotations like this
@ServiceProvider(service=Foo.class)
@ServiceProvider(service=Bar.class)
public class FooBar implements Foo, Bar {
The correct solution is to use the ServiceProviders annotation, which allows you to provide a list of @ServiceProvider declarations.
@ServiceProviders(value={
    @ServiceProvider(service=Foo.class),
    @ServiceProvider(service=Bar.class)}
)
Now you can find the FooBar instance via either defined interface.

Reset windowing system in NetBeans Platform

January 5, 2011 3 comments
One of the benefits of building programs on top of NetBeans Platform is the powerful windowing and docking framework it provides out of the box.  Part of this functionality is persistence; when a user closes a NetBeans Platform application, the state of all the windows is saved.  The next time the application is started, the windowing state is restored.  This is why the NetBeans IDE (which is built on the NetBeans Platform) remembers which files you had loaded and how you had your windows arranged.
During development, it is sometimes beneficial to do a ‘factory reset’ and reset the windows back to the way they would look when the application is launched for the first time. For instance, you may have inadvertently closed some windows you wanted to have open, or you opened some windows that you wanted closed and don’t feel like manually restoring each window’s open/closed state. Or perhaps you moved some of the windows in a position that made sense for testing part of the application, but now you want to test another part that requires the original windowing setup.

Clean and build

There are two main ways to do this.  The easiest way is to do a full clean and build of the project (right click on the top level project node in NetBeans and choose Clean and build)

This works fine, but it has the drawback of.. cleaning and rebuilding the project.  This can take a long time for complex projects, and is a bit overkill if all you want to do is reset the windowing system.

Remove Windows2Local

The second way of accomplishing this is to remove a folder named “Windows2Local”.  If the root of your NetBeans Platform project is located at /path/to/Foo, then the folder to remove is /path/to/Foo/build/testuserdir/config/Windows2Local
You can delete the folder any way you see fit; I usually do a
rm -rf /path/to/Foo/build/testuserdir/config/Windows2Local
from the terminal.
This folder contains the saved information about the window placement and sizes; by removing it, you force NetBeans to recreate it when the application restarts.
This method is much faster, as nothing needs to be recompiled.  It is my preferred way of resetting the windowing system back to its default state when developing NetBeans Platform applications.

NetBeans Platform – ModuleInstall ClassNotFoundException

January 3, 2011 Leave a comment

In the NetBeans Platform, you can create an ModuleInstall class which handles the lifecycle of your module, and provides methods you can override to handle when your module is loaded and unloaded.  The standard way of creating this class is to use the wizard that NetBeans provides for this purpose, accessible by right clicking on the project and choosing New -> Other -> Module Development -> Module Installer

If you decide that you do not want to use the ModuleInstall mechanism any longer (the NetBeans Platform folks suggest you do NOT use it, as it will increase the startup time of the application), you might think you can just delete the Installer.java file that the wizard created.  Unfortunately, that’s not the case.  When you run the project you’ll get an exception like the following

org.netbeans.InvalidException:  
StandardModule:net.developmentality.moduleexample jarFile: ...
  java.lang.ClassNotFoundException:  net.developmentality.moduleexample.Installer starting from  ModuleCL@482...

The problem is that the wizard modified the manifest.mf file as well, and you need to manually clean up the file before your project will work again.

Open the manifest.mf file and you’ll see a line in the file like the following:

OpenIDE-Module-Install: net/developmentality/moduleexample/Installer.class

delete that line, and rebuild.  You should be ready to go.
In general, you need to be very careful about using any of the wizards that NetBeans provides.  They are extremely useful, but they end up changing XML files that you will need to manually edit later if you decide to refactor.  For instance, if you create an Action instance using the New Action Wizard, the action will be registered in the layer.xml file.  If you rename the action using the refactor command, the entries in the xml file are NOT modified, and you will get an exception at runtime unless you remember to edit that file.
Fortunately, the wizards are smart enough to at least tell you which files they are modifying.  It’s just a matter of remembering this further down the road when you need to refactor, move, or delete files.  Look for the modified files section in the wizard dialog:

 

Increase heap size for NetBeans Platform project

December 9, 2010 2 comments

To increase the heap size in a NetBeans Platform project, you can edit the nbproject/platform.properties file and add the line

 

run.args.extra=-J-Xmx1G

 

, replacing the 1G piece with however much memory you’d like. (The other solutions I found did not work for me). Thanks to the NetBeans Forums for this solution.

If you’re curious about the -J piece, it’s necessary to ensure that the arguments are passed to the JVM rather than interpreted by NetBeans itself. This should work in general for whatever arguments you want to pass to the JVM upon launch of your NetBeans Platform project.

NetBeans Platform – How to handle the working directory problem

November 9, 2010 6 comments

I have written previously about NetBeans Platform, but as a refresher or an introduction to my new readers, it’s a Java based framework for developing rich desktop applications.  A NetBeans Project is comprised of one or more modules.  The code in Module A cannot be accessed by Module B, unless Module B declares a dependency on Module A, and Module A explicitly declares that its code is public.  In this way, code is segmented and encapsulated into logical blocks.

In this example, I’ve created an example project, with three modules – one for the View, Model, and Controller.  (See Wikipedia if that’s not ringing a bell, and then my post about a Java Solar system for a concrete example implementation).

The project can be run either from the main project node,

or by any of the modules:

While in most cases, the behavior will be identical, there is one way in which the manner in which you launch the application matters enormously: relative paths.
The working directory is directly influenced by whether you choose the project or the module to launch with:
# Application launched from the ExampleApplication node:
Current Directory       = /NetbeansExample/ExampleApplication

# Application launched from the View module:

Current Directory       = /NetbeansExample/ExampleApplication/View

Why is this a problem?

Say my View code has a properties file it needs to read in to initialize some code.  Let’s say I store it at
/NetbeansExample/ExampleApplication/View/resources/example.properties
From within my sourcecode I might attempt to do the following:
File f = new File("resources/example.properties");
If I have started the application from the View module, then this will work fine; the current working directory is /NetbeansExample/ExampleApplication/View, as I previously said; thus by tacking on resources/example.properties, we come to a valid file.  If you launch from the main project, you will find that the file doesn’t exist, because /NetbeansExample/ExampleApplication/resources/example.properties does not exist.

How do can we handle this?

The best way I’ve found is through the use of the InstalledFileLocator class, provided by the Netbeans Platform Module APIs.

First, we need to move the .properties file from View/resources to View/release.

Once we have done that, we need to declare a dependency on the Module API in order to use this InstalledFileLocator class.  Right click on the View node and choose Properties,
In the libraries pane, click Add Dependency, and then start typing InstalledFileLocator.
The Module API should appear in the list.  Choose it and click OK.  You should see
From within your view code, you now replace code that looked like
File f = new File("resources/example.properties");

with

File f = InstalledFileLocator.getDefault().locate("example.properties", "net.developmentality.view", false);

where “example.properties” is the path to the file you’re trying to load, relative to the “release” folder, and where “net.developmentality.view” is the package name of the file in which you’re working.  The last argument is described in the Javadocs as:

localized – true to perform a localized and branded lookup (useful for documentation etc.)

I have had no problem leaving it false for my purposes.

Conclusion

I found this workaround after scouring the forums and being led to an FAQ about the LocalizedFileLocator.  It makes the code slightly more messy, but at least it works regardless of how the user or developer launches the application, which cannot be said for the standard way of specifying relative paths.  It is a very hard thing to search for, so hopefully someone running into this problem using NetBeans Platform finds this post.

NetBeans Platform Tip #2: Persisting state in TopComponents

April 27, 2010 1 comment

Given the fact that NetBeans remembers the size, location, and layout of all your TopComponents, it isn’t too surprising that there is an easy mechanism for persisting state information.  Unfortunately it’s not immediately obvious; if you don’t stumble onto the right resources, you might be led to believe you need to deal with the Preferences API or writing to a database or some other flat file, and reading it later.  Fortunately it’s easier than that.  Assume we have a list of Strings we want to remember between invocations of our top component; somehow we get them from the user (the details of that are not important here), and we’d like to remember them.  The secret is in the writeExternal and readExternal methods, which are called when the TopComponent is serialized (saved) and deserialized (loaded).  Also make sure the persistence type you return is TopComponent.PERSISTENCE_ALWAYS; otherwise NetBeans will not attempt to save your TopComponent between invocations of your app.

public class TestTopComponent extends TopComponent implements Serializable {

    private List<String> strings = new ArrayList<String>();

    public EngineeringTableTopComponent(Collection<String> toSave) {
        initComponents();
        this.strings.addAll(toSave);
    }

    public EngineeringTableTopComponent() {
        this(Collections.EMPTY_LIST);
    }

    public void initComponents() {
         // Create GUI
    }

    @Override
    public int getPersistenceType() {
        return TopComponent.PERSISTENCE_ALWAYS;
    }

    /**
     * Save the state of the top component, including which properties are displayed
     * @param oo
     * @throws IOException
     */
    @Override
    public void writeExternal(ObjectOutput oo) throws IOException {
        super.writeExternal(oo);
        Object toWrite = new NbMarshalledObject(strings);
        oo.writeObject(toWrite);
    }

    /**
     * Restore the state of the top component, including which properties are displayed
     * @param oi
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @Override
    public void readExternal(ObjectInput oi) throws IOException, ClassNotFoundException {
        super.readExternal(oi);
        NbMarshalledObject obj = (NbMarshalledObject) oi.readObject();
        strings  = (List<String>) obj.get();
    }
}

NetBeans Platform Lessons Learned/Gotchas – Part 1

April 1, 2010 3 comments

As I stated in a previous post, NetBeans is my IDE of choice.  I find it extremely powerful and capable; it is the program I spend most of my day working in.  Fortunately the hard work that went into the NetBeans IDE can be leveraged by average users through the use of the NetBeans Platform (NBP for brevity here).  You can create standalone desktop clients using all the same features of the NetBeans editor (syntax highlighting, robust docking framework, property editors, etc.), without having to worry about coding all these complex features from scratch.  With such a powerful and complex API to learn, there are bound to be stumbling blocks.  This is the first in what’s sure to be a series of lessons I’ve learned while working in the NetBeans Platform.

Learning resources

I purchased a book to learn the NetBeans Platform, but I was getting nowhere with it.  Sometimes you need to be handheld through the process of doing something the first few times, and the book just omitted too many steps.  For instance, there are oftentimes you must add dependencies to your project that the book omits.  I highly recommend the NetBeans Platform Learning Trail, particularly the series of tutorials starting with Managing Selection.  There is a concept of a Lookup in the NetBeans Platform which is just a map from Class to the set of instances of that class; it is used extensively in NBP and understanding it is extremely important.  The section in the book did not do it justice; going through the tutorials methodically did the trick.

Lookup Woes

I’m not going to repeat what is said in the tutorial, but I do want to point out one gotcha that had me hung up for awhile.

Rather than keeping track of which windows have focus and reacting to this, you can instead use a Lookup that proxies whatever window has focus.  So if user clicks from editor window to an output window, you can react to this.  Here is the description:

Utilities.actionsGlobalContext() is a Lookup which proxies the Lookup of whichever TopComponent currently has keyboard focus, and fires changes when focus moves to a different component.

The example they give is as follows:

private Lookup.Result result = null;
public void componentOpened() {
    Lookup.Template tpl = new Lookup.Template (APIObject.class);
    result = Utilities.actionsGlobalContext().lookup(tpl);
    result.addLookupListener (this);
}

Why is this useful?  Let’s use the Properties window as an example.  When you have the properties window open, it always displays the properties of the currently focused window.


When the editor is focused, details about the source file are provided


When the Files menu is focused, details of the currently selected node are provided

The tutorial does not show how you would listen to the Lookup of just a single topcomponent.  Why would you want to do that?  Say you are writing a custom control which somehow edits aspects of the object(s) returned by the lookup returned by Utilities.actionsGlobalContext().  As soon as you click into your custom component, the focus changes, and the lookup now points to a different object (or none at all), meaning you can’t edit the properties you were trying to.  (Somehow the built in properties panel avoid this problem; I don’t know what they do).  But regardless, sometimes you would like to listen to just the lookup of a single window.  To do this you might expect something like:

private Lookup.Result result = null;
public void componentOpened() {
    Lookup.Template tpl = new Lookup.Template (APIObject.class);
    // TopComponent implements LookupProvider

    TopComponent componentToTrack = TheTopComponent.getInstance();
    Lookup toTrack = componentToTrack.getLookup();
    result = toTrack.lookup(tpl);
    result.addLookupListener (this);
}

And that would be a good first effort.  Unfortunately, following their pattern doesn’t work.  You have to add a call to allItems() or allInstances() before you actually receive Lookup events.  Pretty crazy huh?  The only way I found this out (I don’t see it in the Javadocs at all) is through a lot of googling; the page in question is here.  The correct code is thus

private Lookup.Result result = null;
public void componentOpened() {
    Lookup.Template tpl = new Lookup.Template (APIObject.class);
    // TopComponent implements LookupProvider

    TopComponent componentToTrack = TheTopComponent.getInstance();
    Lookup toTrack = componentToTrack.getLookup();
    toTrack.allItems(); // allInstances() seems to work too
    result = toTrack.lookup(tpl);
    result.addLookupListener (this);
}


That issue really stymied me for awhile, so hopefully someone can save some frustration due to this post.  It reminds me of problems I had with Android; the workaround is just as unintuitive.

Wrapping Libraries


Unlike standard Java programs, you cannot just add jars to a libraries folder and expect to be able to use them in a NetBeans Platform project.  Instead, you must create a Module that wraps each jar you want to use.  See the Dev FAQ page for more info.  Fortunately they make it pretty easy to do this; you can just right click the Modules folder, choose Add New Library, then follow the steps in the wizard.

Let’s make this concrete; let’s say I need to use apache-commons-beanutils in a project.  I download the jar and wrap it.


I now have a module in my project that merely wraps the jar.


I start using the bean classes:

As you can see, it won’t compile.  This is because we have not indicated that the API module depends on the commons-beanutils module.


After adding the dependency, everything compiles.

You might expect everything to be fine at this point, but you’d be wrong.  If you ran this example, you would get a ClassPathNotFoundException for some Apache Commons Logging components.  If you had read carefully the dependencies page, you wouldn’t be surprised.  But you probably were surprised that you didn’t see any warnings of any kind.  The secret is you have to choose “Build” on the wrapped jar file.

If you do, you will see a few warnings like the following:


verify-class-linkage:
Warning: org.apache.commons.beanutils.BeanComparator cannot access org.apache.commons.collections.comparators.ComparableComparator
Warning: org.apache.commons.beanutils.BeanMap cannot access org.apache.commons.collections.Transformer
Warning: org.apache.commons.beanutils.BeanMap cannot access org.apache.commons.collections.set.UnmodifiableSet
Warning: org.apache.commons.beanutils.BeanMap cannot access org.apache.commons.collections.list.UnmodifiableList
Warning: org.apache.commons.beanutils.BeanMap$2 cannot access org.apache.commons.collections.Transformer
Warning: org.apache.commons.beanutils.BeanMap$3 cannot access org.apache.commons.collections.Transformer
Warning: org.apache.commons.beanutils.BeanMap$4 cannot access org.apache.commons.collections.Transformer
Warning: org.apache.commons.beanutils.BeanMap$5 cannot access org.apache.commons.collections.Transformer
Warning: org.apache.commons.beanutils.BeanMap$6 cannot access org.apache.commons.collections.Transformer
Warning: org.apache.commons.beanutils.BeanMap$7 cannot access org.apache.commons.collections.Transformer
(additional warnings not reported)

Those warnings should tell you pretty unequivocally that things are going to go terribly wrong if you attempt to use the jar as it is.  You need to add the dependency to the wrapped library jar, in the same way that you added the dependency to the beanutils wrapper module to the API module.

The reason I went through this example is that nowhere online did I see a real world example like this where wrapped library modules themselves need to have their dependencies resolved; the tutorials always have the ideal world of “A depends on B, so A must declare a dependency on B’s wrapper module”.

If you’ve done all this and still have class path not found exceptions, I would advise that you do a full clean build of the project, perhaps replacing the jars with new builds of them as well.  That was the only way I got my dependency problems resolved in one hairy instance.

The moral of the story is ALWAYS attempt to build wrapped module jars.  If you don’t, everything will compile fine but you will get nasty runtime exceptions later.  Don’t ignore the warnings!

Property Sheets

As mentioned earlier, one of the strengths of the NetBeans platform is that you can use the Swing components that NetBeans have developed in your own project.  One of the most useful one of these is the PropertySheetView.  If you’ve designed interfaces in the Matisse GUI builder, you’re no doubt familiar with this.  See earlier in this post for some screenshots of the PropertySheetView component.  It’s fairly simple, merely a two column view of key value pairs.  Properties that cannot be edited are greyed out.  There are mechanisms for creating custom editors (e.g. you can make a color picker pop up when a color is modified, rather than typing in RGB values), and you get a lot of functionality from this component.

In order for the PropertySheetView to display anything, it needs to be associated with a Node.  As the Javadocs say:

This class is a view to use it properly you need to add it into a component which implements ExplorerManager.Provider. Good examples of that can be found in ExplorerUtils. Then just use ExplorerManager.Provider.getExplorerManager() call to get the ExplorerManager and control its state.

It’s slightly confusing and complicated, but just follow the examples here and in the previous tutorials.

To definine what shows up when a node is displayed in a PropertySheetVIew, you must override the createSheet method.  The general pattern is as follows:

@Override
protected Sheet createSheet() {

    Sheet sheet = Sheet.createDefault();
    Sheet.Set set = Sheet.createPropertiesSet();
    
    // Replace with whatever object you're wrapping with this node; make sure that your
    // lookup is set correctly
    APIObject obj = getLookup().lookup (APIObject.class);

       // Here is where the hard part is. How do you define these?
    Property[] properties = ...;
    
    set.putProperties(properties);
    sheet.put(set);
    return sheet;
}

Generally, what you want to display in a property sheet view is all the properties of the node, e.g. those variables exposed via getters and/or setters.  I won’t rehash how to do this here; the previously mentionedNodes API Tutorial shows how to expose a few properties.

The reason I mention this is because I glanced over part of the source code they provided:

protected Sheet createSheet() {

    Sheet sheet = Sheet.createDefault();
    Sheet.Set set = Sheet.createPropertiesSet();
    APIObject obj = getLookup().lookup(APIObject.class);

    try {

        Property indexProp = new PropertySupport.Reflection(obj, Integer.class, "getIndex", null);
        Property dateProp = new PropertySupport.Reflection(obj, Date.class, "getDate", null);

        indexProp.setName("index");
        dateProp.setName("date");

        set.put(indexProp);
        set.put(dateProp);

    } catch (NoSuchMethodException ex) {
        ErrorManager.getDefault();
    }

    sheet.put(set);
    return sheet;

}

Did you miss it too?

indexProp.setName(“index”);
dateProp.setName(“date”);

If you forget the call to setName on a node, your properties will not show up in the property sheet view.  Why is that?  A careful reading of the javadoc for the put methods reveals the answer:

put

public Node.Property<?> put(Node.Property<?> p) Add a property to this set, replacing any old one with the same name.
Parameters:p – the property to add Returns:the property with the same name that was replaced, or null for a fresh insertion

put

public void put(Node.Property<?>[] ar) Add several properties to this set, replacing old ones with the same names.
Parameters:ar – properties to add

My problem was that I was calling setDisplayName on the Property object, without the corresponding setName call.  Thus only the last property I added ended up showing up in the view, because all the Property objects had the same name field (null).  I was led down a false trail when I noticed that all the Property objects had the same hashcode (0).  I reimplemented the hash function to ensure it would be different for all, but the set still only contained one object.  In hindsight, the hashcode of 0 should have tipped me off to a null field rather than assuming that the creators had messed up the hashCode function.

Conclusion

NetBeans Platform is an extremely powerful framework for building Java applications.  The learning curve is very steep, and I hope you can learn from my mistakes.  To recap, the big takeaways were

  • Use the online tutorials rather than a book.  They show each step in detail, instead of glossing over crucial steps
  • You have to add a call to allItems() or allInstances() before you actually receive Lookup events from a LookupListener
  • When dealing with wrapped libraries, make sure you build them to catch any warnings about inaccessible classes
  • When dealing with properties, you must call setName() on them in order to have them show up in a PropertySheetView
    • Read the JavaDocs carefully before you go off and start doing stupid things like reimplementing hash functions.  Chances are, it’s not broken, you’re just not using it right.  To borrow a phrase, “If you hear hoofbeats, think horses, not zebras”