Creating Groovy Custom Annotations

with No Comments

Annotations are one of the best way to enhance language power. Building custom annotations in Groovy is not very hard process.

Lets create simple annotation that will randomly initialize annotated number or string variables. This annotation can be useful for example in testing.

@RandomInit(max=1000) BigDecimal number
@RandomInit(minLength=5, maxLength=150) String str

First of all we need to declare annotation:

1) @ElementType

ElementType Annotation place
ElementType.PACKAGE

@CustomAnnotation
package net.reidconsulting.package

ElementType.TYPE @CustomAnnotation
public class SomeClass {}
ElementType.CONSTRUCTOR

public class SomeClass {
@CustomAnnotation
public SomeClass() {…}
}

ElementType.METHOD

@CustomAnnotation
public void someMethod() {}

ElementType.PARAMETER

public void someMethod(@CustomAnnotation String param) {…}

ElementType.FIELD

@CustomAnnotation
private String classField

ElementType.LOCAL_VARIABLE

public void method() {
@CustomAnnotation String str
}

ElementType.ANNOTATION_TYPE

@CustomAnnotation
public @interface SomeAnnotation {…}

 

2) @Retention

RetentionPolicy.SOURCE: Discard during the compile. These annotations don’t make any sense after the compile has completed, so they aren’t written to the bytecode.
RetentionPolicy.CLASS: Discard during class load. Useful when doing bytecode-level post-processing. Somewhat surprisingly, this is the default.
RetentionPolicy.RUNTIME: Do not discard. The annotation should be available for reflection at runtime.
We use source because we would like to init variables during compilation and keep code clean after it.
3) @GroovyASTTransformationClass
Annotation is only the informational signal to compiler. But using GroovyASTTransformationClass we can define class that will be used to process AST transformation after compiler found annotated source. This class must be annotated with @GroovyASTTransformation.

 

4) Annotation body starts with @interface. We can add some parameters and default values for this parameters.

 

Transformation class:

Implementing ASTTransformation we must override visit method which will be called every time when compiler found our @RandomInit annotations.
One of the most important thing building groovy custom annotation is to select correct Compile Phase. There are no out of the box solutions. Which phase is suited best depends on what we want to do with the AST transformation. We use “Semantic Analysis” and it is the earliest phase we can process our custom annotation.
Groovy AST Browser may help you to check what happens with code during each phase and which one is best for your annotation.

Usage:

 

Useful Links:

https://github.com/illerax/random_init – @RandomInit sources
http://groovy-lang.org/objectorientation.html#_annotation – Official Documentation
http://melix.github.io/ast-workshop/ – Groovy AST Transformations Workshop by Cédric Champeau
http://glaforge.appspot.com/article/groovy-ast-transformations-tutorials – Articles recommended by Guillaume Laforge

Leave a Reply