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

We create ear files with a lot of cans. Some of them contain persistence.xml files that define save units that reference other banks using

<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 when building the ear, dependency mediation can replace other-1.2.3.jar with other-2.3.4.jar , so my link in the persistence.xml file of the jar becomes invalid .

So my question is: how can I properly manage persistence.xml files in Maven when creating a large ear file?


EDIT:

Let me try to build small examples to make my point clearer:

We 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 file with the entry <jar-file> . 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 am creating an ear from first-ejb-1.0.0.jar and second-ejb-1.0.0.jar . Dependencies are allowed, but only one of the other-*.jar can be included in the ear. Let's 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.

+6
source share
3 answers

maven-ear-plugin has a fileNameMapping property, with which you can specify file name mapping for all dependencies included in the EAR file. The following values โ€‹โ€‹are available: standard , no-version , full , no-version-for-ejb . standard means the file name is an artifact, including. version of the artifact. no-version means that files are only artifactId without version. full means that filename is an artifact of groupId + artifactId +. no-version-for-ejb means that filename is artifactId with no version in case of type EJB.

So, define the ear plugin as follows:

  <plugin> <artifactId>maven-ear-plugin</artifactId> <version>2.10.1</version> <configuration> <fileNameMapping>no-version</fileNameMapping> </configuration> </plugin> 

can do the trick for you.

Alternative 2: Externalize persistence.xml

An alternative approach might be to externalize persistence.xml . The easiest approach is to create a jar containing persistence.xml and place it in the ear lib folder:

 EAR + |- lib + | |- core-module.jar | \- persistence-module.jar + | \- META-INF + | \- persistence.xml |- ejb1-module.jar \- ejb2-module.jar 

EJB modules can be either jar archives or exploded directories. In the setup, as stated above, persistence.xml will look like this:

 <?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 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 storage unit that is defined at the EAR level is usually visible for all application components. However, if a storage unit with the same name is defined by a JAR, WAR or application file in the EAR, the storage unit of this name defined at the EAR level will not be visible to the components defined by this EJB-JAR, WAR or application file, if the link per save unit does not use syntax syntax syntax to specify the path name to disambiguate the link. When the # syntax is used, the path name refers to the jar file of the referenced application file. For example, the syntax ../lib/persistenceUnitRoot.jar#myPersistenceUnit refers to a save unit whose name, as indicated in the name element of the persistence.xml file, is myPersistenceUnit and for which the relative path to the root of the save block is saved ../lib/persistenceUnitRoot.jar .

A save unit can be specified by annotating the entityManager with @PersistenceContext(unitName = "../lib/persistenceUnitRoot.jar#myPersistenceUnit") .

+3
source

So, as you said yourself, by the time you build the EAR, your artifact is built, the jar-file already defined and cannot be changed. Thus, there are two options:

  • jar-file must be a specific version - do not allow the use of other versions
  • jar-file can be any version - exclude version from jar name

1. Strict version

You can force Maven to only consider a specific version of a dependency using a range of one version :

 <dependency> <groupId>my.company</groupId> <artifactId>persistence</artifactId> <!-- require specifically this version --> <version>[1.0.2]</version> </dependency> 

2. Exclude version from jar name

You can add EAR banks with any name even without a version :

  <build> <plugins> <plugin> <artifactId>maven-ear-plugin</artifactId> <version>2.10.1</version> <configuration> <modules> <ejbModule> <groupId>my.company</groupId> <artifactId>persistence</artifactId> <!-- rename artifact in ear --> <bundleFileName>persistence.jar</bundleFileName> </ejbModule> </modules> </configuration> </plugin> </plugins> </build> 
+2
source

Since you have an EAR project and a Others project, I assume you have a parent project.

I'm not quite sure what you mean by

But the correct version number cannot be known when the can is built, because when building the ear, dependency mediation can replace other-1.2.3.jar with another-2.3.4.jar

I understand that the other does not know its version until the ear is built (but why?). You can do the following: in the parent project, define a variable to save the actual final version.

 <properties> <my.final.version>...</my.final.version> </properties> 

Obviously my.final.version should be set with your actual expected value. Then change persistence.xml to the following:

 <jar-file>other-${my.final.version}.jar</jar-file> 

Then in another pom.xml add the following:

 <build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> 

Enabling filtering tells maven to replace the variables.

You might want to fine tune filtering if you do not want to filter on all resources (for performance or for some other reason). Look for the tag includes .

+1
source

All Articles