Reflective Annotation Processing

Hi there,
I am using annotations to annotate methods in classes to indicate that they are accessors for some property. Here's an example:
  An enum that defines what type of accessor a method is.
public enum AccessorType {
  GET, SET ;
}And then the annotation definition
   An annotation to indicate that the target method is an accessor for this property.
@Target(ElementType.METHOD)
@Inherited // btw, I am not sure if this inheritance works on targets of ElementType.METHOD.
@Retention(RetentionPolicy.RUNTIME)
public @interface ColorProperty {
  AccessorType value();
}And an example usage:
public class Thing {
private Color _color ;
@ColorProperty(AccessorType.GET)
public Color getColor() {
   return this.color ;
@ColorProperty(AccessorType.SET)
public void setColor(Color color) {
       this._color = color ;
}Such a way of using annotations allows me to properly encapsulate, so I prefer it to simply annotating fields and bypassing the security manager (using Field.setAccessible...). (This also makes using AspectJ for interception simple.)
The application code is supposed to process instances of objects in response to events on a GUI and create appropriate property editors by looking up a widget registry that is basically a Map<Annotation, Widget>. It does this by reflectively examining the methods of each object passed to it, pulling out the methods which have been annotated and binding the appropriate methods to the appropriate widgets. In the above example, this would mean that the engine would create a JColorChooser and bind it to the setColor method of this class.
Now my question: Currently, the only way to do this processing is to get all the methods of the target class, examine each method to see if it has the annotation. I have to do this for each property that is registered in the widget registry because all such properties need to be editable. Is there a way to do something like this:
annotation.getTarget(ElementType elementType)which would return the element which has been annotated using the specified annotation and is of the specified ElementType (and maybe null if there is no match)? Or is repeated iteration the only way to do this? Also, are there data on performance for this sort of reflection and/or annotation available somewhere?

Yes, that's basically what I ended up with a slight difference. I use type() to specify the type of the object that the method accepts in the set method and returns in the get method. As far as I know, there's no way to get a particular method from a class only by its name (is there?). So I can use type information from the annotation to retrieve the correct method without looping through all the methods of this class.
So the Property annotation looks like this:
public @interface Property {
  String name() default "Property" ;
  Class<?> valueType() default Object.class ;
  String getter() default "getProperty()" ;
  String setter() default "setProperty()" ;
}Its used like this:
@Properties({
   @Property(name="Color", valueType=Color.class, setter="setColor", getter="getColor"),
   @Property(name="Width", valueType=double.class, setter="setWidth", getter="getWidth")
public class Thing {
}And processed like this:
Properties propertiesAnnotation = thing.getClass().getAnnotation(Properties.class);
Property[] properties = propertiesAnnotation.value();
for (Property prop : properties) {
     Class<?> c = prop.type();
     Method getMethod = thing.getClass().getMethod(prop.getter(),new Class[0]);
     Method setMethod(thing.getClass().getMethod(prop.setter(),new Class[] { c });
}There is obviously still some convention I am relying upon, like the fact that accessors will have the form I expect them to be here, but that's no big deal.
Thanks for your solution.

Similar Messages

  • JDK 1.6: Annotation Processing & Compiler Hack

    Hello,
    I am currently using JDK 1.6.0_23
    For one of the requirement, I am going with annotation processing & compiler Hack using Tools.jar available as part of JDK.
    I have refered a PDF - "The Hacker's Guide to javac (PDF) by David Erni and Adrian Kuhn (2008)
    " suggested from page of - http://openjdk.java.net/groups/compiler/
    My requirement is below ->
    Origional Source:
    public void someMethod() {
    }Modified Source:
    public void someMethod() {
       int items = new example.Product().getItems();
    } Below is my code to generate the variable declaration -
    private TreeMaker make; // fetch it from somewhere
    JCNewClass newProduct = make.NewClass(null, List.<JCExpression>nil(), make.Ident(names.fromString("example.Product")), List.<JCExpression>nil(), null);
    JCFieldAccess fieldAccess = make.Select(newProduct, names.fromString("getItems"));
    JCMethodInvocation getTimeMethodInvocation = make.Apply(List.<JCExpression>nil(), fieldAccess, List.<JCExpression>nil());
    expression = getTimeMethodInvocation;
    JCVariableDecl itemsDeclaration = make.VarDef(modifiers,name,varType,expression);
    System.out.println(itemsDeclaration); // this prints int items = new example.Product().getItems(); This itemsDeclaration, I am adding to a List<JCStatement> of JCBlock of JCMethodDecl.
    However modified code does not compile :(
    If I make below changes - Modified does compile
    1)
    JCNewClass newProduct = make.NewClass(null, List.<JCExpression>nil(), make.Ident(names.fromString("Product")), List.<JCExpression>nil(), null);Product insteadof example.Product
    2) Add belwo statement in the origional source code
    import examle.Product; What exactly am I missing here ???
    The AST tree is diffcult to understand with minimum documentation & without much help on the interent.
    I hope this is correct forum, for my query.
    It will be a great help.
    Regards,
    Vikas Parikh

    Hello,
    I couldn't contact them, as the white papaer didn't conatin any email address / contact info.
    I have investigated myself on this & would like to share with you guys, so that any other developer
    do not have to invest precious time like I have done.
    To create a New Class, you require a JCExpression.
    Below would work, if class already has imported Product class.
    make.Ident(names.fromString("Product"))However, if class has not imported the Product class, then there are 2 options -
    1) Create a Ident</pre> from <pre>Symbol (ClassSymbol)
    2) Create a JCField</pre> from <pre>NameI used a later approach.
    Regards,
    Vikas Parikh
    Edited by: 996153 on Mar 31, 2013 11:04 PM

  • Is annotation processing the same for Java 5 and Java 6?

    I've been trying to use a package of annotations and processors that was evidently originally designed to be used with "apt" and Java 5. When I try to use this stuff with Java 6 I was assuming that, since the Java 6 javac handles annotations, I could just use javac instead of apt - but it doesn't work; the annotation processors don't appear to be getting executed. It looks like I have to use apt for the Java 6 build after all.
    The question is, did the annotation mechanism change significantly between 5 and 6 that would account for this? Is there a way to adapt an annotation package (i.e. annotation classes and processors) that works with 5 so that it will work with 6 using javac instead of apt (or alternatively, is there a way to tell javac to process the older annotations in the same way that apt would)?

    PeteFord wrote:
    I've been trying to use a package of annotations and processors that was evidently originally designed to be used with "apt" and Java 5. When I try to use this stuff with Java 6 I was assuming that, since the Java 6 javac handles annotations, I could just use javac instead of apt - but it doesn't work; the annotation processors don't appear to be getting executed. It looks like I have to use apt for the Java 6 build after all.
    The question is, did the annotation mechanism change significantly between 5 and 6 that would account for this? Is there a way to adapt an annotation package (i.e. annotation classes and processors) that works with 5 so that it will work with 6 using javac instead of apt (or alternatively, is there a way to tell javac to process the older annotations in the same way that apt would)?If you have apt annotation processors, you can use the apt command in JDK 6.
    However, the javac in JDK 6 support standardized JSR 269 annotation processing; see the javax.annotation.processing package. JSR 269 annotation processing is significantly redesigned and improved based on experiences with apt.
    It would be "a small matter of programming" to port an apt annotation processor to JSR 269.
    Using apt in JDK 6, you can also run both apt and javac processors from a single command line invocation.

  • Annotation-Processing Using Custom ClassLoader Fails

    Hi,
    I have the following problem concerning annotations.
    I am using Jaxb2 to marshal some classes and Jaxb relies heavily on processing annotation information contained in them.
    If I put the Jaxb JAR's directly in the classpath everything works fine.
    However, if I use a custom URLClassLoader to load all the Jaxb-related classes the annotation processing fails thus making Jaxb believe that the objects can't be marshaled.
    Note that the classes to marshal containing the annotations to read are loaded with a different ClassLoader which is higher in the hierarchy.
    I tracked down the problems to the class RuntimeInlineAnnotationReader of the Jaxb API which simply calls Class.getAnnotion(..).
    When searching for this bug I also found the bug report 5015623 which relates to this problem. But it is rather outdated, so I hope that there are some better solutions than just ignoring it.
    I wouldn't like having the Jaxb JARs on the global classpath 'cause they are used in only one class out of 100 and thats not worth the possible conflicts with other 3rd party libs.
    Best regards,
    beebop

    No problem, I will give you some details about my architecture.
    First of all I encapsulated the code which uses the Jaxb-API in one class, say Foo, which implements the interface FooInterface.
    Secondly I load the Foo class in another class, Bar, using my derivation of URLClassLoader, called MyClassLoader. Then I use the interface to marshal an object gen of type GenClass where GenClass was generated using xjc:
    class Bar {
      void method(URL[] urls, GenClass gen) {
        ClassLoader parent = Bar.class.getClassLoader();
        ClassLoader myCL = new MyClassLoader(urls,parent);
        Class clazz = myCL.loadClass("Foo");
        FooInterface foo = (FooInterface)clazz.newInstance();
        foo.marshal(gen);
    }So my class loader will be a child of the current class loader. The delegation model of class loading is reversed in MyClassLoader so that first the urls will be checked and then, if the class was not found, the parent class loader.
    Note that GenClass and its ObjectFactory which acutally contain the annotations Jaxb needs will be loaded by the current class loader, not my own. All classes of the Jaxb-API will be loaded by MyClassLoader. If I try to marshal gen, the annotations of the ObjectFactory corresponding to GenClass won't be readable causing the Class.getAnnotation(...) method called in the class RuntimeInlineAnnotationReader to return null.
    If I don't use my own class loader, say
    FooInterface foo = new Foo();everything works fine and the annotations of the ObjectFactory are loaded correctly.
    I observed the different behaviour by stepping through the classes and methods around JaxbContext.newInstance(...).
    MyClassLoader is not that different from URLClassLoader, only the loadClass method is overridden to change the delegation behaviour. Thats why I suspect an error in the annotations framework and not in my class loader but I may be mistaken.
    Best regards,
    beebop

  • Code Generation Using Annotation Processing

    I'm trying to figure out how to do something like thus:
    Given this source file with the following custom annotation:
    @Composite(interfaces=Mammal.class)
    public class Dog implements IComposite
    };I want to create an annotation processor that inserts a data member, implementation into the constructor, and a public method into this class:
    @Composite(interfaces=Mammal.class)
    public class Dog implements IComposite
        IComponent[] m_inner_objects;
        public Dog()
            m_inner_objects = new IComponent[1];
            m_inner_objects[0] = Mammal.compose(this);
        public IComponent getComponent(Class<?> inInterface)
            if(inInterface == Mammal.class)
               return m_inner_objects[0];
            return null;
    };Are all three tasks possible? Are any of the three tasks possible? If yes to any of my questions how would I go about this. I've gotten just past the 'hello world' state in writing a custom annotation processor so I just need the more advanced knowledge of how to actually affect the code once I'm actively processing it.
    cheers,

