Friday Oct 10, 2008

Flickr Photos of Recent NetBeans Platform Training

Toni's photos, taken last week at the NetBeans Platform Certified Training in Wuerzburg. The training was delivered by Pavel Kotlov, David Strupl, Toni Epple, and myself.

This course is offered for free to universities (and colleges and similar institutions), but only if the course is embedded within the existing curriculum of the class. (I.e, it should be taken seriously by everyone involved.) The course fits very well within an advanced Swing curriculum or within a curriculum that focuses on architectural concerns for large and distributed Java applications. It is probably less appropriate for a class of complete newbies to Java. We have a number of trainers available around the world, in particular in the US, Europe, and Australia. A good report on the whole experience is here in Toni's blog, where he writes about his 1st experience being a trainer on this course.

Using the Layer to Set Customer-Specific Properties

Let's say you have one base application for all your customers. However, each customer has some user-specific settings that need to be distributed and installed in some way. Previously, i.e., in your pre NetBeans Platform days, you might have distributed an INI file (or some other config file) which was somehow read into the application to include the customizations.

But now you're working with the NetBeans Platform. Is there specific support for this scenario or should you go on using your INI approach? Here's where the System FileSystem comes in handy. Let's say we have two clients, called 'Red Station' and 'Blue Station'. For each of these, create a new NetBeans module. Don't add any code at all. Simply populate the layer.xml file of the 'Red Station' module with this content (or whatever content your original INI file used to have):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" 


    <folder name="station">
        <attr name="name" stringvalue="Red Station"/>
        <attr name="welcomeText" stringvalue="Welcome to the Red Station!"/>
        <attr name="isHelpMenuIncluded" boolvalue="false"/>
        <attr name="isToolbarsIncluded" boolvalue="true"/>

Then, in the 'Blue Station' module, populate the layer.xml file with this content:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" 

    <folder name="station">
        <attr name="name" stringvalue="Blue Station"/>
        <attr name="welcomeText" stringvalue="Welcome to the Blue Station!"/>
        <attr name="isHelpMenuIncluded" boolvalue="true"/>
        <attr name="isToolbarsIncluded" boolvalue="false"/>

As you can see, we have set various properties—the name of the station, some welcome text, whether the Help menu should be displayed, and whether the toolbars should be displayed. You can set any attribute you like, i.e., those attributes could be anything at all, whatever you need, such as 'isSantaClausReal' or whatever. By the way, notice those attribute types, i.e., 'stringvalue' and 'boolvalue'. Those are fixed, i.e., there is a specific subset of types that can be used. How did I know what was available? First, I used code completion:

Secondly, look at the DTD, which is available on-line.

OK. So, now we've set our properties. They could be a whole range of different things. Then we distribute them to our users. Users at the 'Red Station' would get that particular module, while users at the 'Blue Station' would get the other one. Even though neither module contains any code at all, once the respective users install them, they'd get very different results (look at the title bar, tab text, text area, toolbars, and Help menu in the screenshots below):

How is that possible? In the base application (i.e., the application that all the users have), I have a TopComponent with all of this content in the constructor (though the code could be anywhere else too, but since it mostly relates to the TopComponent, I put all the code there):

private BaseTopComponent() {

    try {


        //Get the root of the user directory:
        FileObject root = Repository.getDefault().getDefaultFileSystem().getRoot();

        //Get the station element:
        FileObject station = root.getFileObject("station");

        //Get the 'name' string attribute for the station:
        final String name = station.getAttribute("name").toString();

        //Get the 'welcome text' string attribute for the station:
        String welcomeText = station.getAttribute("welcomeText").toString();

        //Get the 'isHelpIncluded' boolean attribute for the station:
        final Boolean isHelpMenuIncluded = (Boolean) station.getAttribute("isHelpMenuIncluded");

        //Get the 'isToolbarsIncluded' boolean attribute for the station:
        final Boolean isToolbarsIncluded = (Boolean) station.getAttribute("isToolbarsIncluded");

        //Dynamically set the main window's title based on the 'name' above:
        WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
            public void run() {

        //Also set the tab of the TopComponent to the 'name' value:

        //Set the text area's content, using the 'welcome text' above:

        //Hide the Help menu, using the boolean above:
        if (!isHelpMenuIncluded) {
            FileObject helpMenu = root.getFileObject("Menu/Help");
            if (helpMenu != null) {

        //Hide the toolbars, using the boolean above:
        if (!isToolbarsIncluded) {
            FileObject toolbars = root.getFileObject("Toolbars");
            if (toolbars != null) {

    } catch (IOException ex) {


This solution means that you need to be using the File System API, which provides the very powerful org.openide.filesystems.FileObject class that you see in action above. In effect, this API lets you very easily parse the layer.xml file, finding its elements and attributes and then converting them to strings, booleans, and so on. Another approach would be to use the NbPreferences class. However, in that case you'd be using properties files. That's less powerful than an XML file, because you simply have key/value pairs, instead of the hierarchical folder/file and element/attribute structure that the layer.xml file implies. I will blog about this second approach soon, at which point the disadvantages will become very clear, especially when compared to the above.


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.


« October 2008 »