Geertjan's Blog

  • April 11, 2008

Injecting a Layer File into a NetBeans Platform Application

Geertjan Wielenga
Product Manager
I tried the How to change menus, etc. after login? scenario today: "Since version 7.1 there is a way to change the content of system file system in a dynamic way. As system file systems contains various definitions (in NetBeans Platform menus, toolbars, layout of windows, etc.) it de-facto allows global change to these settings for example when user logs into some system."

The outline of what you need to do is described there, nothing I can really add. It is one new and cool way in which one module can contribute to an application. You start by creating a new module, add the XML layer defining the items you want to register in the system, then implement FileSystem, and export it to META-INF/services.

One scenario is that of a user logging into an application. On successful login, the layer file is injected and whatever is defined in the layer file is added to the application. I added a small touch—whatever the user sets as their user name determines the text in a new menu item that is added via the injected layer file. That's possible via the NbPreferences class, which can store preferences in the application's user directory.

Here's the whole module:

In the Installer, the login dialog is shown (as described elsewhere in this blog):

package org.yourorghere.addedsfs;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.JButton;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.modules.ModuleInstall;
import org.openide.util.Exceptions;
import org.openide.util.NbPreferences;
import org.xml.sax.SAXException;
public class Installer extends ModuleInstall {
JButton ok = new JButton();
JButton cancel = new JButton();
NotifyDescriptor.InputLine msg;
public Installer() {
ok.addActionListener(new OkActionListener());
private class OkActionListener implements ActionListener {//In real life, you'd have some login validation here!
public void actionPerformed(ActionEvent e) {
try {//Create a preference "USER_KEY", with value set to the input text:
NbPreferences.forModule(Installer.class).put("USER_KEY", msg.getInputText());//Specify the XML file that defines the layer you want to inject:
URL u = new URL("nbresloc:/org/yourorghere/addedsfs/newLayer.xml");//Pass the URL to the LoginFileSystem:
} catch (SAXException ex) {
} catch (MalformedURLException ex) {
public void restored() {
msg = new NotifyDescriptor.InputLine("Login:", "User name: ",
NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.QUESTION_MESSAGE);
msg.setOptions(new Object[]{ok, cancel});

And here's the LoginFileSystem (which is called by means of LoginFileSystem.assignURL(u) above):

package org.yourorghere.addedsfs;
import java.net.URL;
import org.openide.filesystems.MultiFileSystem;
import org.openide.filesystems.XMLFileSystem;
import org.xml.sax.SAXException;
public class LoginFileSystem extends MultiFileSystem {
private static LoginFileSystem INSTANCE;
public LoginFileSystem() {
// let's create the filesystem empty, because the user
// is not yet logged in
INSTANCE = this;
public static void assignURL(URL u) throws SAXException {
// Alternatively:
// Lookup lookup = Lookup.getDefault();
// LoginFileSystem INSTANCE = lookup.lookup(LoginFileSystem.class);
INSTANCE.setDelegates(new XMLFileSystem(u));

So then the URL that points to the newLayer.xml is used to create a new XMLFileSystem. The above class should be exported to META-INF/services, following the JDK 6 java.util.ServiceLoader approach.

And what about the preference that the user entered? Here you see the definition of the TestAction.getName method:

public String getName() {
Preferences pref = NbPreferences.forModule(TestAction.class);
String name = pref.get("USER_KEY", "");
return NbBundle.getMessage(TestAction.class, "CTL_TestAction") + name + "!";

So first some text (like "Hello") is retrieved from the bundle file, appended with the name that the user entered, appended with an exclamation mark. And the above menu item only appears if the login succeeds, which you'd need to make possible via hooking up your database of users to the module so that whatever the user enters can be verified against your database.

In other news. What technology evangelists really do for a living.

Join the discussion

Comments ( 13 )
  • Tom Wheelerr Friday, April 11, 2008

    Just in case it's not clear to readers, the "version 7.1" mentioned in the first sentence refers to the version of the FileSystems API included in NetBeans 6.1. There is not yet a version 7.1 of the NetBeans IDE or Platform.

  • Geertjan Friday, April 11, 2008

    Ah! Good point Tom, thanks!

  • Demetrios Kyriakis Saturday, April 12, 2008

    Hi Geertjan,

    Sorry for beeing offtopic (but you are the most known NB expert :) ):

    Is there a simple way to transform a Netbeans Platform based application into a JavaWebStart one?

    I mean I know how to make a javawebstart application (the process with signing and all those steps is not quite simple), but I don't know

    how to bring a NBplatform based to be one and to work without problems under the restricted conditions of the javawebstart.

    I saw in your articles hints about how to brand and also very important how to loose weight for a NBplatform application, so I thought maybe you have some ideas/hints about how to make it "webstartable" too.

    Thank you,


  • Geertjan Sunday, April 13, 2008

    Demetrios, right-click your application, choose "Build JNLP Application" or "Run JNLP Application".

  • Varun Friday, June 27, 2008


    I think it has huge scope! Login application is good to start with, however there could be many more things that can be achieved with this!

    For instance, Features-on-Demand, I think this could make good use of the above functionality, you stated. Correct me, if I'm wrong!


  • Geertjan Friday, June 27, 2008

    You're 100% right, Varun. This is exactly the functionality on which Feature on demand is based.

  • Varun Friday, June 27, 2008

    Awesome, looking forward to it!

  • Tom schroeder Monday, August 11, 2008

    Thanks for explanation!

    can I also do this not durring the startup of the module?

    if so, how can i refresh the table?

  • Jimena Friday, January 23, 2009

    Hi, I try it and I could make a new menu injecting a new layer.

    Now I want to hide a menu item or menu folder declared by other module wich was loaded before.

    I try to put into the layer the menu item name plus "_hidden" but I fail.

    layer.xml in one module declares

    <folder name="Menu">

    <folder name="MyMenuFolder"/>


    custom layer injected after declares

    <folder name="Menu>

    <folder name="MyMenuFolder_hidden"/>


    wat's wrong in my logic?

    I hide system menu folders like File and Edit by this mechanism (concatenate "_hidden") but can't hide folders declared by other modules

  • Jes&uacute;s Wednesday, October 29, 2014

    Hi Geertjan,

    I want to develop what you are explaining here, and the source code is clear but I have a compilation problem.

    I add the library required org.openide.filesystems and all classes are recognized by netbeans when writing my code source and I can click on Ctrl+mouse to go declaration methods of this API jar, but when I build my app, I get the message that the package does not exist for all import from filesystems API... I had never had something like that, is there any other jar that I sould include?

    C:\SW-TMTC\TMTC\MAIN\src\com\casaespacio\LoginFileSystem.java:8: package org.openide.filesystems does not exist

    import org.openide.filesystems.FileSystem;

    For giving more details, I am using netbeans 7.3.1 and including the jar library contained in netbeans. I have checked with netbeans 8.0 and the same. I have checked in Windows 7 and Windows XP and always the same

    Thanks in advance

  • Geertjan Wednesday, October 29, 2014

    The problem is clear, isn't it? You need a dependency on the File System API, i.e., org.openide.filesystems. Also, if at all possible, stop using 7.3.1 and use the latest version of the NetBeans Platform, 8.0.1.

  • Jes&uacute;s Wednesday, October 29, 2014

    ok, I'll use 8.0.1

    I have added the dependency correctly File System API to my module, that's why it is very strange because netbeans detects and know that the dependcy is ok because if I remove the dependcy then the red underline appears and when I readd the jar it dissapears. But the problem only appears in compilation time and I have tried all things in my mind but without chance...

    please, help

  • Geertjan Wednesday, October 29, 2014

    Not sure how I'm supposed to help? Are you sure the class you're referring is a public API? Anyway, if you remain stuck, do the following (1) remove the 'build' folder, (2) zip up the module, (3) and send it to me at geertjan dot wielenga at oracle dot com and I will look at it. But if your zip contains your 'build' folder, I will immediately delete your e-mail because that will mean the zip is very large and will break my inbox.

Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.