Throughout my work with EJBGen, EJB3 and TestNG, I have identified a couple
of annotation-related patterns that have proven to be quite powerful.  They
are called "Annotation inheritance" and "Class-scoped annotations".

Annotation Inheritance

The idea is simply to extend the familiar inheritance mechanisms to
annotations.  Consider the following annotation:

public @interface Author {
  public String lastName();
  public String date();
}

And an example use:

@Author(lastName = "Beust", date = "February 25th, 2005")
public class BaseTest {
// …
}

public class Test extends BaseTest {
// …
}

If you try to look up annotations on the Test class using the
standard reflection API, you will find none, since inheritance is not supported
by JSR-175 (I submitted the idea but it was decided to keep the specification
simple and leave this kind of behavior to tools, which is exactly what we are
doing right now).

A tool using this pattern would therefore see an @Author annotation
on both BaseTest and Test.

Since we follow the same overriding rules as Java, inheritance would also
work on methods that have identical names and signatures.

Where things get interesting is when you start considering "partial
inheritance" (or partial overriding).  Consider the following:

@Author(lastName = "Beust", date = "February 25th, 2005")
public class BaseTest {
// …
}

@Author(date = "February 26th, 2005")
public class Test extends BaseTest {
// …
}

This time, the class Test is overriding the @Author
annotation but only partially.  Obviously, the date attribute in
the @Author annotation will return "February 26th, 2005", but what is
the value of name?  Should it be null or "Beust"?

My experience seems to indicate that while not necessarily the most
intuitive, the latter form (partial overriding) is the one that is the most
powerful.  Partial overriding is a very effective way to implement
"Programming by Defaults", which is a way of saying that you provide code with
defaults that do the right thing for 80% of the cases. 

Basically, all you need to do to provide these defaults is to store these
annotations on a base class and require client code to extend these base
classes.  Clients are then free to either override already-defined
attributes or add their own, and the tool will gather all the attributes by
collecting them throughout the inheritance hierarchy, starting from the subclass
and working its way up to the base classes.

In a next entry, I will describe the Class-Scoped Annotation pattern, and
more importantly, how it can be combined with Annotation Inheritance to create
some very elegant constructs.