    brucechapman wrote:
    sednivo wrote:
    I can get the CompilationUnitTree. Yes
    Then I can modify it with Compiler Tree API.Really?
    Where is a pitfall in my train of thought?The Tree API is an immutable API, you can look, but not modify.Here is example of modifying compiler tree.
    http://svntrac.hanhuy.com/repo/browser/hanhuy/trunk/panno/src/com/hanhuy/panno/processing/PropertyProcessor.java
    Also, the javax.annotation.processing.Filer will not allow you to overwrite an existing compilation unit, and you must use the Filer if you wish a generated class to be compiled in the next round.I don't use Filer class. Method writeCompilationUnit that I've wrote works well for existed files.
    There is a fundamental principle of java that the same program always has the same meaning. See the 3rd paragraph of the Preface to the first edition of the Java Language Spec . >This is the reason why you can't modify existing source code.We can mark generated methods in a class with @Generated annotation.

  • Javax.annotation.processing.Processor not recognized

    Hi,
    I'm currently experimenting with the javax.annotation.processing API. Thus I created a simple Annotation and a related simple processor.
    Another sample program uses the annotation. When compiling this program everything works fine as long as I specify the processor class
    on the command line. But when I try to simply use a javax.annotation.processing.Processor file, the compiler doesn't seem to find the processor.
    What am I doing wrong?
    Here come the details:
    I use Java6 and the sun java compiler javac.
    The annotation and processor class are packed into a JAR file together with the javax...Processor file. The JAR looks like this:
         hello/HelloProcessor.class
         hello/annotations/Hello.class
         META-INF/services/javax.annotation.processing.Processor
         META-INF/MANIFEST.MF     The javax.annotation.processing.Processor file is UTF-8 encoded and contains a single line:
         hello.HelloProcessorwithout the leading spaces.
    My processor looks like this:
         @SupportedAnnotationTypes (value = {"hello.annotations.Hello"})
         public class HelloProcessor extends AbstractProcessor {
             private int mCounter = 0;
             /* (non-Javadoc)
              * @see javax.annotation.processing.AbstractProcessor#process(java.util.Set, javax.annotation.processing.RoundEnvironment)
             @Override
             public boolean process(Set<? extends TypeElement> aAnnotations, RoundEnvironment aRoundEnv) {
              Messager vMessager = processingEnv.getMessager();
              vMessager.printMessage(Kind.NOTE, "Runde " + ++mCounter);
              vMessager.printMessage(Kind.NOTE, "Hello World!");
              return false;
         }The following call works...
         javac -processor hello.HelloProcessor -d bin -sourcepath src -cp lib/helloap.jar src/hello/examples/SimpleClass.javaand leads to the following output:
         warning: No SupportedSourceVersion annotation found on hello.HelloProcessor, returning RELEASE_6.
         Note: Runde 1
         Note: Hello World!
         Note: Runde 2
         Note: Hello World!          And this call does not seem to work:
         javac -d bin -sourcepath src -cp lib/helloap.jar src/hello/examples/SimpleClass.javaas it does not produce any output.
    And when I try to configure the processor in eclipse, the processor simply is not found, when I define the helloap.jar on the factory path.
    I'd be happy about every hint.
    Greetings
    yawah

    It sounds like your META-INF/services information is bad.
    Outside of javac, I suggest trying to find your processor from its jar file using java.util.ServiceLoader.
    I'd also try making sure your META-INF/services file ends with a newline character rather than just ends.

  • Is it possible to stop compiling process in annotations processing?

    Hi all.
    I'm doing annotations processing with javac.
    Is it possible to stop compilation if an error occurs during annotations processing?
    Thank you!

    francadaval wrote:
    Hi all.
    I'm doing annotations processing with javac.
    Is it possible to stop compilation if an error occurs during annotations processing?If you raise an error with the Messager:
    http://java.sun.com/javase/6/docs/api/javax/annotation/processing/Messager.html
    no class files will be generated. This is the recommended way to start winding things down; from the Processor class:
    "If a processor throws an uncaught exception, the tool may cease other active annotation processors. If a processor raises an error, the current round will run to completion and the subsequent round will indicate an error was raised. Since annotation processors are run in a cooperative environment, a processor should throw an uncaught exception only in situations where no error recovery or reporting is feasible."

  • Compile time Annotation Processing

    Is it possible to access the source of the file being analysed at compile time?
    Thanks

    Milesy wrote:
    Is it possible to access the source of the file being analysed at compile time?If you are naughty, you can try to find the file being processed and read it directly, but that is not supported.
    You can use the javac-specific tree API (http://java.sun.com/javase/6/docs/jdk/api/javac/tree/index.html) to map from a javax.lang.model.Element to a AST representing the source for a method or constructor.
    If you want the source for the purposes of modifying it, the annotation processing API is read-only, but much of the effect of mutating the source can be achieved by generating subclasses or the superclass of the class in question. Check the forum archives for details.

  • Annotation Processing Error - Run vs Debug

    Hello,
    I'm trying to run the Converter Example (Chapter 21 of the Sun's JavaEE 5 Tutorial) with a difference: I've deleted the Enterprise application ("Converter") and I'm using the packages alone: one for the EJB (Converter-ejb) and the second is the App Client (Converter-app-client). No modifications yet. Both use simple (non decorated) annotations @EJB (in the app-client) and @Stateless and @Remote (in the ejb).
    All deployed OK. If you run the Converter-app-client in the Netbeans (version 5.5 - "run main project" command - F6) the
    AppServer (SunJavaSystemAppServer 9.01) issues the folloing exceptions:
    "Class [ Lcom/sun/tutorial/javaee/ejb/ConverterRemote; ] not found. Error while loading [ class com.sun.tutorial.javaee.ejb.ConverterClient ]"
    "Error in annotation processing: java.lang.NoClassDefFoundError: Lcom/sun/tutorial/javaee/ejb/ConverterRemote;"
    The "Converter-app-client (run)" tab window shows the following exception:
    "java.lang.NullPointerException"
    If you run with "Debug Main Project (F5)", the server issues the same errors, but runs the program ok and you can see it's
    results in the "Converter-app-client (debug)" tab window.
    So:
    What's the difference? Why it runs with "debug" and not in "run"?
    After reading many articles, forum, etc it seems to me that It shouldn't issue any "Error in annotation processing".I've
    tried to use the annotation's (name="xxx") and (mappedName="xxx") with no success. Tried also using the files "sun-*.xml" as instructed in the Glassfish EJB FAQ's.
    Any help will be very appreciated.
    Thanks in advance,
    Marcos

    It seem that it's an Netbean 5.5 error.
    This example application (very similar) runs ok (outside Netbeans)
    https://glassfish.dev.java.net/javaee5/ejb/examples/Sless.html
    Comparing the apps, it seems that Netbeans is not packing the AppClient correctly, dropping the remote interfaces of the referred beans.

  • Annotation processing using JDK 1.6 and Apache Ant

    Hello,
    I am trying to run my annotation processor using ant.
    I already built the processor, the javax.annotation.processor.Processor file is in the correct place with the correct content.
    The jar with the processor is in the classpath (i can see it in ant -v), but it does not process my classes. in fact, i get the warning:
    warning: Annotation processing without compilation requested but no processors were found.Do i have to specify -processor or -processorpath or can i just leave it to the default classpath scanning?
    I think everything is in the correct place, because when i compile with maven instead of ant, specifying the processor, it runs nicely. My pom contains:
                   <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <configuration>
                             <source>1.6</source>
                             <target>1.6</target>
                             <compilerArguments>
                                  <processor>br.com.sonner.infra.seguranca.SegurancaAnnotationProcessor</processor>
                             </compilerArguments>
                        </configuration>
                   </plugin>i am using jdk 1.0.6_02 and ant 1.7.0.
    Can anyone help me find out what am i doing wrong?

    Julio.Faerman wrote:
    Hello,
    I am trying to run my annotation processor using ant.
    I already built the processor, the javax.annotation.processor.Processor file is in the correct place with the correct content.
    The jar with the processor is in the classpath (i can see it in ant -v), but it does not process my classes. in fact, i get the warning:
    warning: Annotation processing without compilation requested but no processors were found.Do i have to specify -processor or -processorpath or can i just leave it to the default classpath scanning?When -processor is not given, a service loader is used to find the annotation processors (if any). In addition to the class files of the process, to allow your processor to be found as a service, make sure you've also provided the needed META-INF data in the jar file. The general service file format is described in
    http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html
    That said, I'd recommend setting an explicit processor path separate from your general classpath.

  • Metadata annotations processing?

    When are metadata annotations processing? Just when the applications starts or during the runtime also?

    why do you need to know how this happens? Because I want to know how the matedata mapping process goes?
    I want to know when for some persistence class appropriate object ( or group of objects) that is responsible for making mapping is created (object that e.g moves attributes value from and to database etc.). Is this object created only once for persistence class or e.g each time when some persistence operation is done?
    could You explain me this?

  • Annotation process tools build performance issue

    Annotation process tools is taking 85 minutes to compile page flow files. Is there any suggestion to improve performance.

    As you probably already have gathered, you have different execution plans in the two environments. There could be different reason why this happens, for instance different profiles of the data. But more likely it is due to that in the slow environment, the
    plan was built from some atypical set of input parameters, which causes a performance issue when the procedure is run in a normal fashion.
    When you say that the query has a lot of isnull and convert functions I get a little worried. If it is only in the SELECT list, it's not evil, but if functions are used in the WHERE or ON clauses, the query might benefit from a review, and possibly also
    the data model. But this is pure speculation at this point.
    I would suggest more than one course of action. As a short-term solution, you run UPDATE STATISTICS WITH FULLSCAN on all tables involved, as out-dated statistics can also be explanation for why you got a bad plan. New statistics should trigger a recompilation.
    But even if this resolves the issue, it may not be feasible in the long run, because the events indicate that the query is sensitive to something and the bad plan could come back any day. For this reason, it might be a good idea to make sure that the query
    does include inappropriate constructs, and you also need to review that there are good indexes in place.
    Erland Sommarskog, SQL Server MVP, [email protected]

  • New com.sun.mirror.* packages - annotation processing

    Hello,
    i would like to use annotation processing tool (APT), but there is much to learn yet.
    So, please help me.
    Let�s have an annotation that can be apllied to all code declarations (source code entities).I want to process some *.java files (their proper source code) via APT.From this code i wanna gain (in any way) those declarations (classes, ifaces, methods, constructors, etc.) that are annotated just with the only one annotation that i have.
    i was already going through the API, but not well-understood.
    As written, i created AnnotationProcessorFactory (just my annotation should be processed by this factory) with an appropriate AnnotationProcessor.
    I�ve already done some steps to succeed, but you know, that�s not that i want
    Of course, all is performed in build-time, after i call apt command with the option factory with the appropriate factory class
    Thank you a lot

    Hi,
    I am new to this forum and also just started
    working on apt can u plz tell me where do i get
    com.sun.mirror package and its sub-packages
    hanksIf you can use JDK 6, I strongly recommend using the standardized annotation processioning in javac and the packages javax.annotation.processing and javax.lang.model..* instead of apt and its com.sun.mirror.* API. To get started, take a look at
    sample/javac/processing/src/CheckNameProcessor.java
    under the JDK 6 install directory.
    If you just need to compile against the apt API, it is found in the tools.jar file in Sun's JDK; see http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html
    You can find a jar file with just the API definition from https://aptmirrorapi.dev.java.net/.

  • Changes are not getting reflected in Process Chain after changes.

    Hello,
    I have modified a Process Chain in Development environment. I have created one new infopackage and included it in the process chain. I have also added two new change run variants in the process chain. I have collected the process chain and infopackage in a transport request and transported it to integration environment.
    Transport request has reached successfully in integration but the changes in process chain are not getting reflected. The infopackage has reached to integration after transport.
    I need some suggestion on this.
    Regards,
    Sanjay

    Hi Sanjay.......
    R u in Display mode..........click on Change mode...........
    If you can see the chain in Change mode............then ur process chain is imported in in-active version..........
    U can try activating it manually or re-transport the active version..........
    Regards,
    Debjani......

  • Annotation  processed at run time in java Library?

    Could any one give me a example in java library where annotation is processed at run time? I know there are lot of example in EJB and spring but looking for some in jave core library?

    JavaFunda wrote:
    Could any one give me a example in java library where annotation is processed at run time? I know there are lot of example in EJB and spring but looking for some in jave core library?The mechanism would be the same regardless of where it is used.

Maybe you are looking for

  • How can I set up breakpoints in eclipse for jsp?

    I saw somebody can set up breakpoints in eclipse for jsp. But I can not do that on my eclipse. What's the difference? Thanks.

  • Automatic PO from PR through ME59N

    Dear All, While converting the PR automatically to PO with ME59N, I am getting message "No suitable PR found". Where as the PR contains the open items and the same PR can be converted in to PO thourgh ME57 (manually). Please suggest me what could be

  • Out of the box execution plan for Payables EBS 11.5.10

    Has anyone else experienced performance issues with the out of the box execution plan for the Payables subject area for Oracle EBS 11.5.10? Our incremental ETL for this particular subject area is taking 8+ hours. I understand that there are several f

  • Dblink not working in dedicated mode

    Hi All, my application tried to access the database in dedicated mode but when it's trying to connect to other database from the original database using DBLINK then it's throwing me ora-24777 use of non-migratable database link not allowed. --> when

  • Max number of pin changes

    I m new at bb playbook . Whenever I try to download any app, it gives msg that's have reached maximum number of pin changes for this account '.  Now how to resolve this problem,  kindly help immediately