Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 6 - Annotation processor and code addition

I wrote a custom annotation containing metadata for a property and an AnnotationProcessor:

@SupportedAnnotationTypes({"<package>.Property"})
public class PropertyProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv) {
        // Get messager object
        Messager messager = processingEnv.getMessager();
        // Iterate through the annotations
        for(TypeElement typeElement : annotations) {
            // Iterate through the annotated elements
            for(Element element : roundEnv.getElementsAnnotatedWith(typeElement)) {
                // Get Property annotation
                Property property = element.getAnnotation(Property.class);

            }
        }
        return false;
    }

}

Here is the question, I have used Javassist before but it was depending on the class loader and I think it's not appropriate for OSGi applications. I want to change the generated bytecode when a class with Property annotation is compiled.

like image 457
Deniz Acay Avatar asked Sep 18 '10 19:09

Deniz Acay


People also ask

What is Java annotation processing?

"Annotation Processing" is a hook into the compile process of the java compiler, to analyse the source code for user defined annotations and handle then (by producing compiler errors, compiler warning, emitting source code, byte code ...). API reference: javax. annotation.

How does annotation processing work?

Annotation processing takes place at compile time (compile time = the time when the java compiler compiles your java source code). Annotation processing is a tool build in javac for scanning and processing annotations at compile time. You can register your own annotation processor for certain annotations.


1 Answers

Have you tried Google Guice?

Google Guice lets you do a bit of Aspect Oriented Programming by intercepting methods. If that's all you need to do, you can implement a MethodInterceptor that'll let you override methods at runtime. It's really neat for isolating cross-cutting concerns.

For example, lets say you want to prevent a certain methods from being executed on weekends, you can annotate them as so:

@Property
public class SomeClass {
    public Receipt doSometing() {
        // Do something
    }
}

Define a MethodInterceptor:

public class PropertyInterceptor implements MethodInterceptor {
  public Object invoke(MethodInvocation invocation) throws Throwable {
    // For example prevent the classes annotated with @Property
    // from being called on weekends
    Calendar today = new GregorianCalendar();
    if (today.getDisplayName(DAY_OF_WEEK, LONG, ENGLISH).startsWith("S")) {
      throw new IllegalStateException(
          invocation.getMethod().getName() + " not allowed on weekends!");
    }
    return invocation.proceed();
  }
}

And then bind the interceptor to the annotation:

public class PropertyModule extends AbstractModule {
  protected void configure() {
        PropertyInterceptor propertyInterceptor = new PropertyInterceptor();        
        bindInterceptor(Matchers.annotatedWith(Property.class), 
        Matchers.any(), propertyInterceptor);
  }
}
like image 197
Tristan St-Cyr Avatar answered Nov 10 '22 01:11

Tristan St-Cyr