(Difference between revisions)
(Can I run an annotation processor from my project?)
Line 52: Line 52:
public class HandlableProcessor extends AbstractProcessor {
public class HandlableProcessor extends AbstractProcessor {
     /** public for ServiceLoader */
     /** public for ServiceLoader */
     public HandlableProcessor() {}
     public HandlableProcessor() {}
    public boolean process(Set<? extends TypeElement> annotations,
  public boolean process(Set<? extends TypeElement> annotations,
                           RoundEnvironment roundEnv) {
                           RoundEnvironment roundEnv) {
         for (Element e : roundEnv.getElementsAnnotatedWith(Handlable.class)) {
         for (Element e : roundEnv.getElementsAnnotatedWith(Handlable.class)) {

Revision as of 07:21, 14 July 2010

Can I run an annotation processor from my project?

NetBeans 6.9 supports annotation processors directly. For more information on how to use annotation processors in NetBeans 6.9, see Annotation Processors Support in the NetBeans IDE

The remainder of this page pertains to older releases.

Yes, with a little work.

JDK 5 introduced annotations and a tool apt which could scan for annotations in a project and perform various actions on them, including code generation.

JDK 6 improves on this support and, as part of JSR 269, provides an official API for writing annotation processors. The apt tool is no longer necessary as javac can automatically run processors.

NetBeans currently does not directly support running annotation processors (bug #111294 and others) but you can set up your project to work fairly well with them. An example using JDK 6 follows. (In JDK 5 it is trickier since you must compile the processor against tools.jar and you must run apt explicitly from the project using the annotations.)

Create a Java SE library project. Make sure it is using JDK 6 or higher (see Libraries in the project's Properties dialog). Define an annotation:

package ann;
public @interface Handlable {}

Create a processor for it:

package proc;
import ann.Handlable;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
public class HandlableProcessor extends AbstractProcessor {
    /** public for ServiceLoader */
    public HandlableProcessor() {}  
   public boolean process(Set<? extends TypeElement> annotations,
                           RoundEnvironment roundEnv) {
        for (Element e : roundEnv.getElementsAnnotatedWith(Handlable.class)) {
            if (e.getKind() != ElementKind.FIELD) {
                    "Not a field", e);
            String name = capitalize(e.getSimpleName().toString());
            TypeElement clazz = (TypeElement) e.getEnclosingElement();
            try {
                JavaFileObject f = processingEnv.getFiler().
                    createSourceFile(clazz.getQualifiedName() + "Extras");
                    "Creating " + f.toUri());
                Writer w = f.openWriter();
                try {
                    PrintWriter pw = new PrintWriter(w);
                    pw.println("package " +
                        clazz.getEnclosingElement().getSimpleName() + ";");
                    pw.println("public abstract class " +
                        clazz.getSimpleName() + "Extras {");
                    pw.println("    protected " + clazz.getSimpleName() +
                        "Extras() {}");
                    TypeMirror type = e.asType();
                    pw.println("    /** Handle something. */");
                    pw.println("    protected final void handle" + name +
                        "(" + type + " value) {");
                    pw.println("        System.out.println(value);");
                    pw.println("    }");
                } finally {
            } catch (IOException x) {
        return true;
    private static String capitalize(String name) {
        char[] c = name.toCharArray();
        c[0] = Character.toUpperCase(c[0]);
        return new String(c);

You must also register your processor. Create a file src/META-INF/services/javax.annotation.processing.Processor:


Now to use the annotation. Create a new Java SE main project (again, using JDK 6 or higher) and add the library project as a dependency (e.g. right-click the Libraries node and choose "Add Project"). Here is a usage of the annotation:

package demo;
import ann.Handlable;
public class Main extends MainExtras {
    private String stuff;
    public static void main(String[] args) {
        new Main().handleStuff("hello");

Initially you will see compilation errors in the editor for this file. Don't worry about that yet. In the Files tab, open build.xml and add these lines:

    <target name="-do-compile"
        <property name="ap.dir" location="${build.generated.sources.dir}/ap"/>
        <mkdir dir="${ap.dir}"/>
        <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"
                <compilerarg line="-implicit:class -s ${ap.dir}"/>
        <copy todir="${build.classes.dir}">
            <fileset dir="${src.dir}"

Turn off Compile on Save in the Compiling panel of project properties. (You can leave it on only if you remember to Clean & Build Project whenever you make any changes that might affect generated sources.)

Now run the project. You should see


The Projects tab should show a new Generated Sources (ap) node. Under it you should find:

package demo;
public abstract class MainExtras {
    protected MainExtras() {}
    /** Handle something. */
    protected final void handleStuff(java.lang.String value) {

Switch back to Main.java; the editor should show it as compilable (green box in upper right corner, and no error markings). Generally you will need to compile the project after changing annotated elements before code completion and the editor's background compiler will "know about" the generated sources.

MainExtras will also be included in Javadoc generation for the project.

Applies to: NetBeans 6.7, 6.8

Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo