Generating JPA Canonical Model Metadata In Maven

One of the nice features of JPA 2.x is type-safe queries using the Criteria API. Instead of referencing a string or building an endless bounty of static parameters JPA implementations provide a means to generate them. For example:

EntityManager em = ...
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> at = cq.from(Person.class);
cq.select(at);
// Person_.java is the generated canonical so we don't have to use
// at.get("firstName") and at.get("lastName")
cq.where(cb.and(cb.equal(at.get(Person_.firstName), "John"),
		cb.equal(at.get(Person_.lastName), "Doe")));
TypedQuery<AuditReg> q = em.createQuery(cq);
q.getResultList();

Each JPA implementation has it’s own means for generating canonical model metadata, but most of them provide a javax.annotation.processing.Processor implementation. I’ve seen a few posts demonstrating how to integrate this feature into Maven builds. Most of them use some external Maven plugin to accomplish this, but I found it better to just use the maven-compiler-plugin within a Maven profile. A Maven profile allows us to decouple the projects compilation from the canonical generation so that we aren’t generating canonical metadata every time the project is compiled. This approach makes sense seeing how infrequently the metadata needs to be generated (not to mention it could potentially cause problems using Maven IDE integration tools). It also prevents issues with dependency resolutions. Here is an example using eclipselink:

<build>
	<plugins>
		<plugin>
			<!-- source/target java version needs to be at least 1.6 -->
			<artifactId>maven-compiler-plugin</artifactId>
			<version>3.0</version>
			<configuration>
				<source>1.7</source>
				<target>1.7</target>
			</configuration>
		</plugin>
	</plugins>
</build>
<profiles>
	<profile>
		<id>jpa-canonical-gen</id>
		<build>
			<plugins>
				<plugin>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.0</version>
					<configuration>
						<proc combine.self="override">only</proc>
						<!-- compilerArguments can be removed if there is only one -->
						<!-- PU in the project or eclipselink.canonicalmodel.subpackage -->
						<!-- has been defined for each additional PU added in 
						<!-- persistence.xml for more details see 
						<!-- https://bugs.eclipse.org/bugs/show_bug.cgi?id=308713 -->
						<compilerArguments combine.children="append">
							<Aeclipselink.persistenceunits>
								myPuName
							</Aeclipselink.persistenceunits>
						</compilerArguments>
						<!-- edit the unique directory path to match where the -->
						<!-- JPA entities exist -->
						<includes combine.self="override">
							<include>**/entity/jpa/*.java</include>
						</includes>
						<generatedSourcesDirectory>
							${project.build.sourceDirectory}
						</generatedSourcesDirectory>
						<annotationProcessors combine.self="override">
							<annotationProcessor>
								org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor
							</annotationProcessor>
						</annotationProcessors>
					</configuration>
				</plugin>
			</plugins>
		</build>
		<dependencies>
			<dependency>
				<groupId>org.eclipse.persistence</groupId>
				<artifactId>org.eclipse.persistence.jpa.modelgen</artifactId>
				<version>2.4.0</version>
			</dependency>
		</dependencies>
	</profile>
</profiles>
<dependencies>
	<dependency>
		<groupId>org.eclipse.persistence</groupId>
		<artifactId>org.eclipse.persistence.jpa</artifactId>
		<version>2.4.0</version>
		<scope>compile</scope>
	</dependency>
	<dependency>
		<groupId>org.eclipse.persistence</groupId>
		<artifactId>javax.persistence</artifactId>
		<version>2.0.0</version>
	</dependency>
</dependencies>

The above Maven POM snippet can be executed using the following Maven command and will generate the canonical metadata java source in the same package where the JPA entities exists:

mvn -P jpa-canonical-gen

The example can easily be adapted for other JPA implementations as well by replacing the appropriate project dependencies, profile dependencies (for the annotation processor), and the annotationProcessor with one of the following values:

Advertisements

About ugate
UGate is a fully open source solution for a do-it-yourself configurable indoor/outdoor security system. It's built with Arduino Uno32 (ChipKIT) + JavaFX and a number of other leading software/hardware technologies. Our goal is to provide individuals with access to the most popular hardware sensor technology used in industrial today. Our attempt is to bridge the gap between the hardware and software in an extendable and intuitive GUI interface that is free and open to the public. Visit our code page at: http://ugate.org

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: