Groovy 2.1: The @AnnotationCollector Annotation

Groovy 2.1 comes with another cool addition to the groovy.transform AST package: the @AnnotationCollector [0].

X Annotations -> 1 Annotation

The use case for the annotation collector is simple: we want to define a meta-annotation that includes a handful of other annotations. By the way, it's not just "other annotations" but we also want to include AST transformation annotations like @ToString, @EqualsAndHashCode, @Immutable etc. (for an introduction to Groovy's AST transformation annotations, you might want to start here [1]). Let's say we have the use case to apply @ToString and @Immutable to several classes in our project. With Groovy 2.1 we can use @AnnotationCollector to avoid code duplication and create a single annotation alias:
@AnnotationCollector([ToString, Immutable])
@interface ValueObject {}
Our self-defined @ValueObject can now be applied on Groovy classes:
class UpperLimit {}
What happens during compile-time is, the @ValueObject is detected to be an @AnnotationCollector annotation, thus it is replaced by its meta annotations:
class UpperLimit {}
class UpperLimit {}
One last thing: @AnnotationCollector provides a way to specify annotation type element values. For example, the @ToString annotation comes with various attributes to configure the toString() output:
public @interface ToString {
    String[] excludes() default {};
    // ...

    String[] includes() default {};
    // ...

Let's say we want to ignore all id properties on our value objects. Although our @ValueObject has no attributes defined, we can ignore that fact as the @AnnotationCollector AST transformation modifies the custom annotation accordingly:
@ValueObject(excludes = ['id'])
class UpperLimit {}
One special case is when multiple annotation elements have different types and the same names, or just the same names. If they have different types, compilation will fail. Otherwise, the last annotation collect by @AnnotationCollector will deemed as appropriate while others being ignored.

Advanced Features

@AnnotatioCollector even supports adding custom AST transformation code by specifying its processor annotation element. A custom annotation collector must inherit from org.codehaus.groovy.transform.AnnotationCollectorTransform and override the visit() method. A complete example by Guillaume Laforge can be found at Github [2].


The new @AnnotationCollector annotation can be used to group several (AST xform) annotations to a single annotation. Further, its functionality can be extended by custom AST transformation code.

[0] GROOVY-5821: Provide a way to assemble an annoation consisting of several other
[1] Compile-time Metaprogramming - AST Transformations
[2] Github AnnotationCollectorTransform Example by Guillaume Laforge