Maven2 inheritance - maven-2

If I have a parent pom and want to inherit this to several projects. I usually do this by adding in top of the project <parent> ... </parent>. What I don't like about this approach is that if something changes in my parent I have to edit all project which are inherited by that parent to modify the version number. Is there a better approach? I hope it is understandable what I'm trying to explain.
Thanks in advance.

What i don't like about this approach
is that if something changes in my
parent i have to edit all project
which are inherited by that parent to
modify the version number. Is there a
better approach?
Yes there is! Have a look at the Maven Versions Plugin, specifically:
versions:update-child-modules updates the parent section of the
child modules of a project so the
version matches the version of the
current project.
For example, if you
have an aggregator pom that is also
the parent for the projects that it
aggregates and the children and parent
versions get out of sync, this mojo
can help fix the versions of the child
modules.
(Note you may need to invoke
Maven with the -N option in order to
run this goal if your project is
broken so badly that it cannot build
because of the version mis-match).
Edit: Of course, using Maven3 you can now have < version >-less < parent > elements in sub modules:
Developers working in multi-module or multi-pom projects won't have to specify the parent version in every sub-module in Maven 3. Instead, you can add version-less parent elements.
Ref

You can use the Maven Release Plugin when doing a release. It will update all the version numbers automatically and create a tag in your source control (if you have SCM configured in the POM).
My commands for performing a release are typically as follows, after which I export the tag from SCM and build it with "mvn clean package" or "mvn clean deploy".
svn update (or whatever SCM you use)
mvn clean
mvn release:prepare -DautoVersionSubmodules=true
mvn release:clean
So for example if you version is first "1.0-SNAPSHOT", then the release plugin will create a tag "projectname-1.0" with version "1.0", and finally increase the current version to "1.1-SNAPSHOT". The plugin will ask you for the versions and tag name, so you can override the defaults.

Automatic Parent versioning (i.e. omission of the tag) is a contentious issue in the Maven space. There is a defect logged against it. For now, it is being considered as a fix or improvement in the 2.1 version branch,

You should keep your versions as snapshots until it's time to release. This way you won't have to change it every time you change the pom. However once you've released a parent pom, you will want to make the change to all the children (assuming the parent is outside the "reactor" build...otherwise it would have been all bumped together by the release plugin). There is a relatively new plugin called the versions-maven-plugin that can assist with changing the versions.

I think the important thing to realize is that in a multi-module build, maven always uses the the version that is from your local repository. This applies in multi-module builds too! So when you reference the "parent" pom you're getting the published parent artifact from your local maven repository. So when you do mvn install you repeatedly publish each module to your local repo.
While developing, your own modules are probably versioned to something like X.X-SNAPSHOT. The reference to the parent-pom is X.X-SNAPSHOT. Don't change these before you're ready to release.
So a simple case would be:
Before initial release all modules are called 1.0-SNAPSHOT.
When makin the initial release "golden build", rename all 1.0-SNAPSHOT modules to 1.0.
When starting development on the 1.1 release, you change all version numbers to 1.1-SNAPSHOT.
And so on...
The custom is to work with snapshot versions until you're releasing, at which point you update the version numbers everywhere. In the day-to-day development you do not change the version numbers because snapshot-releases get treated differently than hard-version releases.
Edit:
After some thought I think some of your confusion in the "comments" section arises from this: The version number in your pom reflects the overall application version. Any given pom change does not necessarily change the application version number. If you need to track changes in the pom I would suggest you use a source control system. So in the 3 month period you work on version 1.0, it's reasonable to keep the version number at 1.0-SNAPSHOT. In the (for instance) 3 week period you work on 1.1, the version number is 1.1-SNAPSHOT.

Related

How to handle maven versions in a multi module project?

