Geertjan's Blog

  • May 5, 2009


Geertjan Wielenga
Product Manager
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"><type>org.netbeans.demo.project.DemoProject</type>
<configuration><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.

Join the discussion

Comments ( 6 )
  • Jesse Glick Tuesday, May 5, 2009

    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!

  • Geertjan Tuesday, May 5, 2009

    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!

  • Jesse Glick Tuesday, May 5, 2009

    "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.

  • Varun Nischal Tuesday, May 5, 2009

    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

  • Geertjan Wednesday, May 6, 2009

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

  • Jesse Glick Wednesday, May 13, 2009

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

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