In reading lately about the new Web Beans specification, I started to realize how much meta-annotations change things. What are meta-annotations? Meta-annotations are simply annotations that annotate other annotations. How could they be used?
Shorthand
Remember a few blogs back when I criticized the @HttpMethod annotation for JSR-311? I said I’d rather have a typesafe annotation represent GET, POST, etc… than a String parameter to @HttpMethod. Marc Hadely, the spec lead, had an idea to allow @HttpMethod to be a meta-annotation stead:
@HttpMethod("GET") public @interface GET {}
You could apply @HttpMethod to any annotation and it would be triggered by indirection. The idea being, that if HTTP added methods (like WebDav), then they could easily be defined using @HttpMethod as a meta-annotation. They didn’t like my idea of combining @Get with @UriTemplate, but, what if you took meta-annotations even further? …….
Behavior composition
Hmmm, can you annotate an annotation parameter? I tried it out, and you can. Now, what if we also allowed @UriTemplate to be a meta-annotation on a annotation parameter? Then I could have the @GET(“/foo/bar”) REST annotation I always dreamed of:
@HttpMethod("GET") public @interface GET { @UriTemplate String value(); }
The idea would be that @UriTemplate, empty, on an annotations parameter would trigger the extra @UriTemplate behavior when my custom @Get method was applied. So what’s my point here? Maybe this could be used to get rid of annotation creep. Maybe people could use this as a mechanism to define their own idioms and bind their idioms to various competing component models? Just something to think about…
Meta-annotations and AOP
During the EJB 3.0 jsr of EE 5, Gavin wanted to add the ability of allowing @Interceptors to be a meta-annotations. This would allow you to have user-defined annotations that triggered behavior. Take the JBoss Business Activity Framework. The implementation of it could easily be done within EJB 3.0 interceptors. The problem is that to apply BA interceptors in the current EJB 3.0 specification you’d have to bind them with an ugly @Interceptors annotation on the bean class or with XML within ejb-jar.xml. Wouldn’t it be cool if @Interceptors was a meta-annotation? Then you could do something as simple as:
import javax.interceptor.Interceptors; @Interceptors(org.jboss.ba.BAInterceptor.class) public @interface BACompensatedBy { public String value(); ... }
If the EJB container could resolve @Interceptors as a meta-annotation, then just using and applying the @BACompensatedBy annotation would be enough to trigger the behavior. Gavin, Seam, and Web Beans took this idea further, by defining a @InterceptorBindingType meta-annotation.
@InterceptorBindingType public @interface BACompensatedBy { public String value(); ... }
You would then bind an interceptor class by apply the @BACompensatedAnnotation to your actual interceptor class
@BACompensatedBy @Interceptor public class BAInterceptor { @AroundInvoke public Object registerCompensation(InvocationContext inv) throws Exception {...} }
If you think about it, this could have a profound impact on AOP in that pointcut expressions begin to only be used in edge cases. If you’re implementing aspect-oriented annotations, no quirky, unreadable pointcut expressions are needed. Just use the binding annotations. If you’re using pointcuts to define integration points into your application, instead, remove these in favor of simple annotations that you move around as you refactor your application.
Seems to me that meta-annotations have a lot of potential. Wouldn’t it be cool if all Java EE annotations were allowed to be meta-annotations? Just another thought. If you know any other uses, let me know here. Thanks.
Oh, and BTW:
The thoughts of an IT professional : Annotations used for deployment
Oct 22, 2007 @ 16:17:55
Oct 24, 2007 @ 06:56:00
Spring 2.5 supports meta-annotations for autowire qualifiers. There are a couple examples in the reference documentation (starting with the @Genre annotation).