The whole area of project types is kind of undocumented at the moment. What is a project type? Well, a Java project in NetBeans IDE is a project type, as is a web application project. A project type is created by a plugin developer so that the end user has a logical view on top of the files they're working with, together with a set of actions that relate to that logical view. In an oil refinery application, a project type might represent a particular oil refinery, while an insurance company might appreciate being able to deal with a set of files relating to one particular client as a single unit.

There are two different ways in which a project type can be defined in NetBeans IDE or, generally, in NetBeans Platform applications. Either the project type is Ant Based (i.e., an Ant script should be able to be run to process something in the application) or no Ant script is related to the application. In the latter case, you would learn from the Project Type Sample and, in 6.7, replace the META-INF/services registration with a @ServiceProvider annotation (as listed here) on the ProjectFactory class.

In the former case, i.e., you'd like to work with Ant scripts in projects created via your project type, life becomes a lot more interesting (i.e., challenging). With 6.7, you have the @AntBasedProjectRegistration annotation to help you. That's rather cool. Forget XML layer files and forget META-INF/services. Instead, take a look at this:

public final class DemoProjectType {

    public static final String TYPE = "org.netbeans.demo.project.DemoProject";
    public static final String NAME_SPACE_SHARED = "http://www.netbeans.org/ns/demo-project/1";
    public static final String NAME_SHARED = "data";
    public static final String NAME_PRIVATE = "project-private";
    public static final String NAME_SPACE_PRIVATE = "http://www.netbeans.org/ns/demo-project-private/1";


The above defines my project type, as is done here for all the other project types that are recognized, in the case of NetBeans IDE:


The above is crucial if you want an Ant script to do stuff with the project created via your project type. The examples shown there are excellent.

What does my DemoProjectType.java class, defined above, assume? It assumes that, at the very least, root-dir/nbproject/project.xml has an element project/configuration/data, as follows (look at the lines in bold and then compare them to the class above):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
        <data xmlns="http://www.netbeans.org/ns/demo-project/1">

Now here is the Project class, which makes use of the type class defined above, as part of the @AntBasedProjectRegistration annotation, which you'll see in action for the first time below:

import java.beans.PropertyChangeListener;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.spi.project.support.ant.AntBasedProjectRegistration;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.openide.filesystems.FileObject;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.lookup.Lookups;

    type = DemoProjectType.TYPE,
    iconResource = "org/netbeans/demo/project/icon.png",
    sharedName = DemoProjectType.NAME_SHARED,
    sharedNamespace = DemoProjectType.NAME_SPACE_SHARED,
    privateName = DemoProjectType.NAME_PRIVATE,
    privateNamespace = DemoProjectType.NAME_SPACE_PRIVATE
public class DemoProject implements Project {

    final AntProjectHelper helper;

    public DemoProject(AntProjectHelper helper) {
        this.helper = helper;

    public Lookup getLookup() {
        return Lookups.fixed(new Object[]{new Info()});

    public FileObject getProjectDirectory() {
        return helper.getProjectDirectory();

    private final class Info implements ProjectInformation {

        public String getName() {
            return helper.getProjectDirectory().getName();

        public String getDisplayName() {
            return getName();

        public Icon getIcon() {
            return new ImageIcon(ImageUtilities.loadImage(

        public void addPropertyChangeListener(PropertyChangeListener pcl) {

        public void removePropertyChangeListener(PropertyChangeListener pcl) {

        public Project getProject() {
            return DemoProject.this;



It couldn't possibly be simpler than the above. You'll not get anything fancy, but any project that meets the definitions described above will be openable from the Favorites window:

So, do I only need two classes, i.e., ONLY the code shown above, to be able to open a completely foreign project into NetBeans IDE? Yes, that would appear to be the case, considering that this is my ENTIRE project structure, producing the result shown above:

Next time we'll look at the LogicalViewProvider, which will add some color and some filters to what is displayed in the Projects window.


There is no more need for DemoProjectType.java; the constants could just be moved into DemoProject. (In fact you could just hardcode these strings, though some of the constants may be useful in the future, e.g. for calling ProjectGenerator.createProject.)

You could also introduce a constant for the icon (already used both in the annotation and in the ProjectInfo).

Pass true to ImageUtilities.loadImage.

The @Override's are unnecessary and will not work on JDK 5.

In the next installment, don't forget you can now use @NodeFactory.Registration to add pieces to the logical view!

Posted by Jesse Glick on May 05, 2009 at 06:37 AM PDT #

Thanks for the time and comments! Firstly, isn't a benefit of the DemoProjectType.java that you can very easily upgrade, simply by changing that separate class, rather than the Project class itself? Secondly, aren't the Override annotations useful and that's why it was created in the first place? Thirdly, thanks for the heads up about the NodeFactory registration because I'm not sure I'd have known that off the bat!

Posted by Geertjan on May 05, 2009 at 06:42 AM PDT #

"isn't a benefit of the DemoProjectType.java that you can very easily upgrade, simply by changing that separate class, rather than the Project class itself" - not sure what you mean, but the answer is probably no. Once you use @ABPR, there is no more need for this class, since you are no longer explicitly implementing AntBasedProjectType; a generic ABPT is created for you internally by the @ABPR registration. (Yarda could have deleted them all in his 2a6a3bb9a45e, moving the constants into the \*ProjectType classes; he just did not bother.)

The @Override annotations are useful if you are overriding a method. In this case you are implementing interface methods, where (IIRC) JDK 6 accepts the annotation but JDK 5 does not.

Posted by Jesse Glick on May 05, 2009 at 06:52 AM PDT #

Finally, you are starting off a series on creating a Project Type. I had started off my own blog series few months back, however couldn't continue with time. Here's a link that shows my exploration in the past;

I am glad that you started this. Thanks a lot :D

Posted by Varun Nischal on May 05, 2009 at 03:58 PM PDT #

Jesse, is the 'true' to ImageUtilities.loadImage for lazy loading?

Posted by Geertjan on May 05, 2009 at 11:25 PM PDT #

No, true to IU.lI is to enable the icon to be localized/branded easily.

Posted by Jesse Glick on May 13, 2009 at 02:23 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.


« July 2016