BusinessTechnology

JPA and Maven and multiple persistence units

I needed to convert an existing Netbeans build to use Maven in order to stabilize the code and support Test Driven Development.

Generally this was a fairly simple process: just move all the source files and resources to the right folders in a new Maven project, and add the dependencies.

Everything was going swimmingly until I ran my first tests and got this really lovely set of errors that didn’t really tell me what was going on:

javax.annotation.processing.FilerException: Attempt to recreate a file for type com.omnistools.GaclAcl_

Now at this point I normally just do a few Google searches and find out how somebody else has solved this problem, but I really wasn’t having any luck at all finding an answer.

I did run across a couple of posts that mentioned seeing this error when using multiple persistence units in the persistence.xml.

Now my project does have a persistence unit for testing outside GlassFish (my chosen EJB container), so my first thought was to move that PU to the “right” place for my tests. So I copied the persistence.xml from src/main/resources/META-INF to the src/test/resources/META-INF and changed them so there was only one PU in each.

Well, that seemed to work for a minute, no more exception on the compile step. But now I had a new problem: I was getting an error that the PU couldn’t be found:

Tests in error:
testinsertTrackingCustomerUnFixed(com.omnistools.service.util.CompanyCustomerTrackingTest): No Persistence provider for EntityManager named ProjectTest-ejbPU
testinsertTrackingWithoutCustomerUnFixed(com.omnistools.service.util.CompanyCustomerTrackingTest): No Persistence provider for EntityManager named ProjectTest-ejbPU
testinsertTrackingCustomerFixed(com.omnistools.service.util.CompanyCustomerTrackingTest): No Persistence provider for EntityManager named ProjectTest-ejbPU
testinsertTrackingWithoutCustomerFixed(com.omnistools.service.util.CompanyCustomerTrackingTest): No Persistence provider for EntityManager named ProjectTest-ejbPU

So doing a bit of digging, it appears that the persistence.xml only gets copied once and only from the src/main/resources/META-INF folder.

I must have tried a thousand different permutations and combinations until I realized that I could have an ugly workaround that is not ideal.

The issue is that if both have the “exclude-unlisted-classes” set to true, the javac compiler tries to recreate the annotation classes during the compiler:compile and of course fails on the second PU because the classes have already been created.

So to get this to work, I set the “exclude-unlisted-classes” to false for one of the PU’s, which gets me the generated meta classes, and the tests fail (because the PU doesn’t include the required entities).

I then flip the flag back to true, and run the build again. Since the classes have already been compiled, the compile:compile doesn’t run, and the tests can succeed.

And then finally, I run across a bug report on the NetBeans site: http://netbeans.org/bugzilla/show_bug.cgi?id=183779. Now this bug talked about setting some compiler flags (in particular -proc:none which tells the compiler not to generate meta classes).

Workaround was proc:none to the javac compiler args as described here: http://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html

        <plugin>            <groupId>org.apache.maven.plugins</groupId>            <artifactId>maven-compiler-plugin</artifactId>            <version>2.3.2</version>            <configuration>                <source>1.7</source>                <target>1.7</target>                <compilerArguments>                    <endorseddirs>${endorsed.dir}</endorseddirs>                    <proc:none/>                    <Xlint/>                    <Xlint:-path/>                    <verbose />                </compilerArguments>                <showDeprecation>true</showDeprecation>            </configuration>        </plugin>

Now my Maven build works like a charm. Both persistence units are defined in my persistence.xml, and both have the “exclude-unlisted-classes” set to false, and not only do my tests work, but the deployment is now successful as well.

Hi, I’m Rob Weaver