We are building ear-files with a large number of jars. Some of them contain persistence.xml files defining persistence units which reference other jars with
<jar-file>other.jar</jar-file>
Now we plan to use Maven in the future and jar names now contain version numbers. This is a huge problem for the mechanism described above: Instead of other.jar
, we need to specify other-1.2.3.jar
. But the correct version number cannot be known when the jar is built because in the construction of the ear, the dependency mediation could replace other-1.2.3.jar
with other-2.3.4.jar
so that my reference in the persistence.xml of the jar becomes invalid.
So my question is: How can I manage the persistence.xml files properly in Maven when building a large ear file?
EDIT:
Let me try to construct a small examples to make my point clearer:
Let us have first-ejb-1.0.0.jar
depending on other-1.2.3.jar
and second-ejb-1.0.0.jar
depending on other-2.3.4.jar
. Both first-ejb-1.0.0.jar
and second-ejb-1.0.0.jar
contain a persistence.xml with a <jar-file>
entry. first-ejb-1.0.0.jar
points to other-1.2.3.jar
and second-ejb-1.0.0.jar
points to other-2.3.4.jar
. So far, so good.
Now I build an ear from first-ejb-1.0.0.jar
and second-ejb-1.0.0.jar
. The dependencies are resolved, but only one of the other-*.jar
can be included in the ear. Say, our dependency mediation chooses other-2.3.4.jar
. Then first-ejb-1.0.0.jar
has a dead <jar-file>
entry, pointing to a non-existent jar.
xml should be put in the EJB JAR's META-INF directory. If you package the persistence unit as a set of classes in a WAR file, persistence. xml should be located in the WAR file's WEB-INF/classes/META-INF directory.
The maven-ear-plugin
has a property fileNameMapping
by which you can specify the file name mapping to use for all dependencies included in the EAR file. The following values are valid standard
, no-version
, full
, no-version-for-ejb
. The standard
means the filename is the artifactId incl. the version of the artifact. The no-version
means the files is only the artifactId without the version. The full
means the filename is the groupId+artifactId+version of the artifact. The no-version-for-ejb
means the filename is the artifactId without the version in case of EJB type.
So specifying the ear plugin as follows:
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>2.10.1</version>
<configuration>
<fileNameMapping>no-version</fileNameMapping>
</configuration>
</plugin>
might do the trick for you.
Alternative 2: Externalize persistence.xml
An alternative approach could be to externalize the persistence.xml
. The most straight forward approach would be to create a jar containing the persistence.xml
and put it into the lib folder of the ear:
EAR +
|- lib +
| |- core-module.jar
| \- persistence-module.jar +
| \- META-INF +
| \- persistence.xml
|- ejb1-module.jar
\- ejb2-module.jar
EJB modules may be either jar archives or exploded directories. In the setup as above the persistence.xml
would look like:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="my-persistence-unit">
<!-- Note: it's relative to `persistence-module.jar` file location in EAR -->
<jar-file>../ejb1-module.jar</jar-file>
<jar-file>../ejb2-module.jar</jar-file>
....
</persistence-unit>
</persistence>
A persistence unit that is defined at the level of the EAR is generally visible to all components in the application. However, if a persistence unit of the same name is defined by an EJB-JAR, WAR, or application jar file within the EAR, the persistence unit of that name defined at EAR level will not be visible to the components defined by that EJB-JAR, WAR, or application jar file unless the persistence unit reference uses the persistence unit name #
syntax to specify a path name to disambiguate the reference. When the #
syntax is used, the path name is relative to the referencing application component jar file. For example, the syntax ../lib/persistenceUnitRoot.jar#myPersistenceUnit
refers to a persistence unit whose name, as specified in the name element of the persistence.xml
file, is myPersistenceUnit
and for which the relative path name of the root of the persistence unit is ../lib/persistenceUnitRoot.jar
.
The persistence unit can be specified by annotating the entityManager with @PersistenceContext(unitName = "../lib/persistenceUnitRoot.jar#myPersistenceUnit")
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With