I have a maven project infrastructure like this:
/trunk/all/pom.xml
/trunk/all/libs/lib1/pom.xml
/lib2/pom.xml
...
/trunk/all/projects/p1/pom.xml
/p2/pom.xml
...
You see, I have a lot of libraries and a lot of projects using these libraries.
All this is combined to one multi module project, because I like to
import the top project into eclipse and have all my libraries and projects available at once
only do a single mvn test to compile and test all my code after I've done some global refactorings.
Currently, all my modules are version 1.0-SNAPSHOT.
Now I want to release project p2 and all libs p2 uses (e.g. lib1 and lib2) to version 1.0. After that I do some code modifications on lib1, but none on lib2.
I want the next release of p2 being version 1.1, using lib1 in version 1.1 (it was modified since the last release), but lib2 still in version 1.0 (since it wasn't modified).
More general: If I do a release, I want to increase the minor numbers of the project being released and of all changed libraries since the last release.
Question
Do I have to take care for all the module versions by myself or is there a plugin that is able to do the required work for me?
Do I have to take care for all the module versions by myself or is there a plugin that is able to do the required work for me?
Well, if you don't want to keep the versions of the various artifacts (projects, libs) in sync with the version defined in all/pom.xml (i.e. just inherit it through the whole hierarchy), I'm afraid you'll have to start to manage them manually. I'm just not sure to understand why you wouldn't bump the version of say lib2 even if you didn't make any change to it. With your current svn repository structure, all artifacts have the same release lifecycle somehow (when you'll tag the trunk, you'll tag everything in it).
Now, if p1 and p2 (I'll ignore the libs for the sake of simplicity) have an independent release cycle, I would recommend a multiple "trunk/tags/branches" structure as described in this thread:
myrepo
+ .links (2)
+ trunks
+ pom.xml
+ parent-pom (1)
+ trunk
+ pom.xml
+ project-A
+ trunk
+ pom.xml
+ project-B
+ trunk
+ pom.xml
1) The parent POM of the project has
an own release cycle. Every
component's POM will use it as parent
(referenced simply with groupId and
artifactId, no relativePath). For
a release you'll have to release the
parent POM first.
2) This is a construction to enable
easy check outs of a specific branch
of the project i.e. normally the
trunk. A subversion user checks out
myrepo/.links/trunk to get the head
revision of all sources. The trick is,
that that directory contains
external links (i.e. with the
svn:externals property) to the
trunks of all other modules of this
project (parent-pom, project-A,
project-B). The pom.xml in this
directory is never released, it
contains simply a modules section for
the three modules to enable a multi
module build. With this construct
you're able to setup easily branches
e.g.:
myrepo
+ .links
+ branch-2.x
+ pom.xml
I've used this setup many times (I already wrote about it here on SO, see the related questions below), it works very well. Actually, many projects, including Maven, are using this approach, it's not a fantasy one.
This will not solve your "automagic" version handling (I don't know any solution for that) but at least, this structure plays nicely with the Maven Release Plugin and would support your independent release cycle requirements.
See also
Building Maven
XWiki Platform Structure
Cargo SVN
Related questions
Maven parent pom vs modules pom
Migrating to maven from an unusual svn directory structure?
HI!
Maybe I'm missing something, but if your libs/modules start feeling the need to have their own version numbers, isn't that an indication that they are growin up and taking on a life of their own - i.e. becoming separate-ish projects in their own right?
Meaning it might make sense to treat them as such - treat them as separate projects, pushed to some mvn repo, and added to the core project as normal dependencies?
Sorry if I'm missing the point somehow, but I've been running into multi-module project "issues" myself....and maybe the issue isn't really an issue at all?

Specify artifact version outside of pom

Is there a way to specify the artifact version outside of the POM file?
I have 2 CI projects that build an artifact. One builds a "stable" development version from a 'develop' branch and the other builds an unstable version which is the result of merging all active feature branches into the develop branch. I want the stable version to build as xyz-1.0.jar and the integration build to go in as xyz-1.0-SNAPSHOT.jar. Is there a way for the CI job to run a maven task or specify via the command line if a release or snapshot jar should be built without manually modifying the POM? Currently I have the version specified as 1.0 in the pom. I considered using the release plugin but I don't want the automatic version number increase and tagging that it does.
Short answer: no. And here are some additional remarks:
It doesn't make much sense to use a "released" version (i.e. non SNAPSHOT) for a branch under CI since released versions are not downloaded again even if a newer version is available.
Released versions should be tagged (e.g. 1.0), maintenance is done is in a branch derived from the tag (e.g. 1.0.1-SNAPSHOT).
If you want to distinguish versions built from different branches, use different versions in the POMs.
I was able to accomplish this by using a property in my POM and then overriding it via the command line.
pom.xml:
...
<version>${artifactVersion}</version>
<properties>
<artifactVersion>1.0</artifactVersion> <!-- default version -->
</properties>
...
Then overriding with mvn -DartifactVersion=1.0-SNAPSHOT package
But Pascal's answer above is more in line with what I was really asking. My solution is more of a workaround I feel.
You should be able to achieve this using maven profiles

Publishing POMs via Maven and inserting build version info

I'm building Maven projects via TeamCity/Git and trying to insert the TeamCity build numbers in the pom.xml that gets published to my repository upon a successful build. Unfortunately I can't determine how to publish a pom.xml with the substitutions inserted.
My pom.xml contains info like:
<version>${build.number}</version>
where build.number is provided by TeamCity. That all builds ok, and if (say) build.number = 0.1, then the deployment is a pom.xml to a directory with 0.1. All well and good.
However, the pom.xml that is deployed is the pom.xml without the substitutions made. i.e. Maven is running with a pom.xml with appropriate substitutions, but deploys the initial version and so I get
<version>${build.number}</version>
in the final pom.xml. How can I get the build version number in the pom.xml ?
I wouldn't use this approach because it makes building a project checked out from the SCM not possible without providing the build.number property. I don't think that this is a good thing. Maybe I'm missing something though.
Actually, I don't get what you are trying to achieve exactly (why don't you write the build number in the manifest for example). But, according to the Maven Features on the Teamcity website:
By default, it also keeps TeamCity build number in sync with the Maven version number (...).
Couldn't that be helpful? There is another thread about this here.
Try to use generateReleasePoms property of maven-realease-plugin, maybe that helps a little.

