In Maven is there a way to replace properties in the POM file itself like Ant's build.properties file? - maven

I'm not talking about the Maven Properties Plugin, or resource filtering. I want Maven to replace properties in the POM itself. For example, let's say I have several POMs that reference a particular dependency's version number. I want to be able to load in one properties file for each of those POMs, and then change the values once. Maven would then read the properties file before processing the POM and replace accordingly. I believe this is how Ant does it in a single pass, and the properties are then immutable within the build.xml.

You can do property replacement on the command line if that fits your situation. I change the version of my project in the pom on the commandline (really through NAnt scripts). For example:
mvn deploy -Dproject.version=1.00.00.0-Something-SNAPSHOT
You mentioned you want to change a property that is within the parent tags. In maven 2 (not sure about maven 3) anything within the parent tags cannot be a property and must be the actual values. Maven doesn't evaluate properties with in the parent tags.

You are asking about a multi-module build which often comes to the point of the version number. But the simple answer for that is: Use the maven release plugin so you don't need to deal with the version numbers. Or you can use the versions-maven-plugin to handle modifications of them in an elegant way. And it's best practive not to use properties for versions of parents in pom's (onr that it will work as you described).

Related

Is it possible to see the actual pom.xml executed, including parent dependencies/plugins?

I need to extract a project from a repository which uses several layers of parent projects. Every parent project adds some dependency or plugins or properties. This is becoming a nightmare as I'm not able to build any more the project, once I've manually added pieces from parent projects.
Is there a way to create a list of all dependencies/plugins/properties which are linked by a single pom.xml so that I can build a portable, single Maven project?
Thanks
You can create the effective pom (https://maven.apache.org/plugins/maven-help-plugin/effective-pom-mojo.html) that is a kind of merge with all parent POMs.
This is useful to understand the complete list and configuration of plugins.
Whether this helps you to build a "portable" Maven project, I don't know. Without the appropriate Maven repositories with all the plugins, dependencies and so on, Maven will not build.
Base concept of Maven is CoC (Convention over Configuration). Maven has a SuperPOM and all model is inherited from that. SuperPOM is located in maven-model-builder jar. Here is the source https://maven.apache.org/ref/3.6.2/maven-model-builder/super-pom.html
Each Maven goal is using a merged model called effective pom. The help plugin has effective-pom goal which displays the full model including parent model(s) and SuperPOM.
So the answer is just run: mvn help:effective-pom command to see actual model.

How to built a multi-module Maven project with 4-digits of version string that includes CI build numbers?

I've been asked to do this, so please don't suggest that I shouldn't need to. :-p
We currently build a multi-module project with Maven. We have no problems doing so. We're using the Maven release plugin, and we get SNAPSHOT builds for development and release builds in Jenkins. The release plugin automagically increments the 3rd place of the version string. Life is good.
But, I've been asked to add a 4th place in our version strings, which is populated with the Jenkins build #.
The canonical way I see suggested to do this works fine with a single module: You define a property like build.number, to have a default value of "0-SNAPSHOT", and you define your POM to have a element value like "1.9.${build.number}". And, you set your Jenkins job to define build.number to be the Jenkins build #, for its invocation of Maven.
That would be great, if we had a single module, but we don't. We have multiple modules, and in Maven I can't either
1. not specify a version in the child module POMs, nor
2. use a property in the version of the child module POMs.
I gather it's a bad idea for Maven POMs to try to produce multiple artifacts in a single module (using. say, profiles), so I don't want to try to smoosh this project down to a single module.
I probably could try instead splitting it into separate projects, except that seems drastic, and besides, this project really is producing very tightly-related artifacts, so I want to be sure to build all the artifacts for any source code change in the project.
Any solutions?
The maven-release-plugin has two parameters named releaseVersion and developmentVersion. There you set the version to build and the next version, respectively.
Using Jenkins, you can fill these variables with Jenkins generated content, using e.g. the build number. If you want to read the parts of the version number from the POM, you can use build-helper:parse-version and use terms like ${parsedVersion.majorVersion}.

POM files to use

I'm going to be building a project from the Spring Examples package. Specifically, I am going to be building onto the Simple JPA Example. When I view the POM file however I notice that it references a parent, which contains pretty much every Spring project you can imagine.
Is there a way to tell which POM files I need in order to have the 'Simple JPA Example' project work?
EDIT:
This is why Maven needs to go away!
You can move all the dependencies into the project's pom, remove the reference to the parent pom, then use the maven dependency plugin's analyze goal to sort out what you need. There are examples and a rather nifty script referenced from this popular SO question.
Which parent pom is it (and which sample)? If it's this one have another look at the parent - it doesn't define any dependencies, only dependency management, so that you get a consistent set of versions of everything without having the specify versions in your own dependencies. It's quite a common pattern (look for a blog on "bill of materials" configuration). See also docs on how to use your own parent.

What is the value of project.build.finalName?

The Maven documentation talks about a property called project.build.finalName, but I couldn't find a definition of the value it is set to based on other values in the pom.xml.
How is the value of project.build.finalName computed in absence of an overriding property definition in the pom.xml?
Google that...
Look at the Maven POM reference: http://maven.apache.org/pom.html#BaseBuild_Element
finalName: This is the name of the bundled project when it is finally
built (sans the file extension, for example: my-project-1.0.jar). It
defaults to ${artifactId}-${version}. The term "finalName" is kind of
a misnomer, however, as plugins that build the bundled project have
every right to ignore/modify this name (but they usually do not). For
example, if the maven-jar-plugin is configured to give a jar a
classifier of test, then the actual jar defined above will be built as
my-project-1.0-test.jar.
In the Eclipse Maven POM Editor, the "Effective POM" tab, you can see the value explicitly.
In the IntelliJ Idea, Right-click on the project top folder and then click Maven => Show Effective POM to view the effective pom file. In that file, search for "finalName" to know it.
The final value is composed of the artifact groupId concatenated to the artifact id that you have declared in your pom.xml file

specify a maven2 dependency version from the commandline

I'm working a contract that has some build oddities... they're using maven, but the pom file is actually edited by the build script to replace the version number with the jenkins build number, and then that same number is used to replace the version of other internal projects which will be used at build time by this project. I am new to maven, but know enough to know this feels wrong.
I can pass in the version number, but putting the same property in the dependency block doesn't seem to work.
I know the tao of maven is serious business, please understand this is a very short term contract and build system isn't in my statement of work - I just want to get to a place where the source controlled files aren't edited by the simple act of running a build.
You can definitely define a Maven property with a version value, and reference it in the dependency declaration. And, with Maven properties, they can be passed into maven using the "-D" command line option.
What I'm not sure of it whether the timing of how Maven runs will allow this to change the dependency version. I think (so, I'm not 100% certain) that the dependency management will be managed before command-line options are processed.
I'd try defining a maven property with the dependency version in it, and reference the maven property in the dependency declaration appropriately. Then, when running mvn, supply the desired version as a property value. That'd be the most-likely approach.

Resources