Red Hat

Hibernate Static Metamodel Generator Annotation Processor

Posted by Hardy Ferentschik    |       |    Tagged as

Steve mentioned in his Hibernate 3.5.0 Beta2 blog entry briefly the Hibernate Static Metamodel Generator Annotation Processor. Time to have a closer look what this annotation processor actually does.

Typesafe Criteria API

Let's start with a look at one of the new features of JPA 2 - the type-safe Criteria API. The key to this new API are metamodel classes generated for their corresponding managed entities. These metamodel classes allow the construction of object based queries. Lets look at an example:

@Entity public class Order {
    @Id 
    Integer id;
    @ManyToOne 
    Customer customer;
    @OneToMany 
    Set<Item> items;
    BigDecimal totalCost;
    ...
}

In the above example we have a managed entity Order with an id, a reference to a customer, a list of order items and the total costs. The corresponding metamodel class looks like this:

@StaticMetamodel(Order.class)
public class Order_ {
    public static volatile SingularAttribute<Order, Integer> id;
    public static volatile SingularAttribute<Order, Customer> customer;
    public static volatile SetAttribute<Order, Item> items;
    public static volatile SingularAttribute<Order, BigDecimal> totalCost;
}

Having such a metamodel class allows for queries of the form:

CriteriaBuilder cb = ordersEntityManager.getCriteriaBuilder();
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
SetJoin<Order, Item> itemNode = cq.from(Order.class)
	.join(Order_.orderItems);
cq.where( cb.equal(itemNode.get(Item_.id), 5 ) ) 
	.distinct(true);

I don't want to go any deeper into the actual Criteria API here. Refer to JSR-317 for more information. Instead I would like to answer the question on how to generate this metamodel classes? Of course a developer could manually maintain them, but that would hardly be productive. A better solution is to utilize the annotation processing facilities officially available since Java 6. In Java 6 javac behaves analogously to the apt command in Java 5. This is specified by JSR-269.

Hibernate Static Metamodel Generator

Hibernate Static Metamodel Generator is an implementation of such an annotation processor with the task of creating the static metamodel classes for entities (as seen in the example above). In the following I will show how to integrate the annotation processor into your build environment. The good news is that in most cases the annotation processor will automatically run provided the annotation processor jar is on the classpath. This happens due to Java's Service Provider contract and the fact the the Hibernate Static Metamodel Generator jar files contains the file javax.annotation.processing.Processor in the META-INF/services listing org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor as annotation processor.

Maven

There are several ways of running the annotation processor as part of a Maven build. It will automatically run if you are using a JDK 6 compiler and the annotation processor jar is on the classpath. In case you have more than one annotation processors on your classpath you can explicitly pass the processor option to the compiler plugin:

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.6</source>
        <target>1.6</target>
        <compilerArguments>
        	<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
        </compilerArguments>
    </configuration>
</plugin>

The maven-compiler-plugin approach has the disadvantage that the maven compiler plugin does currently not allow to specify multiple compiler arguments (MCOMPILER-62) and that messages from the Messenger API are suppressed (MCOMPILER-66). A better approach is to disable annotation processing for the compiler plugin:

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.6</source>
        <target>1.6</target>
        <compilerArgument>-proc:none</compilerArgument>
    </configuration>
</plugin>

and use the maven-annotation-plugin for annotation processing (you will need the following additional maven repositories - maven-annotation-plugin and jfrog):

<plugin>
    <groupId>org.bsc.maven</groupId>
    <artifactId>maven-processor-plugin</artifactId>
    <executions>
        <execution>
            <id>process</id>
            <goals>
                <goal>process</goal>
            </goals>
            <phase>generate-sources</phase>
            <configuration>
                <!-- source output directory -->
                <outputDirectory>target/metamodel</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>1.3</version>
    <executions>
        <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>add-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>target/metamodel</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

Last, but not least one could also use the antrun-plugin to run the annotation processor. This approach can be seen here.

Ant

As mentioned before, the annotation processor will run automatically in a Java 6 environment. In case you want configure the processor explicitly or disable it you can use the compilerarg option of the Javac Task. The supported command javac line options are listed here.

Eclipse

Of course you also want to have annotation processing available in your favorite IDE. In Eclipse (at least since the latest Galileo release) exists an additional configuration section under Java Compiler where you can configure all kinds of aspects of annotation processing. Just check the Enable annotation processing option, configure the directory for the generated sources and finally add the Hibernate Static Metamodel Generator and JPA 2 jar files to the factory path.

Idea

Idea does not have an explicit configuration section for annotation processing yet. Instead do you have to rely on the fact that the processing will automatically occur in the case the Hibernate Static Metamodel Generator is on the classpath and you are using a Java 6 compiler. You can, however, specify additional compiler command line options under the Compiler - Java Compiler section.

Feeback

Hopefully this gets you started with the Hibernate Static Metamodel Generator. It would be great to get some feedback. The source code is currently part of the Hibernate svn repository. The trunk is http://anonsvn.jboss.org/repos/hibernate/jpamodelgen/trunk/. The latest SNAPSHOT of the jar file can be retrieved from the JBoss snapshot repository. Bugs should be reported in METAGEN.

Enjoy!

back to top