Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Version number in jar name - how to handle persistence.xml?

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.

like image 646
J Fabian Meier Avatar asked May 18 '16 08:05

J Fabian Meier


People also ask

Where do I put persistence xml?

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.


1 Answers

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").

like image 149
uniknow Avatar answered Sep 28 '22 00:09

uniknow