FaqApt

(Difference between revisions)
(Replaced content with '__NOTOC__ ===Can I run an annotation processor from my project?=== Yes. NetBeans supports JSR 269-compliant annotation processors directly - both during the build (for Ant o…')
 
(10 intermediate revisions not shown)
Line 2: Line 2:
===Can I run an annotation processor from my project?===
===Can I run an annotation processor from my project?===
-
Yes, with a little work.
+
Yes. NetBeans supports JSR 269-compliant annotation processors directly - both during the build (for Ant or Maven projects), and in the IDE's Java editor as you type. For more information on how to use annotation processors, see [http://netbeans.org/kb/docs/java/annotations.html Annotation Processors Support in the NetBeans IDE]
-
 
+
-
JDK 5 introduced annotations and a tool <tt>apt</tt> 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 <tt>apt</tt> tool is no longer necessary as <tt>javac</tt> can automatically run processors.
+
-
 
+
-
NetBeans currently does not directly support running annotation processors 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 <tt>tools.jar</tt> and you must run <tt>apt</tt> 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:
+
-
 
+
-
<pre>
+
-
package ann;
+
-
public @interface Handlable {}
+
-
</pre>
+
-
 
+
-
Create a processor for it:
+
-
 
+
-
<pre>
+
-
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;
+
-
@SupportedAnnotationTypes("ann.Handlable")
+
-
@SupportedSourceVersion(SourceVersion.RELEASE_6)
+
-
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) {
+
-
                processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, "Not a field", e);
+
-
                continue;
+
-
            }
+
-
            String name = capitalize(e.getSimpleName().toString());
+
-
            TypeElement clazz = (TypeElement) e.getEnclosingElement();
+
-
            try {
+
-
                JavaFileObject f = processingEnv.getFiler().createSourceFile(clazz.getQualifiedName() + "Extras");
+
-
                processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "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("    }");
+
-
                    pw.println("}");
+
-
                    pw.flush();
+
-
                } finally {
+
-
                    w.close();
+
-
                }
+
-
            } catch (IOException x) {
+
-
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, x.toString());
+
-
            }
+
-
        }
+
-
        return true;
+
-
    }
+
-
    private static String capitalize(String name) {
+
-
        char[] c = name.toCharArray();
+
-
        c[[0 | 0]] = Character.toUpperCase(c[0]);
+
-
        return new String(c);
+
-
    }
+
-
}
+
-
</pre>
+
-
 
+
-
You must also register your processor. Create a file <tt>src/META-INF/services/javax.annotation.processing.Processor</tt>:
+
-
 
+
-
<pre>
+
-
proc.HandlableProcessor
+
-
</pre>
+
-
 
+
-
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:
+
-
 
+
-
<pre>
+
-
package demo;
+
-
import ann.Handlable;
+
-
public class Main extends MainExtras {
+
-
    @Handlable
+
-
    private String stuff;
+
-
    public static void main(String[] args) {
+
-
        new Main().handleStuff("hello");
+
-
    }
+
-
}
+
-
</pre>
+
-
 
+
-
Initially you will see compilation errors in the editor for this file. Don't worry about that yet. In the
+
-
'''Files''' tab, open <tt>nbproject/project.properties</tt> and add/edit these lines:
+
-
 
+
-
<pre>
+
-
# edit to ensure path is absolute:
+
-
build.dir=${basedir}/build
+
-
# add:
+
-
build.apt.dir=${build.dir}/apt
+
-
# add ${build.apt.dir}:
+
-
javac.classpath=\
+
-
    ${reference.lib.jar}:\
+
-
    ${build.apt.dir}
+
-
# edit:
+
-
javac.compilerargs=-s ${build.apt.dir}
+
-
</pre>
+
-
 
+
-
Now run the project. You should see
+
-
 
+
-
<pre>
+
-
run:
+
-
hello
+
-
</pre>
+
-
 
+
-
If you look in the '''Files''' tab, you should see <tt>build/apt/demo/MainExtras.java</tt> with
+
-
 
+
-
<pre>
+
-
package demo;
+
-
public abstract class MainExtras {
+
-
    protected MainExtras() {}
+
-
    /** Handle something. */
+
-
    protected final void handleStuff(java.lang.String value) {
+
-
        System.out.println(value);
+
-
    }
+
-
}
+
-
</pre>
+
-
 
+
-
Switch back to <tt>Main.java</tt>; 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.
+
-
 
+
-
If you want to include <tt>MainExtras</tt> in Javadoc generation for the project, just open <tt>build.xml</tt> from '''Files'''
+
-
and add an override of a target from <tt>nbproject/build-impl.xml</tt> with one addition:
+
-
 
+
-
<pre>
+
-
    <target name="-javadoc-build" depends="init">
+
-
        <mkdir dir="${dist.javadoc.dir}"/>
+
-
        <javadoc destdir="${dist.javadoc.dir}" source="${javac.source}" notree="${javadoc.notree}" use="${javadoc.use}" nonavbar="${javadoc.nonavbar}" noindex="${javadoc.noindex}" splitindex="${javadoc.splitindex}" author="${javadoc.author}" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}" private="${javadoc.private}" additionalparam="${javadoc.additionalparam}" failonerror="true" useexternalfile="true">
+
-
            <classpath>
+
-
                <path path="${javac.classpath}"/>
+
-
            </classpath>
+
-
            <sourcepath>
+
-
                <pathelement location="${src.dir}"/>
+
-
                <pathelement location="${build.apt.dir}"/> <!-- added -->
+
-
            </sourcepath>
+
-
            <packageset dir="${src.dir}" includes="*/**"/>
+
-
            <fileset dir="${src.dir}" includes="*.java"/>
+
-
        </javadoc>
+
-
    </target>
+
-
</pre>
+
-
 
+
-
Discussion on nbdev: "Requirements for Supporting Annotation Processors in Mustang" [http://www.netbeans.org/servlets/BrowseList?list=nbdev&by=thread&from=542406 #1] [http://www.netbeans.org/servlets/BrowseList?list=nbdev&by=thread&from=551162 #2]
+
-
 
+
--------
--------
-
Applies to: NetBeans 5.0
+
Applies to: NetBeans 6.9+

Current revision as of 22:06, 13 December 2011

Can I run an annotation processor from my project?

Yes. NetBeans supports JSR 269-compliant annotation processors directly - both during the build (for Ant or Maven projects), and in the IDE's Java editor as you type. For more information on how to use annotation processors, see Annotation Processors Support in the NetBeans IDE


Applies to: NetBeans 6.9+

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