NetBeans Master Developer FAQ

How do I get sources for NetBeans using CVS?

For NB 6.0 please see WorkingWithNetBeansSources.

There are several methods of getting the source, detailed here: http://www.netbeans.org/community/sources/

For a development version:

cvs -d :pserver:anoncvs@cvs.netbeans.org:/cvs login
cvs -d :pserver:anoncvs@cvs.netbeans.org:/cvs co standard

For e.g. NetBeans 4.1, use -r release41.

Most Linux machines at least have the command-line CVS client installed by default - try typing simply cvs at a command prompt. You might want to visit any of several good sites such as http://www.cvshome.org/ which lists available CVS clients for different platforms, their strengths and weaknesses. Alternatively, you may wish to use the CVS support built into the NetBeans IDE itself. You should also read the Cederqvist manual included with most CVS clients for general information.

NOTE: Due to recent changes in the build for 6.0 http://www.netbeans.org/issues/show_bug.cgi?id=104290, you can no longer download source or javadoc for recent milestones of the NetBeans IDE or platform. Therefore, if you are extending the IDE or platform and want recent documentation or source code for reference, you will have to build NetBeans yourself.


Applies to: all versions of NetBeans

How do I add an action to my custom node type ?

You have to override the

public Action[] getActions( boolean context )
method of your node.

If this node is really a DataNode for your own file type, instead see How do I add an action to a file of a given mime-type?.

See also:

How do I add an action to a the popup menu of the Java editor?

You must declare your action in your layer.xml file. Like this:

<folder name="Editors">
 <folder name="text">
   <folder name="x-java">
      <folder name="Popup">
         <file name="org-mymodule-MyAction.instance"/>
</folder></folder></folder></folder></folder>

Prior to NB 4.2, you could use Editors/text/base/Popup/ to add an action to all editor kits. As of NB 4.2, use just Editors/Popup/ instead.

See also:

How do I add an action to a file of a given mime-type?

You must declare your action in your layer.xml file. Like this:

<folder name="Loaders">
   <folder name="text">
     <folder name="html">
        <folder name="Actions">
           <file name="org-mymodule-MyAction.instance">
</folder></folder></folder></folder>

Substitute "text/html" by "text/x-java" or "text/x-ant+xml" or "text/x-jsp" or "image/png".

However, this still may not work depending on how the data loader for the type works. The DataLoader implementation has to override actionsContext() and return this path if it wants to load the Action instances from there. If the data loader you are interested in does not yet do this, please first file a bug report to make sure this is fixed in a future release; as an inferior workaround, you can use e.g.

DataLoader loader = DataLoaderPool.getDefault().firstProducerOf(SomeDataObject.class);
if (loader != null) {
    SystemAction[] actions = loader.getActions();
    SystemAction[] newactions = new SystemAction[actions.length + 2];
    System.arraycopy(actions, 0, newactions, 0, actions.length);
    // More realistically: take care that it is not a duplicate,
    // place into a specific position, etc.:
    newactions[actions.length] = null;
    newactions[actions.length + 1] = SystemAction.get(SomeAction.class);
    loader.setActions(newactions);
}

You need to know the implementation class of the foreign data object to implement this workaround. You should avoid doing this unless it is really critical to usability, and replace it with layer-based declarative actions as soon as that is available (you did file that bug report, right?).

See also:

How do I add an action to a folder?

You must declare your action in your layer.xml file. Like this:

<folder name="Loaders">
 <folder name="folder">
   <folder name="any">
      <folder name="Actions">
         <file name="org-mymodule-MyAction.instance"/>
      </folder>
    </folder>
 </folder>
</folder>

See also:

How do I add an action to the menu bar?

You must declare your action in your layer.xml file. Like this:

<folder name="Menu">
   <folder name="File">
         <file name="org-mymodule-MyAction.instance"/>
</folder></folder>

See also:

CategoryNeedCleanup (There are two unrelated things being answered here: how to add an action to the context menu of someone else's project type; and how to implement the context menu for your own project type. Also code samples in second section are inadequate.)

How do I add an action to a project popup menu?

Just register an instance of the action in your XML layer under Projects/Actions/. It should be a ContextSensitiveAction, such as a CookieAction.

How do I add an action to a project node's popup menu?

public final class AddActionOperation implements CopyOperationImplementation {
    
    private final AddActionProject project; // suppose this is the 
    private final FileObject projectDir;
    
    public AddActionOperation(final AddActionProject project) {
        this.project = project;
        this.projectDir = project.getProjectDirectory();
    }
    
    public List/*<FileObject>*/ getMetadataFiles() {
        return Collections.EMPTY_LIST;
    }
    
    public List/*<FileObject>*/ getDataFiles() {        
        return Collections.EMPTY_LIST;
    }
    
    public void notifyCopying() throws IOException {
        System.out.println("Copying");
    }

    public void notifyCopied(Project project, File file, String string) throws IOException {
        System.out.println("Copied");
    }
}
public final class AddActionActions implements ActionProvider {
    
    private final AddActionProject project; //suppose this is your project
    
    public AddActionActions(AddActionProject project) {
        this.project = project;
    }
    
    public String[] getSupportedActions() {
        return new String[] {
            ActionProvider.COMMAND_COPY
        };
    }
    
    public boolean isActionEnabled(String command, Lookup context) {
        if (command.equals(ActionProvider.COMMAND_COPY)) {
            return true;
        } else {
            throw new IllegalArgumentException(command);
        }
    }
    
    public void invokeAction(String command, Lookup context) {
        if (command.equalsIgnoreCase(ActionProvider.COMMAND_COPY)){
            DefaultProjectOperations.performDefaultCopyOperation(project);
        }
    }
}
lookup = Lookups.fixed(new Object[] {
            this,
            state,
            new AddActionOperation(this),
            new AddActionActions(this),
            loadProperties(),
            new Info(),
            new AddActionLogicalView(this)
        });
public Action[] getActions(boolean context) {   
        Action[] nodeActions = new Action[2];
        nodeActions[0] = CommonProjectActions.copyProjectAction();
        nodeActions[1] = CommonProjectActions.closeProjectAction();
        return nodeActions;
    }

Only possible as of NB 4.2:

http://www.netbeans.org/download/dev/javadoc/org-netbeans-modules-projectuiapi/apichanges.html#ProjectActions

How do I add an action to a project popup menu of a specific project type?

You can install an action into the context menu of all projects simply by adding to your layer under the folder Projects/Actions/. Your action should be context-sensitive, meaning it should be a placeholder which implements ContextAwareAction; the context-aware derived action will do the real work. Generally it will look for an instance of Project in the supplied Lookup (context).

If you just override isEnabled on the derived action based on the context, the menu item will always be present, though it will be greyed out in the case of inappropriate projects. If you want to hide the menu item for all but relevant projects, you will need to make the derived action implement Presenter.Popup and the resulting component should also implement DynamicMenuContext.

This is a lot of boilerplate (hopefully a future revision of the APIs will make it simpler and/or the module development support will include a wizard for it), so it is better to show an example you can copy and customize. The following trivial action shows the location of a project so long as its name comes in the first half of the alphabet:

package projectcontextmenudemo;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.DynamicMenuContent;
import org.openide.awt.Mnemonics;
import org.openide.filesystems.FileUtil;
import org.openide.util.ContextAwareAction;
import org.openide.util.Lookup;
import org.openide.util.actions.Presenter;
public class DemoAction extends AbstractAction implements ContextAwareAction {
    public void actionPerformed(ActionEvent e) {assert false;}
    public Action createContextAwareInstance(Lookup context) {
        return new ContextAction(context);
    }
    private boolean enable(Project p) {
        assert p != null;
        // TODO for which projects action should be enabled
        char c = ProjectUtils.getInformation(p).getDisplayName().charAt(0);
        return c >= 'A' && c <= 'M';
    }
    private String labelFor(Project p) {
        assert p != null;
        // TODO menu item label with optional mnemonics
        return "&Info on " + ProjectUtils.getInformation(p).getDisplayName();
    }
    private void perform(Project p) {
        assert p != null;
        // TODO what to do when run
        String msg = "Project location: " + FileUtil.getFileDisplayName(p.getProjectDirectory());
        DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(msg));
    }
    private final class ContextAction extends AbstractAction implements Presenter.Popup {
        private final Project p;
        public ContextAction(Lookup context) {
            Project _p = (Project) context.lookup(Project.class);
            p = (_p != null && enable(_p)) ? _p : null;
        }
        public void actionPerformed(ActionEvent e) {
            perform(p);
        }
        public JMenuItem getPopupPresenter() {
            class Presenter extends JMenuItem implements DynamicMenuContent {
                public Presenter() {
                    super(ContextAction.this);
                }
                public JComponent[] getMenuPresenters() {
                    if (p != null) {
                        Mnemonics.setLocalizedText(this, labelFor(p));
                        return new JComponent[] {this};
                    } else {
                        return new JComponent[0];
                    }
                }
                public JComponent[] synchMenuPresenters(JComponent[] items) {
                    return getMenuPresenters();
                }
            }
            return new Presenter();
        }
    }
}

