views:

456

answers:

4

Hi all,

I realise that this might be a question that has been asked and answered, but please bear with me.

I want to know if it is possible to use annotations to inject code into your classes compile time. The classic example is to generate a getter and setter for the members of your object. This is not exactly what I need it for, but it serves to illustrate the basic idea.

Now on the internet the basic answer I get is no, but this guy did it:

link text

Does anyone know how he does what he does (and if he actually does what he says he does)?

The main thing is that he does not use an annotation processor to generate a new java file to compile. This technique I am aware of and will not work for our purpose.

Thanks

+1  A: 

Something needs to process the annotations, so it either happens at compile time with an annotation processor or at runtime with reflection (yes I know, there are even more exotic ways of doing it at runtime).

He most definitely is using an annotation processor, it's just that it's implicit. The javac command will search the class path for annotation processors if not explicitly set.

Since he uses this command to compile:

javac -cp ~/development/panno/build/hanhuy-panno.jar *.java

We see he has modified the class path to include the hanhuy-panno.jar, which will contain the annotation processor.

Why not just email the guy and ask if he'll give you the code?

hbunny
Yes, I realise that he does it using a annotation processor, the question is more what he does in it. I have mailed him, but I have not received a reply yet. Thanks
+3  A: 

Hello,

It is not supported to modify code at compile time but it seems to be possible by using non-supported javac-internal APIs, here is a post referencing the hanbuy-panno solution with also a link to the code...

pgras
Thank you very much. That second link is exactly what I was looking for. Now I can see how he does it and decide whether it is a good/bad idea to do it that way.
+2  A: 

I went looking for something similar last year. There is no standard way to alter classes using annotation processors or the compiler and the annotation API documentation recommends creating decorators.

If you are willing to live with the hacks, have a look at Adrian Kuhn's use of the private API where he adds Roman numeral literals to Java. This approach is limited to the Sun javac compiler and you would need to implement something else if you used another (like the Eclipse compiler).


Edit: anyone interested in this area should check out Project Lombok.

McDowell
Ah, I see what you mean about limiting yourself to a certain compiler. That might be a problem. Thanks for the response.
+1  A: 

You can do this, but you're not supposed to modify the class containing the annotations. (The trick you link to uses the compile tree api to modify the bytecode being generated...) This is not supported and will probably be guarded against in later Java SDKs.

The proper way to do it is to generate a superclass, subclass or wrapper class.

I've written a set of annotations that generate getters/setters and other fun stuff. I generate a superclass.

See http://code.google.com/p/javadude/wiki/Annotations

You can do things like

package sample;

import com.javadude.annotation.Bean;
import com.javadude.annotation.Property;
import com.javadude.annotation.PropertyKind;

@Bean(properties={
    @Property(name="name"),
    @Property(name="phone", bound=true),
    @Property(name="friend", type=Person.class, kind=PropertyKind.LIST)
}) 
public class Person extends PersonGen {
}

and it'll generate PersonGen for you with the fields/getters/setters and bound property support.

Scott Stanchfield
Thanks for the response, but as I stated in my original question, generating other java files is not an ideal solution in our case. Although, I do agree that using the compile tree api is not ideal either.
Any particular reason code gen won't work for you? Keep in mind that not only is the code tree api non-ideal this purpose, it is explicitly stated in the APT docs that it's illegal.
Scott Stanchfield