Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven: Pom file - externalizing dependency versions to a properties file

Tags:

maven

I'd like to externalize the dependency versions in the POM file to a properties file.

Example: pom.xml

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>${externalized.junit.version}</version>
</dependency>

abc.properties

externalized.junit.version=4.8.2

Can this be done? If so, what would be the best way to do it?

like image 264
pcs Avatar asked Oct 18 '16 17:10

pcs


People also ask

Is dependency version mandatory in POM xml?

Each maven dependency defined in the pom must have a version either directly or indirectly for example, through dependencyManagement or parent. That being said, if the version is not given, then the version provided in the dependencyManagement or the parent pom will be used.

How do you save dependencies in POM xml?

For that, you need to run a simple command cmd at the same location where pom. xml is present. The command is mvn dependency:analyze, once you run this command you will see those dependencies which are not correct. That's how you can add and manage dependencies in pom.

Does child POM inherit dependency?

Now child POM need to refer the parent POM using parent tag and specifying groupId/artifactId/version attributes. This pom file will inherit all properties and dependencies from parent POM and additionally can include extra sub-project specific dependencies as well.


Video Answer


1 Answers

No, you cannot do that.

When you're launching a Maven command on a project, the first action it takes is creating the effective model of the project. This notably means reading your POM file, reasoning with activated profiles, applying inheritance, performing interpolation on properties... all of this to build the final Maven model. This work is done by the Maven Model Builder component, whose entry point is the ModelBuilder interface, and exit point is the Model class.

The process of building the model is quite complicated, with a lot of steps divided in possibly 2 phases, but the crux of the issue here is simple: at the end of that step, there is a valid effective model to be used by Maven. Which means that all dependencies must have valid group ids, artifact ids, versions; that there are no duplicate dependencies, no plugin execution's with the same ids, etc. (refer to the model description).

Take note that during the model building, interpolation is happening, meaning that if a property is available at that time, and it was used, like ${myProperty}, then it will be replaced with its corresponding value. Among the properties available are:

  • POM content, like ${project.version} or ${project.artifactId};
  • ${project.basedir}, which corresponds to the directory where the pom.xml is;
  • user properties set on the command line with the -D switch (like -DmyProperty=myValue);
  • any properties set directly in the POM file, inside the <properties> element;
  • several built-in Maven properties, like ${maven.build.timestamp}, which represents the date/time at which the build started, or ${maven.version} for the current Maven version;
  • Java system properties, as returned by System.getProperties()
  • environment variables;
  • and finally properties set inside the settings.xml file.

The critical point point here, is that the version of dependencies must be valid when the effective model is built. This is the only way to make sure the dependency graph is stable and consistent during the build.

This is exactly what is failing here: you would want Maven to be able to read versions inside a properties file, so it means binding a plugin to a specific phase of the lifecycle to read that file and somehow refer to the properties read using a standard Maven properties. Trouble is, this would all be happening after the model is already built, so it is too late for that. All of this process is happening before the build lifecycle has even started; no chance to invoke a plugin before that.

This also implies that it would work if you were to define the property as a command-line property (since, as outlined above, it is available during the interpolation process when building the model). But that is not a best practice: specifying dependency version as a command-line property makes the build very hard to reproduce. Better to specify it as a Maven property inside the <properties> element of the POM, or to make use of the <dependencyManagement> scheme in a parent POM or also importing a BOM.

like image 111
Tunaki Avatar answered Oct 02 '22 06:10

Tunaki