and here is how to register it:

<filesystem>
    <folder name="Projects">
        <folder name="Actions">
            <file name="projectcontextmenudemo-DemoAction.instance"/>
        </folder>
    </folder>
</filesystem>

Applies to: NetBeans 5.0, 5.5

How do I add an action to the Toolbar?

You must declare your action in your layer.xml file. Like this:

<folder name="Toolbars">
   <folder name="Build">
         <file name="org-mymodule-MyAction.instance"/>
</folder></folder>

See also:

How do I create an Action that is automatically enabled and disabled depending on the selection?

There are three ways to do this, depending on what exactly you need:

CookieAction

CookieAction is used to write actions that are sensitive to what is in the selected Node(s) Lookup. You can specify one or more classes that must be present in the selected Node's Lookup, and some other semantics about enablement.

Being an older class, under the hood it is using Node.getCookie(), so your action will only be sensitive to things actually returned by that method - in other words, only objects that implement the marker interface Node.Cookie can work here.

NodeAction

NodeAction is somewhat more flexible, but requires more code to implement. It is just passed the array of activated nodes whenever that changes, and can choose to enable or disable itself as it wishes. Essentially this is just an action that automagically tracks the global Node selection.

Roll your own

The following is relatively simple and affords a way to perform whatever enablement logic you like (NodeAction can do that too, but this might be a little more straightforward and your code doesn't have to worry about Nodes at all). To understand how this works, see the section on the global action context:

public class FooAction extends AbstractAction implements LookupListener, ContextAwareAction {
    private Lookup context;
    Lookup.Result lkpInfo;

    public FooAction() {
        this(Utilities.actionsGlobalContext());
    }

    private FooAction(Lookup context) {
        putValue (Action.NAME, NbBundle.getMessage(FooAction.class,
                "LBL_Action")); //NOI18N

        this.context = context;
    }

    void init() {
        assert SwingUtilities.isEventDispatchThread() 
               : "this shall be called just from AWT thread";

        if (lkpInfo != null) {
            return;
        }

        //The thing we want to listen for the presence or absence of
        //on the global selection
        Lookup.Template tpl = new Lookup.Template(Whatever.class);
        lkpInfo = context.lookup (tpl);
        lkpInfo.addLookupListener(this);
        resultChanged(null);
    }

    public boolean isEnabled() {
        init();
        return super.isEnabled();
    }

    public void actionPerformed(ActionEvent e) {
        init();
        Collection c = lkpInfo.allItems();
        //do something with them here
    }

    public void resultChanged(LookupEvent ev) {
        setEnabled (lkpInfo.allItems().size() != 0);
    }

    public Action createContextAwareInstance(Lookup context) {
        return new FooAction(context);
    }
}

How do I make my Node have a submenu on its popup menu?

Override getActions(). Create a custom subclass of javax.swing.Action which implements the interface Presenter.Popup. Return a JMenu with whatever you want on it from getPopupPresenter(). Return that action in the array of actions from getActions().

How do I can I add an action to the Tools menu for every node ?

You need to add a section to your module's manifest denoting your action as a 'tools action.'

This section should look similar to this:


Name: com/tomwheeler/example/dataimport/wizard/DataImportCookieAction.class
OpenIDE-Module-Class: Action

Don't forget to put the extra space above it, since manifest sections need to be separated this way. This method will be deprecated sometime in the future and replaced by an entry in the layer file.

See also:

What is the Actions folder in the system filesystem, and why should I use it?

You may have noticed that the examples of adding actions typically look like this:

<folder name="Actions">
   <folder name="Build">
     <file name="com-foo-SomeAction.instance"/>
   </folder>
</folder>

<folder name="Menu">
   <folder name="Build">
     <file name="pointerToComFooSomeAction.shadow">
        <attr name="originalFile" stringvalue="Actions/Build/com-foo-SomeAction.instance"/>
     </file>
   </folder>
</folder>

And you may have noticed that actions are usually put, not directly into the Menu/ folders, but into subfolders of this Actions/ folder. Then we create .shadow files that act like symbolic links, pointing to the real .instance file . Why all this indirection?

The default UI in NetBeans includes the ability to rearrange, and even delete, whole menus or individual menu items. Many applications built on NetBeans will not want to expose such customizability, but some do. The Actions/ folder is shown in the options dialog (and also used from the key bindings editor); it makes it possible for a user to delete an action from menus and toolbars, but still be able to restore it at a later date - if there were not some UI for this, any deleted action would effectively disappear from the universe, as far as the user was concerned.

I have a reference to an existing Node from some other module. Can I add cookies/properties/actions/children?

No.

Occasionally people want to do something like this, because they want to enhance, for example, the behavior or nodes for Java files or other nodes created by some other modules. However, this is a recipe for disaster - nobody writing a Node subclass does so expecting that random modules will change its internal structures without warning. It is possible to write code that does this sort of thing that looks like it works, but it is sheer luck and it will probably not work for long.

DO NOT DO THAT UNDER ANY CIRCUMSTANCES

(there, did I say that strongly enough?).

Many modules are designed for extensibility - in fact, Nodes for Java files in the IDE do allow you to add children, actions, etc. They offer an API for doing this sort of thing (for example, adding Actions to Loaders/text/x-java/Actions declaratively); see the beans module for an example of adding sub-nodes to Java classes.

If you want to modify the children/properties/actions/etc. of a Node you did not create, look for an API that lets you do that in a supported way.

If one does not exist, file an enhancement request against the module that actually creates these nodes, asking for an appropriate API for doing what you want (and be clear about exactly what you want or why). If you really want to expedite it, write a patch that creates such an API (look at how other modules do this sort of thing and aim to follow a similar pattern) - it's hard to say no to working code.

Can I add or remove children of a node on the fly?

Yes. Have your node subclass AbstractNode or whatever else you like.

NB 6 > m9 Specific: Implement ChildFactory. To create the Children object for your Node, pass it to Children.create(). When the child list needs updating, call refresh() on your ChildFactory. Its createKeys method will be called again and you can update the set of key objects as needed; Nodes for objects that remain in the list of keys will simply continue to exist; additions and removals will be handled.

NB 5 And Earlier: Have your Children object subclass Children.Keys . As needed, call setKeys() on the Children.Keys object. Just by passing a larger or smaller (or reordered) list of keys, you will be adding or removing (or reordering) children.

Do not ever try to add/remove children from a node you did not create (unless it has an API that explicitly gives you permission to do that); occasionally people try to add child nodes to nodes for things like Java files. If it works at all it's by accident.


Applies to: NetBeans 4.0, 4.1, 5.0

What are the basic things I should know about NetBeans' architecture to get started?

The most important thing is to know what you are trying to do clearly, so you can find what you need to get started quickly. Here are some basic NetBeans factoids which will either answer some questions or whet your appetite for more information:

A lot of things in NetBeans are based around file recognition and using files to provide Java objects. Even if your application has nothing to do with editing files, this may still be very useful to you, since the same mechanism that recognizes/displays a user's files on disk also recognizes/displays configuration data (which may not even be files in the traditional sense at all), and such "files" can actually be factories for whatever kind of object you want (and that way you get persistence of those files for free).

For example, the FeedReader tutorial simply serializes POJO Feed objects into the configuration filesystem , and its whole UI consists of aiming a standard tree component at a folder full of those objects, and providing a few actions to let the user create more of them. When the application shuts down, it does not need to any special code for persisting them, it is all automatic.

For more information about how that works, see the section on file recognition.

One of the most basic and important things to know about is how modules register objects - this is mainly done through a configuration file inside the module's jar file (if you are using NetBeans 5.0 or greater's module building support, you can usually avoid hand-editing this file). Most things a module does to influence the environment are declarative rather than programmatic - in other words, you put some text in an XML file, or an entry in a jar manifest, or a file in some specific place in the module jar, and your functionality will be discovered when the system starts up - as opposed to writing java code.

