views:

410

answers:

4

I have created an annotation, applied it to a DTO and written a Java 1.6 style annotationProcessor. I can see how to have the annotationProcessor write a new source file, which isn't what I want to do, I cannot see or find out how to have it modify the existing class (ideally just modify the byte code). The modification is actually fairly trivial, all I want the processor to do is to insert a new getter and setter where the name comes from the value of the annotation being processed.

My annotation processor looks like this;

@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes({ "com.kn.salog.annotation.AggregateField" })
public class SalogDTOAnnotationProcessor extends AbstractProcessor {

    @Override
    public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
        //do some stuff
    }
}
A: 

You have to extend the javac compiler for this, which means building your program won't be as portable as a regular application. See http://weblogs.java.net/blog/cayhorstmann/archive/2006/06/say_no_to_prope.html for more details on how someone achieved this.

Xr
That's certainly a solution, but I'm pretty sure that it isn't the only solution. What I want to do could be done by several existing frameworks/toolsets, eg javassist. I was trying to avoid introducing a dependency that doesn't appear to be strictly necessary though, the introduction of annotation processing in JDK1.6 looked like the functionality of javassist was being baked in.Maybe I was wrong though and I still need a 3rd party tool to perform the compile time weaving.
Steve
+1  A: 

By design, the annotation processing facility does not allow direct modification of the source code being processed. However, one can generate subclasses of the type being processed or the superclass of the type being processed. With some planning, this does allow some of the effect of modifying the type in question. I've written up an example of how this can fit together; see this blog entry for a more detailed explanation and some sample code.

Joe Darcy
+1  A: 

You are looking for "Instrumentation", which is what frameworks like AspectJ do. In this case you have to specify a jar in the command line with the "-agent" option, and then have the possibility to filter all loaded classes. During this filter step you can check for annotations, and modify the bytecode before it gets loaded in the virtual machine. Libraries for doing the actual bytecode modification include "asm", and maybe the highlevel wrappers "cglib" and "javassist". You could even precompile your classes to generate a list of classes which have to be instrumented by you, to make filtering in the beginning a bit faster.

See java.lang.instrumentation for more info.

Daniel
A: 

Project Lombok does such a thing. Only I haven't figured it out exactly how it does that. It looks like manipulating the source for the compiler.

SPee