Geertjan's Blog

  • February 22, 2007

Programmatically Hiding Actions in NetBeans Platform Applications

Geertjan Wielenga
Product Manager
I got a very interesting question yesterday from two engineers from a local company, Samyak Infotech Pvt. Ltd., which is close to Hyderabad. They said they read my blog, so hopefully this will find them and not confuse them too much. :-) (No guarantees that the approach taken in this blog is correct, by the way.) They're obviously very advanced NetBeans module writers. Their question boiled down to the scenario where you have users in a database and, depending on whether their login succeeds, some additional menus are shown in the application's menu bar. How to implement this? Jesse Glick and Tonny Kohar gave some advice. It ended up being a bit of a puzzle and it still isn't complete, but here's the basic outline (and I'm hoping that it will make more sense to me as I write about it).

First, some pictures. In this scenario, the user types a name in the Options window. Ultimately, this would be connected somehow to a database and maybe you wouldn't use the Options window at all for this. However, to set the scene, I had to be able to type in a name somewhere. So here it is:

Now I click OK. Next (i.e., immediately), only if I typed "Tom", do I see the following menus:

If I do not type "Tom", then the above screenshot would not have (1) "Some", (2) "Menu for Tom", and (3) "Super secret submenu". All three of these would not be there. When I go back to the Options window and change the name to anything else, and when I then click OK in the Options window, all three of the above disappear. They reappear when I go back and enter "Tom" again.

If I understood it correctly, this is exactly what the engineers that I met wanted to implement.

So here are the pieces of this solution (I am sure there are other, and probably better, solutions, by the way):

  1. Use the Options window wizard to generate stubs for implementing a new category in the Options window's Miscellaneous panel. Use the Preferences API, as described in detail elsewhere in this blog, to persist the name typed in the text field.

  2. Use the Action wizard to create a stub for implementing a new menu item. However, delete the Menu entries generated in the layer.xml file. If you keep that entry there, under the Menu folder, the menu item will automatically be displayed. You do not want this to happen. You want it to be hidden. You will create the required entry in the NetBeans user directory programmatically in the next step, when the correct name is entered in the text field.

  3. Use the Module Installer wizard to create a stub for implementing a new module installer. Using a module installer in general is a bad idea, because it slows down start up time. However, how else is the application going to know at start up whether to show or hide the menu item? The module installer discovers that the login works (it is persisted via the Persistence API, so here the module installer retrieves the preference, which is also described in this blog) and then writes entries in the NetBeans user directory.

    Here's some code that I have in the installer. If name equals Tom, the code below creates the new folder Menu/Some. It then writes a shadow file with a reference to the action's actual instance class:

    //Create the folders:
    FileObject menuSomeFolder = Repository.getDefault().getDefaultFileSystem().getRoot().getFileObject("Menu/Some");
    if (menuSomeFolder == null) {
    try {
    menuSomeFolder = Repository.getDefault().getDefaultFileSystem().getRoot().createFolder("Menu/Some");
    } catch (IOException ex) {
    //Create the shadow file in the above folder,
    //with content connecting the shadow file to the real instance:
    FileObject newMenuItem = Repository.getDefault().getDefaultFileSystem().getRoot().getFileObject("Menu/Some/org-netbeans-modules-test-TestAction.shadow");
    if (newMenuItem == null) {
    try {
    newMenuItem = menuSomeFolder.createData("org-netbeans-modules-test-TestAction","shadow");
    FileLock lock = newMenuItem.lock();
    OutputStream out = newMenuItem.getOutputStream(lock);
    //In the shadow file, write the reference to the instance file,
    //which must match the registration in the module's layer.xml file:
    OutputStreamWriter out1 = new OutputStreamWriter(out, "UTF-8");
    } catch (IOException ex) {

    Note: The line Actions/Build/org-netbeans-modules-test-TestAction.instance matches the Actions registration entry generated by the Action wizard in my layer.xml file. This line is needed to connect the shadow file to the real Java class. (I discovered this after copying a menu item, in the Advanced section of the Options window, from one menu to another. When you do that, the IDE generates a shadow file in your NetBeans user directory. When you open that you will find just one line, which is in the format shown above.)

  4. At this point, I simply did a null check on the folders and shadow file. If they were not null, while the username was not Tom, the file objects are deleted. As a result, they are no longer in the NetBeans user directory. As a result of that, they're not in the menu bar either. Whenever the preference changes, the file objects for the folder and shadow file are either created or deleted. Simple and effective.

  5. Next, I used Jesse's suggestion of taking the NetBeans API DynamicMenuContent class. Here's the relevant code added to the action class created in step 2, in order to implement DynamicMenuContent:

    public JComponent[] getMenuPresenters() {
    JMenu m = new JMenu("Menu for " + Installer.getUserName());
    JMenuItem item = new JMenuItem("Super secret submenu");
    return new JComponent[] {m};
    public JComponent[] synchMenuPresenters(JComponent[] items) {
    return getMenuPresenters();

    So the name "Tom" is retrieved from the module installer, added as text to the menu, to which a submenu is added. However, since I created the folder Menu/Some, any shadow file in that folder, pointing to a corresponding instance file, is displayed in the new menu. So, I could create a whole new module (i.e., the third party vendor could do this too) and add my own action to the same folder, as shown here, where I've added "Some Other" menu item:

    In fact, the DynamicMenuContent class is not needed at all in this scenario, because all submenus are automatically retrieved from the layer.xml file's Menu/Some folder. However, the Action wizard doesn't show my original "Menu for Tom" action and neither do the nodes representing the layer.xml file. This must be a bug. Here's proof:

    So, before installing the "Some Other" action in the "Some" folder, the "Some" folder wouldn't have been visible in the screenshot above, even though I was working in an IDE which had the module including the "Menu for Tom" action installed in the "Some" folder.

Again, I don't know if this is the best approach, or even a good approach. But it works and it shows yet again the versatility of the NetBeans layer.xml file concept. I am able to show and hide menus and submenus, even entire actions, depending on a name set and retrieved by the Persistence API. In fact, note that I am not hiding the action, but showing it, because by default there is no action in this scenario. It is programmatically created and deleted as needed. And any third party vendor can add menu items as submenus below my action, since they're only going to be shown when the action is shown, which is exactly how one would want it. Hurray.

Postscript: Some caveats on this approach, received from Jesse: I'm unclear why you are modifying the SFS; you shouldn't need to, AFAIK. Generally modifying the SFS is a poor idea as changes are persisted to the userdir. It is also likely to be bad for performance. Anyway, if you do, use FileUtil.createData on Repo.default.defaultFS.root; and don't write that ugly URL to the body of the file, leave it empty but set the attr originalFile to the full path.

Join the discussion

Comments ( 14 )
  • guest Thursday, February 22, 2007
    Good morning, I’m a Cuban developer of software, and I’m very interesting in to learn and work with Net Bean, but I do not have access to the net bean site web, my country has not access to that side web, I’m needing documentation about net bean and examples, If there is somebody that may help me, send e-mail noel@mtz.desoft.cu.
  • Geertjan Thursday, February 22, 2007
    Hi Noel, I'm sorry, but for the same reason that your country doesn't have access to the NetBeans web site, I am not allowed to write to you.
  • Krish Friday, February 23, 2007
    Hi Geertjan,
    I am in the midst of evaluating NetBeans RCP to port our custom Swing App & have a somewhat similar requirement of enabling/disabling Menu Items depending upon which user has logged in the application. I am wary of the NB file system as its tied to the user's home directory & our target deployment scenario is to use WebStart with very little access to the user's disk. Can you advise on alternatives?
  • guest Friday, February 23, 2007
  • Geertjan Saturday, February 24, 2007
    Hi Krish. There is a different approach, much simpler, has no impact on the user directory, but doesn't remove the top most menu. So, you wouldn't be able to hide the "File" and "Edit" level menus. But, if you had your menus within one of these, as submenus (with their own submenus), then this other approach would work. I will blog about this soon. Would you be interested in this scenario. Please keep in touch and feel free to ask any questions. If we can help with your evaluations, please drop me an e-mail at geertjan.wielenga@sun.com.
  • Wiechu Wednesday, April 11, 2007
    You can simply override getMenuPresenter() and getToolbarPresenter() in your action and invoke there super.getToolbarPresenter().setVisible(false).
    Because this method is invoked only once, you can not return just null because you would not be able to recreate the action in case of relogin.


    public final class MyAction extends CallableSystemAction {

    //... all the generated stuff

    private JMenuItem menu; //for future reference

    public JMenuItem getMenuPresenter() {

    JMenuItem retValue;

    retValue = super.getMenuPresenter();

    menu = retValue;

    retValue.setVisible(false); //we disable it by default

    return retValue;

  • RatKing Thursday, May 24, 2007
    The following content is copied from http://www.netbeans.org/download/dev/javadoc/org-openide-filesystems/overview-summary.html
    How to change menus, etc. after login?
    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.
    First thing to do is to create an implementation of filesystem. It can be created either from scratch, or by subclassing AbstractFileSystem, or MultiFileSystem. In this example we will subclass the MultiFileSystem:
    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 {
    INSTANCE.setDelegates(new XMLFileSystem(u));
    It is necessary to register this instance in lookup by creating the file:
    with a single line containing the full name of your filesystem - e.g. your.module.LoginFileSystem. When done, the system will find out your registration of the filesystem on startup and will merge the content of the filesystem into the default system file system. You can show a dialog letting the user to log in to some system anytime later, and when the user is successfully in, just call LoginFileSystem.assignURL(url) where the URL is an XML file in the same format as used for regular layer files inside of many NetBeans modules. The system will notice the change in the content and notify all the config file listeners accordingly.
    Of course, instead of XMLFileSystem you can use for example memory file system, or any other you write yourself.
  • Anzaan Wednesday, June 13, 2007
    Hi Geertjan,
    I found it interesting that you declined to send email to the fellow Cuban who asked for some assistance. I don't know the circumstances and politics surrounding him not being able o access Netbeans site, but what politics stops you from responding to him really escapes me.
    I didn't realise learning stuffs was so heavily bound by politics that someone who posts all sorts of articles in the internet that is supposedly in the public domain for everyone to see, yet refuses to give assistance to people who look for assitence just because he hails from a country from a different political spectrum.
    I don't know how deeply you are involved with Netbeans. I can make a guess from following your posts and tutes for about a year now. If netbeans has issues with Cuba, does your Blog site and you yourself will have issues with Cuba automatically?
    From your, short and casual reply, its difficult for me to comprehend the mentality of people who apply the code of conduct, rules and regulation of their employer when it comes to sending an email for a bit of assitence.
    By the way, when you go to supermarket to do your groceries, do you boycott Cuban goods (if you actually find some )because Netbeans Org has issues with the Cuban Government?
    And did Netbeans have issues with Cuba because your Government has issues with it?...
    gee....I can write a whole friggin book on this issue....
    By the way, I use Netbeans at work as well as home and I follow your articles as I need to conduct research into Netbeans RCP to determine how deeply we should couple our application with NB Platform.
    I hope our country doesn't have issues with your country as I may be forced to boycott your articles from then on for political reasons. :)
    Meanwhile I'll try to gather as much as I can .....
    wish me luck.....
    and happy horizon.....
  • Geertjan Wednesday, June 13, 2007
    Sorry, please contact the Sun legal department about your legal questions. I can give you an e-mail address if you want. Thanks.
  • Glauco Thursday, December 2, 2010

    Hello, I'm from Brazil and this article almost solves my problem.

    I have a component that receives some object,

    then I read the methods that contain an annotation that I created.

    Then for each of these methods I have to create a button (action) on the toolbar, and each button should trigger the method of the object received by the component.


    public class someClass{

    @ ToolbarAction (name = "someAction" icon = "org/prj/resorces/icon1.pnj)

    public void someMethod () {... }

    @ ToolbarAction (name = "otherAction" icon = "org/prj/resorces/icon2.pnj)

    public void otherMethod () {... }


    If my component receives an instance of SomeClass, should appear two buttons on the toolbar.

    With this article I managed to add and remove actions on the toolbar, but actions always runs the same thing.

  • sivaprasad Sunday, February 6, 2011

    Hi Geertjan,

    When i am double click on node it display the children nodes..but i want disable this,how it is possible.

    thank you

  • guest Friday, March 2, 2012

    Hi, Geertjan. This works! I have two questions:

    1) The added menu item is disabled. How to enable it?

    2) When I try to undo the menu add by renaming xxx.instance to xxx_hidden.instance,

    there is an IllegalStateException: no selectionType parameter in {}

    at org.openide.awt.Actions.inject(Actions.java:698).

    Following your guidance, this is what the Action wizard added to Actions/Window:

    <file name="com-company-MyAction.instance">

    * <attr bundlevalue="com.company.Bundle#CTL_MyAction" name="displayName"/>

    <attr methodvalue="org.openide.awt.Actions.context" name="instanceCreate"/>

    * <attr name="type" stringvalue="com.company.MyTopComponent"/>

    * <attr methodvalue="org.openide.awt.Actions.inject" name="delegate"/>

    * <attr name="injectable" stringvalue="com.company.MyAction"/>

    <attr name="selectionType" stringvalue="EXACTLY_ONE"/>

    * <attr boolvalue="false" name="noIconInMenu"/>


    This is the code that tries to remove the new entry in Actions/Window by renaming

    the entry, taken from some other working code:

    String actPath = "Actions/Window/";

    String actFilename = "com-company-MyAction";

    String actExt = "instance";

    FileObject actObj = FileUtil.getConfigFile(actPath+actFilename+"."+actExt);

    if (actObj != null) { // If module found and enabled

    FileLock flock = null;

    try {

    flock = actObj.lock();

    // The next line gives IllegalStateException:

    actObj.rename(flock, actFilename + "_hidden", actExt);


    catch (IOException ex) {logger.error(ex);}

    finally {if (flock != null) {flock.releaseLock();} } }

    None of my other Action/Window entries have any of the attributes marked with * above,

    but that is what the Action wizard generated. How to overcome this?


  • Patrick Tuesday, March 26, 2013

    Hi Geertjan,

    i tried to implement this to my application (a storage management tool with different users login in) and it did not work out.

    Hers's the scenario:

    I'm having a login modul that authenticates the user. Now all actions appearing on the menu are created in annotations in the action class itself, e.g.

    @ActionID(category = "File",

    id = "org.myapp.ui.actions.neu.NewUserAction")

    @ActionRegistration(iconBase = "org/myapp/utils/icons/newUser.png",

    displayName = "#CTL_NewUserAction")


    @ActionReference(path = "Menu/Tools/Admin", position = 1)


    @Messages("CTL_BenutzerNeuAction=Add New User")

    public final class BenutzerNeuAction implements ActionListener {...}

    The result is a new menuitem: Tools -> Admin -> Add New User, but of course it is visible to all authenticated users.

    Now i want to hide that menuitem from not-admin users, or - even better - ged rid of:


    @ActionReference(path = "Menu/Tools/Admin", position = 1)


    and build this menuitem in my login-modul, eg.:

    (in the login-modul installer)

    if (user.getAdmin) {



    I'm not using the layer.xml right now, because - with 10 or more usergroups - this seems to much handwork for me.

    Do you think that is possible? And, if yes, any suggestions how to do this?

    Thank you,


  • Geertjan Tuesday, March 26, 2013

    I'd recommend using the layer. I.e., a different layer for each usergroup, each defining the UI that relates to the usergroup. Also, let's not have a long discussion about this here in a blog entry, rather join and write to the dev@platform.netbeans.org alias and discuss this there.

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