Two of the most common needs are opening custom Swing components in the UI, and installing actions in the main menu .

Other basic topics that are worth reading to get the lay of the land are:

There are various tutorials, and the canonical reference to NetBeans APIs is the API javadoc .

How to create Java EE Application Client on top of NetBeans Platform

This is based on Lukas Jungmann's blog, which shows one way how to deal with current issues. Unfortunately if the application client is made that way one cannot use any enterprise resources. See also How to call EJB from NetBeans module.

Follow first three steps described at the beginning of the blog entry - build JNLP Application, edit build script and edit application client's main class. Then follow this guide to resolve issues:

issue 1 : java.lang.Error during application startup
Not resolved yet - there could be maybe some problems if you will use some NetBeans specific protocol in your platform based application (such as nbres://)

issue 2: application user directory is not created in correct location
This can be easily fixed eg. by passing --userdir <path-to-userdir> to org.netbeans.Main (btw. thanks Gergely Dombi)

issue 3: warning that Database Schema module cannot be installed because of missing dependencies
This issue is fixed in GlassFish-v2-b26 and newer.
In case you're using SJS Application Server 9.0, 9.0 UR1 or some older build of GlassFish then you have to remove all OpenIDE related entries from the manifest of $GLASSFISH_HOME/lib/dbschema.jar, so its manifest will be just:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.5
Created-By: 1.4.2_09-b05 (Sun Microsystems Inc.)

issue 4: java.io.FileNotFoundException: Windows2/WindowManager.wswmgr is thrown right after opening application's main window
This issue is fixed in GlassFish-v2-b27 and newer.
See issue in GlassFish for more details.

Java EE Application Client on top of the NetBeans Platform Tutorial

Draft

This is document currently has draft status

This tutorial will show you how easy is to create an application client on top of the NetBeans Platform. It will be demonstrated on the example of Database Reader.

Table of Contents



Requirements

Installation And Configuration

Install all of the required products (installation guides are available on the product's websites). When it'll be done we have to set up a few things. First of all please start NetBeans IDE 5.5.1 and register GlassFish v2. Right click on the Servers node in the Runtime tab and select Add server (choose Sun Java Application Server).

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/addserver.png

Now we need to register NetBeans Platform into IDE. It's in fact almost same as to add a new server. In menu Tools -> NetBeans Platform Manager click on a Add Platform button and pass through the wizard (as a new platform select downloaded NetBeans Platform 5.5.1).

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/addplatform.png

Projects Creation

It's time to create all projects. We need NetBeans Module Suite project, NetBeans Module (added into your NetBeans Module Suite) project and Enterprise Application project with Application Client and EJB module included. Let's do it. First of all we create NetBeans Module Suite project. Call it dbreader. As used platform choose the new one what you registered before.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/createsuite1.png

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/createsuite2.png

Then create NetBeans Module Project. Call it customers. And check that you want to add it into your dbreader suite. All other options leave as default.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/createmodule.png

Actually we have had NetBeans Modules created and now we have to create Java EE part. So let's create an Enterprise Application with Application Client and EJB module. Call it dbreader-ear. Include Application Client and EJB module. Exclude Web module. Also select Java EE 5 version and choose Sun Java Application Server as development server.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/createear1.png

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/createear2.png

Great ! You have successfully created all required projects. Now you should see something like this in Projects tab.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/projects.png

Enterprise Application Development

Build Script Modifying

We need to modify dbreader-ear build.xml script because the dbreader suite jnlp distro has to be packed into dbreader ear. Due to add these lines into dbreader-ear build.xml.

    <property name="dbreader.home" value="../"/>
    
    <target name="build-dbreader-jnlp">
        <java classname="org.apache.tools.ant.Main" dir="${dbreader.home}" failonerror="true" fork="true">
            <jvmarg value="-Dant.home=${ant.home}"/>
            <arg value="build-jnlp"/>
            <classpath path="${java.class.path}"/>
        </java>
    </target>
    
    <target name="pre-dist" depends="build-dbreader-jnlp">
        <!-- dbreader.home must point to DatabaseReader Application home directory -->

        <mkdir dir="${build.dir}/lib"/>
        <copy todir="${build.dir}/lib">
            <fileset dir="${dbreader.home}/build/jnlp/app" includes="*.jar" />
            <fileset dir="${dbreader.home}/build/jnlp/branding" includes="*.jar" />
            <fileset dir="${dbreader.home}/build/jnlp/netbeans" includes="*.jar" />
        </copy>
    </target>

You are able to access build.xml file in Files view.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/editearbuild1.png

After editing you should see something like this.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/editearbuild2.png

Generating Entity Classes From Database

We have dbreader-ear project infrastructure prepared. Now we have to generate entity classes from sample database. Right click on dbreader-ear-ejb project in Project tab and select New -> Entity Classes From Database. In wizard chose as datasource jdbc/sample datasource and select CUSTOMER table.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/generateentity1.png

On the next wizard panel type package for entity classes. Type db. Then Click on create persistence unit. Persistence unit dialog will appear. Click on Create. Now finish the wizard by clicking on the Finish button.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/generateentity2.png

Now we have generated entity classes from jdbc/sample database. Under dbreader-ear-ejb project you can see generated classes.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/generateentity3.png

Create Session Bean

We need to create stateless session bean with remote interface to communicate with persistence unit. Create one and call it DataBean.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/createsession1.png

When you have session bean created add business method called getData. You are able to do it by right clicking on the editor pane (in DataBean.java file opened) and select EJB Methods -> Add Business Method. Pass through the wizard and create getData method which returns java.util.List.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/createsession2.png

Now use entity manager. Once again do a right click on the editor pane and select Persistence -> Use Entity Manager. Entity manager code is generated. Now implement getData method.

    public List getData() {
        //TODO implement getData
        return em.createQuery("SELECT c FROM Customer c").getResultList();
    }

After that you should see in editor (in DataBean.java file) something like this.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/createsession3.png

Modify Application Client

We prepared EJB module and now we have to implement functionality into dbreader-ear-app-client Application Client module. Open Main.java file in dbreader-ear-app-client project.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/modifyappclient1.png

Now call your session bean DataBean. Right click on editor pane and select Enterprise Resources -> Call Enterprise Bean. In the dialog select your DataBean and click OK.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/modifyappclient2.png

Now we need to implement main method and create getCustomers method. Before that add <dbreader_project_home>/build/jnlp/netbeans/boot.jar file on classpath. Do it by right clicking on dbreader-ear-app-client project and select Properties. There select Libraries and then click on Add JAR/Folder and in open file dialog select boot.jar file. Don't forget to uncheck the checkbox. We do not want to package this file with dbreader-ear-app-client module. Actually you have to run build-jnlp target on dbreader suite. Before that please perform step Set Up Suite. Then you can right click on dbreader project and select Build JNLP Application.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/modifyappclient3.png

Implement main method by this code.

    public static void main(String[] args) {
        try {
            String userDir = System.getProperty("user.home") + File.separator + ".dbreader";
            org.netbeans.Main.main(new String[] {"--branding", "dbreader", "--userdir", userDir});
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

Now create getCustomers static method.

    public static List getCustomers() {
        return dataBean.getData();
    }

After doing this you should see something like this in editor pane.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/modifyappclient4.png

Great ! We have finished development of the dbreader-ear Enterprise Application. Let's go to develop NetBeans Modules.

NetBeans Modules Development

Set Up Suite

Now we set up the dbreader NetBeans module suite. We have to set it as standalone application and also we are able to change splash screen. Right click on dbreader project and select Properties. There select Application and then click on the Create Standalone Application.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/setupsuite1.png

Also you are able to set up your own splash screen. Do it by same way and under the Application node in project Properties click on Splash Screen.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/setupsuite2.png

Set Up Module

Now we set up the customers NetBeans Module. We have to add dbreader-ear-ejb.jar, dbreader-ear-app-client.jar and javaee.jar on compile classpath. First of all set sources level of the module to 1.5. Right click on customers project and on the first panel select 1.5 for sources level.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/setupmodule1.png

Open project.properties file from project tab.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/setupmodule2.png

Add this code into project.properties file. Of course use your own path to dbreader and glassfish.

cp.extra=\
/home/marigan/temp/dbreader/dbreader-ear/dbreader-ear-ejb/dist/dbreader-ear-ejb.jar:\
/home/marigan/temp/dbreader/dbreader-ear/dbreader-ear-app-client/dist/dbreader-ear-app-client.jar:\
/home/marigan/apps/glassfish/lib/javaee.jar

After that you should see something like this in editor pane.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/setupmodule3.png

Create Window Component

Now we create a new window component which will serve as viewer for database data. Right click on customers project and select New -> Window Component. On the first wizard panel choose editor as Window Position and select Open on Application Start.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/createwindow1.png

On the second panel specify component Class Name Prefix (use Customers) and finish the wizard.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/createwindow2.png

After that you should see this in Project tab.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/createwindow3.png

Write Customers Top Component Logic

We have to write application logic for customers top component. Open CustomersTopComponent.java file in design mode and drag and drop a jTable component from palette into it.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/writelogic1.png

Now switch into source view and modify constructor and add initData method.

    private CustomersTopComponent() {
        initComponents();
        setName(NbBundle.getMessage(CustomersTopComponent.class, "CTL_CustomersTopComponent"));
        setToolTipText(NbBundle.getMessage(CustomersTopComponent.class, "HINT_CustomersTopComponent"));
//        setIcon(Utilities.loadImage(ICON_PATH, true));
        
        initData();
    }
    
    private void initData() {
        List<Customer> data = Main.getCustomers();
        
        Object[][] rows = new Object[data.size()][3];
        int i = 0;
        
        for (Customer c : data) {
            rows[i][0] = c.getName();
            rows[i][1] = c.getEmail();
            rows[i++][2] = c.getPhone();
        }
        
        Object[] colums = new Object[] {"Name", "E-mail", "Phone"};
        
        jTable1.setModel(new DefaultTableModel(rows, colums));
    }

After that you should see something like this.

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/writelogic2.png

Run Application

Great job !! Everything is done. Now you can run your application. Right click on dbreader-ear project and select Run Project. Wait a minute do build and glassfish to start. Enjoy your application :o)

http://wiki.netbeans.org/wiki/attach/DevFaqAppClientOnNbPlatformTut/runapp.png

Becoming a Proficient NetBeans Module Developer

NetBeans has a learning curve. The goal of this article is to get you over the basic humps quickly. Being proficient does not necessarily mean knowing everything there is to know. It means being able to find what you need to know quickly when you need it. Here are some pointers.

All of the documents linked here are also available from del.icio.us.

It's a good thing to bookmark.

Javadoc

The reference documentation for all of NetBeans APIs can be found on the web here: http://www.netbeans.org/download/dev/javadoc/

If you want a local copy of it, you can either download it from the update center, or build it from your source checkout

cd $NB_SRC_ROOT/nbbuild
ant build-javadoc

Using the Javadoc

Notice the list of APIs in the upper left in the javadoc. These restrict the list of classes to a single API. /Also notice the link that says _javadoc_ next to each API name. It's important! This links to the overview page for each API. That page contains a list of changes, an architecture description, and other very useful stuff!/

NetBeans Tutorials

There are a huge number of tutorials. Do at least some of them - step by step.

FAQs

There is a huge Frequently Asked Questions for Module Developers list. It is worth bookmarking.

Getting the Source Code

Some people claim that they should never need to look at source code - documentation should suffice. That's just silly. The NetBeans codebase is a treasure-trove of examples of how to do things. Here's how to get the sources:
cvs -d:pserver:anoncvs@cvs.netbeans.org:/cvs co -P standard_nowww
You will end up with a large number of directories representing top-level NetBeans projects. Most of them will be openable as projects in NetBeans. Most have additional module projects underneath them.

Here's how to build it: In NetBeans, open the nbbuild project, right click it and choose the build item from the menu. Or, from the command line:

cd $NB_SRC_ROOT/nbbuild
ant build-nozip
The build of NetBeans will be created in nbbuild/netbeans. Note, if the build fails saying that a directory javahelp/i18n exists, you didn't pass -P to CVS. Back up a directory and run cvs update -P -d to prune empty directories, then try the build again.

How To Find Useful APIs

See the tasks to APIs faq for a list of common tasks and what APIs you will want to use to accomplish those tasks.

Get the Platform Examples

There are a large number of samples. Many of these correspond to the tutorials. To get them, do a CVS checkout of the CVS module platform from netbeans.org. They are in the samples/ subdirectory.

Build Platform from Sources

First get platform sources from download page or use CVS to get desired version with command
cvs -d:pserver:anoncvs@cvs.netbeans.org:/cvs -q -z6 co -P apisupport autoupdate core editor graph libs nbbuild openide projects
To build platform run
cd $NB_SRC_ROOT/nbbuild
ant build-platform
You may need to add -Dverify.checkout=false if you get error about missing modules ie.:
ant -Dverify.checkout=false build-platform
It depends on version of sources.

Mining the NetBeans Source Code for Examples

For most things you will need to do, there is some module that does something similar already. For example, say that you want to show a window that shows the contents of some random directories on disk or some registry of objects your module creates. The core/favorites module provides the Favorites window which does exactly this. A bit of intuition and a willingness to open a couple of projects is all it takes to find examples of many things. Often a good place to start is simply to open the source for a class you think you want to use and run Find Usages on it.

Use the Mailing Lists

If you have questions, the best place to go is the developer mailing list. Click this link to subscribe. You can also get there via a newsreader by going to news://news.gmane.org or access them on the web via Nabble. Ask questions, and when you can answer them, do that too. There is a very healthy and helpful community there.

How to call EJB from NetBeans module

This How-To is based on GlassFish EJB Faq

How to call EJB from Java EE Application Client built on top of NetBeans Platform

Important: Application Client must be created as it is described in How to create Java EE Application Client on top of NetBeans Platform otherwise this will not work

Example

protected mypkg.MySessionBeanRemote lookupMySessionBean() {
    try {
        javax.naming.Context c = new javax.naming.InitialContext();
        return (mypkg.MySessionBeanRemote) c.lookup("java:comp/env/ejb/MySessionBean");
    } catch(javax.naming.NamingException ne) {
        java.util.logging.Logger.getLogger(getClass().getName()).log(java.util.logging.Level.SEVERE,"exception caught" ,ne);
        throw new RuntimeException(ne);
    }
}
<ejb-ref>
    <ejb-ref-name>ejb/MySessionBean</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref-type>
    <remote>mypkg.MySessionBeanRemote</remote>
</ejb-ref>

How to call EJB from standalone module/NB platform based application

Call EJB on GlassFish

Example

run.args.extra=-J-da -J-Dorg.omg.CORBA.ORBInitialHost=localhost -J-Dorg.omg.CORBA.ORBInitialPort=3700 \
               -cp:a $GLASSFISH_HOME/lib/appserv-rt.jar:$GLASSFISH_HOME/lib/appserv-ext.jar:\
                     $GLASSFISH_HOME/lib/appserv-deployment-client.jar:$GLASSFISH_HOME/lib/javaee.jar:\
                     $GLASSFISH_HOME/lib/jmxremote_optional.jar:someejb.jar
to module suite project.properties
// for EJB 3.0 bean
protected mypkg.MyBeanRemote lookupMyBeanRemote30 throws NamingException {
    javax.naming.Context ic = new javax.naming.InitialContext();
    return (mypkg.MyBeanRemote) ic.lookup("mypkg.MyBeanRemote");
}

// for EJB 2.1 and/or earlier
protected mypkg.MyBeanRemote lookupMyBeanRemote21 throws NamingException {
    javax.naming.Context ic = new javax.naming.InitialContext();
    Object remote = c.lookup("java:comp/env/ejb/MyBean");
    mypkg.MyBeanRemoteHome rv = (mypkg.MyBeanRemoteHome) PortableRemoteObject.narrow(remote, mypkg.MyBeanRemoteHome.class);
    return rv.create();
}


Applies to: NetBeans 5.5, 6.0

Platforms: all

How can I change my node's appearance?

It's pretty simple to change the font color, style or weight for your node's label. Simply override getHtmlDisplayName and provide some HTML in your return value. The javadoc for the HtmlRenderer class explains what subset of HTML is supported. You can also change the icon's node by overriding various methods such as getIcon(int type) or getOpenedIcon().

It's also possible, but far more difficult, to control other aspects of the node's appearance; for example, drawing a box around the node or changing its background color. To do this you must create or modify the explorer view in which the node is rendered. Fabrizio Giudici posted code that illustrates this on the dev@openide list.

How Can I Change the NetBeans Splash Screen Shown When A User Installs a Module Requiring Restart?

The splash screen is here:

 
    autoupdate/services/libsrc/org/netbeans/updater/resources/updatersplash.gif 

You should be able to brand this as normal, by creating a file in your module at this same path (including the branding token).

What classloaders are created by the module system?

Overview

This FAQ item should be a companion to the main classpath documentation. Please refer to the original document for additional details.

Classloaders in the NetBeans platform

There are basically three main classloader types used in the platform. Most of the code should be loaded by the Modules classloader. Only in justified special cases the System classloader can be used - e.g. when you need access to resources from all the modules. And finally the resources directly on the classpath from the launch script are loaded by the original classloader (the term boot classloader might be a bit confusing because of the bootstrap classloader used by the JVM).

Most of the classloaders in the NetBeans platform are multi-parented classloaders. This means that the classloader can have zero or more parents. When looking for a resource the classloader uses this algorithm (implemented in class org.netbeans.ProxyClassLoader):

Modules Classloader

Every module registered by the module system creates one instance of the Module classloader. The classloader loads resources primarily from the module's jar file. This classloader is able to load from more jar files (besides having more classloaders as parents). The original (application) classloader is implicitly one of the parents of each module's classloder - always at the first position.

The implementation class as of this writing (NetBeans 5.5) is org.netbeans.StandardModule$OneModuleClassLoader. The ability to use more jar files is implemented in its superclass org.netbeans.JarClassLoader.

System Classloader

The system classloader is regular multiparented classloader that has as its parents all module's classloaders. It is accessible via call to the global lookup (ClassLoader)Lookup.getDefault().lookup(ClassLoader.class); or by using the fact that it is the context classloader on most of the threads: Thread.currentThread().getContextClassLoader();.

Original (application, JNLP) Classloader

This classloader is set up by the launching script. It is usually able to load classes from the original CLASSPATH plus clontents of the folder lib (with usual subfolder lib/ext). If a jar is loaded by this loader and it does not have proper manifest information required by the NetBeans module system the contained resources "bypass" the NetBeans module system. Also such resources are always found first if by accident the same resource is contained here and in a module jar (the module supplied resource is ignored in such case). It is generally discouraced to use this classloader for loading anything in the platform but it is sometimes needed e.g. for the Look And Feel classes (that has to be loaded very early during the startup sequence).

Example

example.gif

Let's have a very simple module a:

Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.modules.a

and module b depending on a:

Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.modules.b
OpenIDE-Module-Module-Dependencies: org.netbeans.modules.a
Class-Path: ext/library-a-1.0.jar ext/library-b-1.1.jar

Module b also declares a dependency on 2 external libraries - they will be loaded by the very same classloader as b.

I have written a module for NetBeans. Can I contribute it to the NetBeans project?

Yes. In fact, once you have some code written, request the developer role on contrib.netbeans.org (you need to have an account and be logged in to see the link), so you have write access to CVS there, and go ahead and check it in. You will need to sign a Contributor Agreement to get CVS write access.

For more info on how to start module projects or join existing ones, see the contributing page on netbeans.org .


If you have initially written the module as a standalone module project using the NB 5.0 IDE, beware that the format for module projects inside the netbeans.org CVS tree is slightly different. To convert a standalone module project to a netbeans.org module:

  1. . Close your module and shut down the IDE, just to be safe.
  1. . Copy the module into the desired location in the netbeans.org CVS source tree.
  1. . Open nbproject/project.xml and delete the line <standalone/>.
  1. . Delete =nbproject/genfiles.properties=, =nbproject/platform.properties=, and =nbproject/build-impl.xml=.
  1. . Open build.xml and change <import file="nbproject/build-impl.xml"/> to <import file="../../nbbuild/templates/projectized.xml"/> (assuming a second-level module like =contrib/foo=; adjust number of ../ occurrences as needed).

Now you ought to be able to open the new project in the IDE and work with it as usual.

If you had specified an explicit NBM license (=license.file=) before, you might just remove it - netbeans.org modules by default use nbbuild/standard-nbm-license.txt which is appropriate for any SPL module with no external (non-SPL) components.

If you had a module suite project with several module suite component projects, just discard the suite project (netbeans.org modules cannot reside in suites) and copy the component module projects into the netbeans.org CVS tree. You will be deleting <suite-component/> from project.xml and deleting suite.properties rather than platform.properties but the process is otherwise similar.

A future release of the module development support should permit you to simply select Move Project or Copy Project from the GUI and handle these format changes automatically.

How do I create a TopComponent to show an explorer view?

Explorer views are generic Swing components, not subclasses of TopComponent , the Swing panel class that is used for top level components (tabs) in the main window. So an explorer view component is added to a TopComponent, using the TopComponent as a Swing container for the view.

A little bit of plumbing is needed to wire up an explorer view to the global Node selection so that code that is sensitive to selection such as context sensitive actions . Basically you want the TopComponent to expose the selection in your Explorer View so that when your view has focus, the global selection that affects everything will be whatever the user selects in your view.

In olden times, there was a convenient class called ExplorerPanel (now in org.openide.compat ) which would do this for you; due to a tragedy of being in the wrong package, it is now deprecated, but the required plumbing is not hard:

public class MyView extends TopComponent implements ExplorerManager.Provider {
    private final ExplorerManager manager = new ExplorerManager();
    private final JComponent view = new BeanTreeView();
    public MyView() {
        setLayout (new BorderLayout());
        add(view, BorderLayout.CENTER);
        manager.setRootContext(someNode);

        // Probably boilerplate (depends on what you are doing):
        ActionMap map = getActionMap();
        map.put(DefaultEditorKit.copyAction, ExplorerUtils.actionCopy(manager));
        map.put(DefaultEditorKit.cutAction, ExplorerUtils.actionCut(manager));
        map.put(DefaultEditorKit.pasteAction, ExplorerUtils.actionPaste(manager));
        // This one is sometimes changed to say "false":
        map.put("delete", ExplorerUtils.actionDelete(manager, true));
        // Boilerplate:
        associateLookup(ExplorerUtils.createLookup(manager, map));
    }
    // This is optional:
    public boolean requestFocusInWindow() {
        super.requestFocusInWindow();
        // You will need to pick a view to focus:
        return view.requestFocusInWindow();
    }
    // The rest is boilerplate.
    public ExplorerManager getExplorerManager() {
        return manager;
    }
    protected void componentActivated() {
        ExplorerUtils.activateActions(manager, true);
    }
    protected void componentDeactivated() {
        ExplorerUtils.activateActions(manager, false);
    }
}

The primary difference between the above code and ExplorerPanel is that ExplorerPanel automagically persisted paths from the selected nodes to the root, so that it could be deserialized on restart with the same selection it had before shutdown (assuming that selection still existed - this was never terribly robust).

-- Main.timboudreau w/ cut & paste from Jesse Glick - 17 Sep 2005

What is thestandardmodule, and how does it differ from stable?

It doesn't. stableis the older name; use standard.

You can list all alias used in the netbeans.org CVS server using

cvs co -c

or the IDE's CVS client. There's a lot of junk in there, so briefly, the important aliases:

cvs co -r release50 standard

You need to do

cvs co -r release50 standard50

standard_nowww is like standard but excludes */www subdirectories, which makes the checkout faster. (These subdirectories are not needed for the build; they just contain module website docroots.) You might get these directories anyway if you then do an update, unfortunately.


Applies to: NetBeans 3.6, 4.0, 4.1, 5.0

What is a DataLoader?

DataLoaders recognize files by type - type is typically determined by the file extension, though it can depend on content for things like XML files. They are the mechanism by which NetBeans recognizes files.

DataLoaders are factories for DataObjects. Typically there is a 1:1 mapping between file-type:DataLoader-subclass and a 1:1 mapping from files:DataObject instances for files that are visible in the UI. When a file is encountered, a DataLoader is found and used to produce a DataObject for that file.

Modules that provide the ability the system to open (or otherwise use) files of a particular type will register DataLoaders for those types. When the system needs to display a file in the UI, or when some code calls DataObject.find(someFileObject), the registered loaders are queried and one of them will claim it, and create a DataObject to represent it. So typically for each file type (as defined by file name extension, or XML subtype) there is a matching DataObject subclass.

DataLoaders are registered in the module manifest - for example:

Name: org/netbeans/modules/povray/PovDataLoader.class
OpenIDE-Module-Class: Loader

Note that the empty line above the Name: line must be present; create such entries at the bottom of the module manifest.

What is a DataObject?

DataObjects wrap FileObjects. A FileObject is just a container for data; it happens to have a MIME type, but like java.io.File, it doesn't know or care what kind of file it represents, or what the file is. DataObject is part of the Loaders API - a good overview of this API can be found here.

A DataObject represents one or more (typically only one) FileObjects. A DataObject knows what kind of a file it represents; it may represent the parsed contents of a file such as a .java file; or, as in the case of InstanceDataObject the file name may provide all the information it needs to be useful.

DataObjects are produced by DataLoaders, which modules register for specific file types. So for each file type, there is (usually) one DataLoader; and for each file of that type, there is (typically) one DataObject.

DataObjects are seldom referred to by type - if you are casting a DataObject to its implementation class, you are probably doing something wrong. This is a general rule for which there can be exceptions, but is especially true if you're doing the cast from code in a different module than the one in which the DataObject was defined. The usage pattern is to ask a DataObject for instances of interfaces that are the things your code will actually interact with. The method for doing this is dataObject.getCookie(Interface.class) (or in newer versions of NB, dataObject.getLookup().lookup(Interface.class)).

As a simple example, the NetBeans APIs define an interface org.openide.cookies.OpenCookie. It has one method, open(). That method will open the file in the editor. What exactly will happen when open() is called is entirely up to the module that implements the DataObject. The rest of the system does not need to know any of the implementation details - it just needs to know if the DataObject has an OpenCookie. If it does, then the Open action on its context menu can be enabled, and that action will call ((OpenCookie) theDataObject.getCookie(OpenCookie.class)).open().

The name cookie is historical and somewhat unfortunate; the getCookie() pattern is an older variation on the Lookup pattern for service discovery. The two are equivalent, with the exception that getCookie() requires all returned objects to implement the empty Node.Cookie marker interface, and Lookup can return any object. Expect getCookie() to be replaced with a new getLookup() method at some point in the future.

As suggested above, a DataObject may actually represent more than one file - so when you expand a folder in the UI, there may actually be fewer DataObjects in that folder than there are files. This is why, in the NetBeans IDE, a Swing form is represented by a .java file and a corresponding .form file, but the .form file is not visible in the UI; in the past, .properties files have also used this mechanism to present resource bundles in various languages as a single node in the files tree.

However, this ability to represent multiple files with a single DataObject is strongly discouraged for new code and will probably eventually be deprecated - it has serious negative implications for scalability.

How do I get a DataObject for a FileObject?

DataObject.find (theFileObject)

The next button is never enabled when I create my DataObject from a template. Help!

Most likely your DataObject does not put itself into its own CookieSet/Lookup. If you call setCookieSet(), or override getLookup() or getCookie(), this can happen. There are a few parts of NetBeans which will expect Nodes to be present in their own Lookups and DataObjects to be present in theirs. It is always best to make sure they are there. For a DataObject, the code for this is usually as simple as:

getCookieSet().add(this);

How do I get a DataObject for a Node?

DataObject dob = (DataObject) theNode.getLookup().lookup (DataObject.class);
if (dob != null) {
   //do something
}

How do I add an item to for every folder in the system?

There is a folder in the System Filesystem called Loaders. It is where various things are registered that apply to specific DataObject types. For example, there is a folder Loaders/text/x-java that contains things that pertain to Java files (notice that the path is a MIME type). It has an Actions subfolder where you can add actions to the popup menu for Java files.

You may not think of a folder as being a file type, but to NetBeans it is. There is a subfolder Loaders/folder/any/Actions which contains actions that should appear in the popup menu for folders. Just add your action in your layer file to that folder, i.e.

<filesystem>
  <folder name="Loaders">
      <folder name="folder">
          <folder name="any">
            <folder name="Actions">
               <file name="com-foo-module-MyAction.instance"/>
          </folder>
        </folder>
      </folder>
    </folder>
</filesystem>

There is a class under org.netbeans.core that does what I need. Can I call/use/depend on it?

No. Not if you want your module to work in the future. Copy the code instead. If it is a thing that seems generally useful, file an enhancement request requesting an API for the thing you need to do (and make sure there isn't already a supported way to do it).

Anything under org.netbeans.core is non-public, not an API, and subject to change without notice. An API is a contract - an agreement about compatibility. There is no such contract for this namespace, under any circumstances. The class or method you are using may not even exist in the future. Depend on it at your peril.

A perfect example of why not to do this is JProfiler's plugin for NetBeans - it broke very badly across releases because it needlessly depended on the implementation of DialogDisplayer rather than on the API class - so when that class moved, it could no longer link, so the module didn't work.

If you really must use some non-API classes to do what you need to do, use an implementation dependency - your module probably won't load in any version except the one it was built against, but at least your users won't get nasty surprises. And ideally, notify the maintainer of the thing you're depending on - they can give you a heads-up if they think they're about to make a change that will break your module.

Whenever I start NBs, or when I run a module, I get warnings that some modules use deprecated APIs. Is that why XYZ doesn't work?

Q:
Whenever I start NBs, or when I run a module, I get these warnings:
[org.netbeans.core.modules #2] Warning: the module org.netbeans.core uses org.openide.compat which is deprecated: The
   classes in this API are all deprecated and can be replaced by more modern APIs.
...

This sort of message just means that some modules are using org.openide.compat, which is deprecated stuff that many modules use. Probably the particular culprit is ExplorerPanel, which is what you typically use if you want to show a tree or other view of Nodes. It's deprecated, not because anything was particularly wrong with it, but because it was in the wrong package - it created an undesirable dependency from the Explorer API into the Window System API, which became more of an issue when these were split into separate jars. There is no simple replacement - what should happen is to create some kind of utility module that depends on both and includes it or its equivalent.

Even if you're seeing warnings about some other deprecated module, it doesn't mean that you need to be worried (of course, if you're the author of the module being warned, you should fix it). There is an ebb and flow to the development cycle - after a release, it's not uncommon for some things to be deprecated, and there is an inevitable delay before all modules that rely on the deprecated thing stop using it.

How can I control when the OK button is enabled?

The NetBeans Dialogs API makes it easy to create consistent dialogs that behave as users would expect. But since you don't directly create the OK button, it may not be obvious how you can enable it or disable it.

You can enable the OK button by calling setValid(true) and disable it by calling setValid(false). This thread from the dev@openide list might also be helpful.

Can I disable Auto Update (for example, while running tests)?

The NetBeans 6.0 IDE often checks for updates on startup. This behavior may not be desired in some cases; for example, when running tests on the GUI, because they can slow the application down or potentially change its behavior from what you expected. In order to prevent the autoupdate check, run the application with the "netbeans.full.hack" system property set to "true". For example, use -J-Dnetbeans.full.hack=true on the command line.

What are .settings files?

.settings files are similar to
.instance files, with the distinction that they specify all the superclasses/interfaces of the object represented, so that some code can ask Lookup/whatever "Do you have one of these?" without needing to actually create an instance of the object. You could call .settings files "POJO persistence".

They had a brief run of popularity as Yet Another Way To Store Settings a few years ago, around when the new window system was being conceived. They're not bad, but a bit baroque. The main point was to avoid loading classes or creating objects just to satisfy a test like "how many object instances are there of X", "does this folder/lookup/collection contain an instance of X". For NetBeans, where there are lots of classes, this sort of thing really does make a difference in performance. The observation was that huge amounts of classloading could be triggered just to find out that something was not actually of use to whatever code triggered it to be instantiated.

.settings files can be used for the same purposes as .instance files - as a way of indicating that the file represents some class that should be instantiated. The main difference is that by defining all of the superclasses and interfaces of the the object they represent, it is possible for the system to delay actually instantiating the object longer - more questions about the object can be answered by the system without creating it to answer those questions.

.settings files are typically not used for registering actions in the main menu and similar places, since these actions will need to be instantiated almost immediately anyway in order to determine if they should be enabled or not. A future API for declarative actions will possibly change that, but at present, it does neither harm more good, and .instance files are simpler (and for cases where the object will be instatiated immediately anyway, faster).

Some examples:

Declaring a system option as a .settings file from an XML layer

Have a layer entry such as this:

  <folder name="Services">
    <file name="org-openide-text-PrintSettings.settings" url="PrintSettings.settings">
      <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.core.Bundle"/>
      <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/openide/resources/printSettings.gif"/>
    </file>
  </folder>

Note the url attribute - it points to a file PrintSettings.settings which is in the same directory in the module jar as the layer file - it is a relative path. That settings file will look like this:

  <?xml version="1.0"?>
  <!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN" "http://www.netbeans.org/dtds/sessionsettings-1_0.dtd">
  <settings version="1.0">
    <instanceof class="java.beans.beancontext.BeanContextProxy"/>
    <instanceof class="org.openide.util.SharedClassObject"/>
    <instanceof class="org.openide.options.SystemOption"/>
    <instanceof class="org.openide.options.ContextSystemOption"/>
    <instanceof class="org.openide.text.PrintSettings"/>
    <instance class="org.openide.text.PrintSettings"/>
  </settings>

The two things to note are that the .settings file declares many of the relevant parent classes of the object (so it does not need to be instantiated just to see what kind of object it is), and the layer file declares the icon and a resource bundle (for the display name) as file attributes .

What are .shadow files?

.shadow files are mainly used in the
System Filesystem for configuration data. They are the functional equivalent of Unix symbolic links - a .shadow file is a pointer to another file whose behavior in every respect except its path and file name is the same as the original.

.shadow files are commonly used where only a single instance of an object is needed, but it must exist in multiple folders. For example, an Action is typically declared in the Actions/ folder of the System Filesystem. But the action also needs to appear in menus and toolbars, possibly other places. So, rather than create multiple instances of an action, one .instance file is created in the module's layer file , in the Actions/ folder. Then .shadow files are created in all of the other places the .instance file would be needed, pointing to the .instance file.

Declaring a .shadow file in the system filesystem looks like this:

     <folder name="A">
        <file name="com-foo-mymodule-MyClass.instance"/>
     </folder>

     <folder name="B">
        <file name="Shadow1.shadow">
            <attr name="originalFile" stringvalue="A/com-foo-mymodule-MyClass.instance"/>
        </file>
     </folder>

     <folder name="C">
        <file name="anotherShadow.shadow">
            <attr name="originalFile" stringvalue="A/com-foo-mymodule-MyClass.instance"/>
        </file>
     </folder>

.shadow files can point to either files in the system filesystem, or real files on disk. For example, the Favorites tab in the NetBeans IDE uses .shadow files to link to real directories on disk.

How do I add a drop-down menu to a toolbar button?

To add a drop-down menu to a component in a toolbar, you can either extend CallableSystemA