LATEST version of parent project in Maven

I am using Maven2. I have created a parent POM for my organization. I want the various groups will use it as a parent for their project but I want them to use the latest version.
for some reason, using it as a parent with version LATEST doesn't work,
any idea?
Thanks,
Ronen.
You don't need to define a new version for every small change you make in the POM.
The version means specific features of an artifact (in a POM are build settings), what I'd do is to declare one version and make all the projects use that version (to use a SNAPSHOT version is a great idea). If you make a small update do it in that version. If you make a bigger change you might want to declare a new version and have all the new POMs to use that version, this way you'll avoid to break old projects by using a new super POM.
Maven version plugin has a goal version:update-parent to set the parent version to the latest parent version.
Just execute
mvn versions:update-parent
in the project which you want to use latest parent version, it modifies the POM files for you.
I think you want to use SNAPSHOT, e.g.
<version>1.2-SNAPSHOT</version>
You need to run mvn with parameter -U in order to force the update of the local metadata files which hold the mappings for LATEST and RELEASE versions.

how to release a project which depends on a 3rd party SNAPSHOT project in maven

i would like to release a snapshot project 'foo-1.0-SNAPSHOT' using the maven release plugin. The project depends on a 3rd party module 'bar-1.0-SNAPSHOT' which is not released yet.
I use the option 'allowTimestampedSnapshots' in my project's pom.xml to allow timestamped snapshots but i assume that the 3rd party module (bar) is not timestamped unless i build it myself as maven still complains about unresolved SNAPSHOT dependencies.
Is there a way to release the project foo regardless of dependent SNAPSHOT projects and if not how could i add a timestamp to the 3rd party project?
Problem is with the allowTimestampedSnapshots parameter name, it's in the documentation but the plugin's source uses a different parameter name in expression - ignoreSnapshots.
So just use -DignoreSnapshots=true and the prepare goal of the release plugin will ignore snapshot dependencies.
Using the maven-release-plugin option
-DignoreSnapshots=true
instead of
-DallowTimestampedSnapshots=true
helped in my case, this will allow to use dependencies with snapshot version to prepare and perform a release.
This option should be handled very carefully, because using snapshot versions in a release can later break your release, if the snapshot dependency is updated, which in normal case is not what you want.
The short answer is see the following answer.... the long answer is you can work around it.
The only way I have coped in the past is to effectively fork the 3rd party library and cut a release myself. This of course is easier said than done and is just plain difficult if the library is large and complex and impossible if the 3rd party library is closed source. An easier route maybe to approach the 3rd party and ask them to cut a release.
Another option may be to copy their pom (ensure that it has no snapshots) change the version information and manually install the pom and artifact in your repository.
The previous answer suggested changing the group and artifact id...don't do this as maven won't recognize it as the same artifact later when this dependency is released and you'll end up with two copies on the classpath. My preferred method is to change only the version and I'll do something like : [original version]-[my org name]-[svn version i pulled it from] so i get something like 1.0-SONATYPE-3425. By using the svn rev, i can always pull the source again and patch it if needed and know exactly what i'm using without pulling the whole source into my own svn.
Update - I blogged about this a while back.
Just install the jar with a pom you own. I generally change the group and artifact id to make it clear that this is not the official version, but that's generally the best work around for your problem.