Annotate plugins is capable of adding arbitrary annotations to the generated sources.
Annotate plugin uses Annox to read annotations from binding customizations and adds them to the schema-derived classes. Here's a small example:
Below is the generated code:
Please see this test project for example.
The plugin is activated by the
-Xannotate command-line argument.
The purpose of the Annotate Plugin is to allow adding arbitrary annotations to the classes generated by the schema compiler (XJC). When schema is compiled, the Annotate Plugin reads annotation definitions from schema bindings and adds appropriate code to the generated classes.
In order to use this plugin to add your own annotations to the generated classes you have to do two things:
- Activate the plugin.
- Add definitions of annotations you want to add to schema bindings.
First part is trivial. Second part - defining your annotations in schema bindings can be a bit more tricky. It is explained in the next sections.
Schema bindings are essentially XML documents which provide XJC with additional information which may be used to customize schema compilation. There is a number of standard JAXB customization elements (like
jaxb:property), but XJC also allows vendor customizations. Annotate Plugin employs this possibility and uses customization elements as a source for definitions of annotations. Annotations are defined XML elements; Annotate plugin uses Annox to read annotations from XML definitions.
There are mainly two ways to add bindings to your schema: directly in schema files or in external binding files. You can add annotation definitions in both cases, but due to certain technical reasons there are slight differences between these two variants. I'll demonstrate it on an example of
org.hibernate.search.annotations.FieldBridge from Hibernate Search.
Defining annotations directly in schemas
annox:annotate element within schema - it is the customization element that the Annotate Plugin processes. The
hs:FieldBridge sub-element is the XML: definition of the
The key to the elegant definition in the example above is the
http://annox.dev.java.net/org.hibernate.search.annotations associated with the
hs prefix. Namespace URI points to the
org.hibernate.search.annotations package - this is how the Annotate Plugin (i.e. the underlying Annox parser) knows that
hs:FieldBridge is actually
@org.hibernate.search.annotations.FieldBridge Java class.
Defining annotations in external binding files
Unfortunatelly the elegant syntax above does not work when defining customization elements in external binding files. XJC is for some reason too strict here. It considers the package namespace URI (like
http://annox.dev.java.net/org.hibernate.search.annotations above) to be a vendor extension URI and consequently fails. I believe this to be a bug in XJC.
Accordignly, we can't use package namespaces in external binding files. All the binding definitions must be declared in a single namespace. Here's how it looks like:
In this case we had to use
annox:annotate elements everywhere. The
annox:class attribute is used to provide the class name of the annotation. In case of nested annotation definitions
annox:field indicates the field of the annotation.
You can use
annox:annotateElement if you want your customization to be a bit more specific.
If an annotation of the given class already exists, this annotation will be augmented. Thus, the following customizations:
Would result in: