How exactly does Maven find the LATEST version of an artifact? - java

In our project, we have multiple branches for our main features. As we develop, we want our repository to contain snapshots of the APIs in each branch, so that if a branch depends on another, it can easily get its APIs from the repository. However, we want it to hold multiple snapshot versions, so that if one snapshot breaks something, they can refer to an older snapshot. Our potential naming scheme goes like this
example-1.0-SNAPSHOT-01.jar
example-1.0-SNAPSHOT-02.jar
etc...
Most POM files will use LATEST for the version reference of these snapshot jars.
Anyways, my question is, how exactly does maven determine the LATEST version? Does it go off just the version number (which I think would just be 1.0 for both SNAPSHOT-01 and SNAPSHOT-02) or does it also incorporate a time-stamp?

repository management system (for example nexus) manages snapshots the latest is named as -SNAPSHOT.jar generally and rest of them have timestamp in the file name

Related

Find all the dependency higher versions available from pom.xml

I want to find all the higher versions available for each dependency and download them all of them. I tried to get the version by this command
versions:display-dependency-updates
But it is only displaying the latest version. Instead how should I find all higher versions using a java.
First of all, updating all the dependencies of a project just for having the latest version isn't the most recommended option. You may encounter unintended consequences such as, for example, changing the Java version with which the projects were compiled so you can't deploy your application on your server. My recommendation is that you always keep control of the dependencies you use in your projects and define a specific value appropriate to your needs. But if the supplier of the dependencies is a trustworthy organization and maintains compatibility between its versions, you can use the maven dependency syntax to get the latest. Dependency Version Ranges

Avoid update POM versions for next development iteration with maven-release-plugin

I'm doing my first release with maven-release-plugin and git. Instead of tagging I'm using the release:branch goal. I'm agree with the complete relase-flow process except in one point: all local dependencies are automatically updated to the next SNAPSHOT version in the development branch.
This is my concrete situation: I'm working in a project with more than 20 maven projects. Let's say all of them are in SNAPSHOT version during development. I want to make a release with the maven plugin. After the release is done, all POM versions have been incremented and set again to SNAPSHOT. If I need to make a change in just one line of code of one project (fix a bug) and I make a new release, all projects (by default) must increment their version again when I've just changed one of them.
In my opinion, it makes more sense to continue the development with the state of the last release (all version without SNAPSHOT). In the next development iteration, I can set manually the next SNAPSHOT version only in these projects that I have changed. In the next release, only the changed projects will be "promoted" to a new version but not all of them.
I think this situation is not exceptional but I didn't found information how to do it (and I don't know if I'm breaking the "release" phylosophy...)
Somedy knows how to avoid update all POMs to the next SNAPSHOT version and leave the POM files as the relase version?
Thank you in advance!
The idea of a multimodule project is that all modules are part of the same release cycle. Even is some modules contain no changes, they will be part of the release. As some may say: versions are cheap.
The benefits are bigger compared to the ideal picture you described: it is much easier to manage the versions and to control inter-module dependencies.
Keep in mind that both trunk and branches should always have a SNAPSHOT version, since these are the working copies. If you use final versions, releases will fail, since you can't tag the same version twice, neither can you deploy(=upload) the same version twice. This is very important, because Maven relies on the definition that final versions are immutable, i.e. Maven will never download a final version again once it is available in the local repository.
So if some modules don't have the same release-cycle as the total multimodule project, you should move them out of this multimodule project (or release them all at once).
The differences between releasing individual modules, applications or application systems are summarized in my slideshare presentation http://www.slideshare.net/geertpante/version-mgmt-in-maven (slide 20 and following).
What we sometimes do is set the snapshot version to e.g. 2.0-SNAPSHOT, and do releases as 1.x.y. So in development, we always keep using 2.0-SNAPSHOT, but when we release, we choose older versions, e.g. 1.3, 1.4, and choose 2.0-SNAPSHOT as the next release version.
Also, if you use git, take a look at https://bitbucket.org/atlassian/jgit-flow/wiki/Home. One of the advantages is it keeps a single development branch, and only the releases are merged to the master branch:
mvn jgitflow:release-start -DreleaseVersion=1.2 -DdevelopmentVersion=2.0-SNAPSHOT
mvn jgitflow:release-finish -DreleaseVersion=1.2 -DdevelopmentVersion=2.0-SNAPSHOT

Standards for installing a jar into local repository

I made changes to the source code of a certain project (that exists in maven repo) by taking its source code from svn and having some lines changed in it,
now I need to install this into our local repository so other people using it have access to this update, what are the recommended steps to install this into my local repo, shall i change the version ? shall it be a snapshot ? or shall i just build it with the same version. I just need more standards on doing this
You definitely should not use the same version no. If you use the same version number there will be a lot of confusion as to which jar are you using? The one thats in the maven repo or your local repo. You don't want a person in the future looking at your dependencies and getting thoroughly confused.
Also to be make it absolutely clear, I would change the artifact id as well. Prefix it with your name or some name so that it can be easily distinguished.

What is the Maven way for automatic project versions when doing continuous delivery?

I have a web application where we deploy to production whenever a feature is ready, sometimes that can be a couple of times a day, sometimes it can be a couple of weeks between releases.
Currently, we don't increment our version numbers for our project, and everything has been sitting at version 0.0.1-SNAPSHOT for well over a year.
I am wondering what is the Maven way for doing continuous delivery for a web apps. It seems overkill to bump up the version number on every commit, and never bumping the version number like we are doing now, also seems wrong.
What is the recommend best practice for this type of Maven usage?
The problem is actually a two-fold one:
Advancing project version number in individual pom.xml file (and there can be many).
Updating version number in all dependent components to use latest ones of each other.
I recommend the following presentation that discusses the practical realities of doing continuous delivery with Maven:
You tube presentation on CD with Maven
Slides
The key takeaway is each build is a potential release, so don't use snapshots.
This is my summary based on the video linked by Mark O'Connor's answer.
The solution requires a DVCS like git and a CI server like Jenkins.
Don't use snapshot builds in the Continuous Delivery pipeline and don't use the maven release plugin.
Snapshot versions such as 1.0-SNAPSHOT are turned into real versions such as 1.0.buildNumber where the buildNumber is the Jenkins job number.
Algorithm steps:
Jenkins clones the git repo with the source code, and say the source code has version 1.0-SNAPSHOT
Jenkins creates a git branch called 1.0.JENKINS-JOB-NUMBER so the snapshot version is turned into a real version 1.0.124
Jenkins invokes the maven versions plugin to change the version number in the pom.xml files from 1.0-SNAPSHOT to 1.0.JENKINS-JOB-NUMBER
Jenkins invokes mvn install
If the mvn install is a success then Jenkins will commit the branch 1.0.JENKINS-JOB-NUMBER and a real non-snapshot version is created with a proper tag in git to reproduce later. If the mvn install fails then Jenkins will just delete the newly created branch and fail the build.
I highly recommend the video linked from Mark's answer.
Starting from Maven 3.2.1 continuous delivery friendly versions are supported out of the box : https://issues.apache.org/jira/browse/MNG-5576
You can use 3 predefined variables in version:
${changelist}
${revision}
${sha1}
So what you basically do is :
Set your version to e.g. 1.0.0-${revision}. (You can use mvn versions:set to do it quickly and correctly in multi-module project.)
Put a property <revision>SNAPSHOT</revision> for local development.
In your CI environment run mvn clean install -Drevision=${BUILD_NUMBER} or something like this or even mvn clean verify -Drevision=${BUILD_NUMBER}.
You can use for example https://wiki.jenkins-ci.org/display/JENKINS/Version+Number+Plugin to generate interesting build numbers.
Once you find out that the build is stable (e.g. pass acceptance tests) you can push the version to Nexus or other repository. Any unstable builds just go to trash.
There are some great discussions and proposals how to deal with the maven version number and continuous delivery (CD) (I will add them after my part of the answer).
So first my opinion on SNAPSHOT versions. In maven a SNAPSHOT shows that this is currently under development to the specific version before the SNAPSHOT suffix. Because of this, tools like Nexus or the maven-release-plugin has a special treatment for SNAPSHOTS. For Nexus they are stored in a separate repository and its allowed to update multiple artefacts with the same SNAPSHOT release version. So a SNAPSHOT can change without you knowing about it (because you never increment any number in your pom). Because of this I do not recommend to use SNAPSHOT dependencies in a project especially in a CD world since the build is not reliable any more.
SNAPSHOT as project version would be a problem when your project is used by other ones, because of the above reasons.
An other problem of SNAPSHOT for me is that is not really traceable or reproducibly any more. When I see a version 0.0.1-SNAPSHOT in production I need to do some searching to find out when it was build from which revision it was build. When I find a releases of this software on a filesystem I need to have a look at the pom.properties or MANIFEST file to see if this is old garbage or maybe the latest and greatest version.
To avoid the manual change of the version number (especially when you build multiple builds a day) let the Build Server change the number for you. So for development I would go with a
<major>.<minor>-SNAPSHOT
version but when building a new release the Build Server could replace the SNAPSHOT with something more unique and traceable.
For example one of this:
<major>.<minor>-b<buildNumber>
<major>.<minor>-r<scmNumber>
So the major and minor number can be used for marketing issues or to just show that a new great milestone is reached and can be changed manually when ever you want it. And the buildNumber (number from your Continuous Integration server) or the scmNumber (Revision of SUbversion or GIT) make each release unique and traceable. When using the buildNumber or Subversion revision the project versions are even sortable (not with GIT numbers). With the buildNumber or the scmNumber is also kinda easy to see what changes are in this release.
An other example is the versioning of stackoverflow which use
<year>.<month>.<day>.<buildNumber>
And here the missing links:
Versioning in a Pipeline
Continuous Delivery and Maven
DON'T DO THIS!
<Major>.<minor>-<build>
will bite you in the backside because Maven treats anything after a hyphen as LEXICAL. This means version 1 will be lexically higher than 10.
This is bad as if you're asking for the latest version of something in maven, then the above point wins.
The solution is to use a decimal point instead of a hyphen preceding the build number.
DO THIS!
<Major>.<minor>.<build>
It's okay to have SNAPSHOT versions locally, but as part of a build, it's better to use
mvn versions:set -DnewVersion=${major}.${minor}.${build.number}
There are ways to derive the major/minor version from the pom, eg using help:evaluate and pipe to a environment variable before invoking versions:set. This is dirty, but I really scratched my head (and others in my team) to make it simpler, and (at the time) Maven wasn't mature enough to handle this. I believe Maven 2.3.1 might have something that go some way in helping this, so this info may no longer be relevant.
It's okay for a bunch of developers to release on the same major.minor version - but it's always good to be mindful that minor changes are non-breaking and major version changes have some breaking API change, or deprecation of functionality/behaviour.
From a Continuous Delivery perspective every build is potentially releasable, therefore every check-in should create a build.
At my work for web apps we currently use this versioning pattern:
<jenkins build num>-<git-short-hash>
Example: 247-262e37b9.
This is nice because it it gives you a version that is always unique and traceable back to the jenkins build and git revision that produced it.
In Maven 3.2.1+ they finally killed the warnings for using a ${property} as a version so that makes it really easy to build these. Simply change all your poms to use <version>${revision}</version> and build with -Drevision=whatever. The only issue with that is that in your released poms the version will stay at ${revision} in the actual pom file which can cause all sorts of weird issues. To solve this I wrote a simple maven plugin (https://github.com/jeffskj/cd-versions-maven-plugin) which does the variable replacement in the file.
As a starting point you may have a look at Maven: The Complete Reference. Project Versions.
Then there is a good post on versioning strategy.

What exactly is a Maven Snapshot and why do we need it?

I am a bit confused about the meaning of a Maven Snapshot and why we build one?
A snapshot version in Maven is one that has not been released.
The idea is that before a 1.0 release (or any other release) is done, there exists a 1.0-SNAPSHOT. That version is what might become 1.0. It's basically "1.0 under development". This might be close to a real 1.0 release, or pretty far (right after the 0.9 release, for example).
The difference between a "real" version and a snapshot version is that snapshots might get updates. That means that downloading 1.0-SNAPSHOT today might give a different file than downloading it yesterday or tomorrow.
Usually, snapshot dependencies should only exist during development and no released version (i.e. no non-snapshot) should have a dependency on a snapshot version.
The three others answers provide you a good vision of what a -SNAPSHOT version is. I just wanted to add some information regarding the behavior of Maven when it finds a SNAPSHOT dependency.
When you build an application, Maven will search for dependencies in the local repository. If a stable version is not found there, it will search the remote repositories (defined in settings.xml or pom.xml) to retrieve this dependency. Then, it will copy it into the local repository, to make it available for the next builds.
For example, a foo-1.0.jar library is considered as a stable version, and if Maven finds it in the local repository, it will use this one for the current build.
Now, if you need a foo-1.0-SNAPSHOT.jar library, Maven will know that this version is not stable and is subject to changes. That's why Maven will try to find a newer version in the remote repositories, even if a version of this library is found on the local repository. However, this check is made only once per day. That means that if you have a foo-1.0-20110506.110000-1.jar (i.e. this library has been generated on 2011/05/06 at 11:00:00) in your local repository, and if you run the Maven build again the same day, Maven will not check the repositories for a newer version.
Maven provides you a way to change this update policy in your repository definition:
<repository>
<id>foo-repository</id>
<url>...</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>XXX</updatePolicy>
</snapshots>
</repository>
where XXX can be:
always: Maven will check for a newer version on every build;
daily, the default value;
interval:XXX: an interval in minutes (XXX)
never: Maven will never try to retrieve another version. It will do that only if it doesn't exist locally. With the configuration, SNAPSHOT version will be handled as the stable libraries.
(model of the settings.xml can be found here)
The "SNAPSHOT" term means that the build is a snapshot of your code at a given time.
It usually means that this version is still under heavy development.
When the code is ready and it is time to release it, you will want to change the version listed in the POM. Then instead of having a "SNAPSHOT" you would use a label like "1.0".
For some help with versioning, check out the Semantic Versioning specification.
A "release" is the final build for a version which does not change.
A "snapshot" is a build which can be replaced by another build which has the same name. It implies that the build could change at any time and is still under active development.
You have different artifacts for different builds based on the same code. E.g. you might have one with debugging and one without. One for Java 5.0 and one for Java 6. Generally its simpler to have one build which does everything you need. ;)
Maven versions can contain a string literal "SNAPSHOT" to signify that a project is currently under active development.
For example, if your project has a version of “1.0-SNAPSHOT” and you deploy this project’s artifacts to a Maven repository,
Maven would expand this version to “1.0-20080207-230803-1” if you were to
deploy a release at 11:08 PM on February 7th, 2008 UTC. In other words, when you
deploy a snapshot, you are not making a release of a software component; you are
releasing a snapshot of a component at a specific time.
So mainly snapshot versions are used for projects under active development.
If your project depends on a software component that is under active development,
you can depend on a snapshot release, and Maven will periodically attempt
to download the latest snapshot from a repository when you run a build. Similarly, if
the next release of your system is going to have a version “1.8,” your project would
have a “1.8-SNAPSHOT” version until it was formally released.
For example , the following dependency would always download the latest 1.8 development JAR of spring:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>1.8-SNAPSHOT”</version>
</dependency>
Maven
An example of maven release process
I'd like to make a point about terminology. The other answers gave good explanations about what a "snapshot" version is in the context of Maven. But does it follow that a non-snapshot version should be termed a "release" version?
There is some tension between the semantic versioning idea of a "release" version, which would seem to be any version that does not have a qualifier such as -SNAPSHOT but also does not have a qualifier such as -beta.4; and Maven's idea idea of a "release" version, which only seems to include the absence of -SNAPSHOT.
In other words, there is a semantic ambiguity of whether "release" means "we can release it to Maven Central" or "the software is in its final release to the public". We could consider -beta.4 to be a "release" version if we release it to the public, but it's not a "final release". Semantic versioning clearly says that something like -beta.4 is a "pre-release" version, so it wouldn't make sense for it to be called a "release" version, even without -SNAPSHOT. In fact by definition even -rc.5 is a release candidate, not an actual release, even though we may allow public access for testing.
So Maven notwithstanding, in my opinion it seems more appropriate only to call a "release" version one that doesn't have any qualifier at all, not even -beta.4. Perhaps a better name for a Maven non-snapshot version would be a "stable" version (inspired by another answer). Thus we would have:
1.2.3-beta.4-SNAPSHOT: A snapshot version of a pre-release version.
1.2.3-SNAPSHOT: A snapshot version of a release version.
1.2.3-beta.4: A stable version of a pre-release version.
1.2.3: A release version (which is a stable, non-snapshot version, obviously).
usually in maven we have two types of builds
1)Snapshot builds
2)Release builds
snapshot builds:SNAPSHOT is the special version that indicate current deployment copy not like a regular version, maven checks the version for every build in the remote repository
so the snapshot builds are nothing but development builds.
Release builds:Release means removing the SNAPSHOT at the version for the build, these are the regular build versions.
A Maven SNAPSHOT is an artifact created by a Maven build and pretends to help developers in the software development cycle.
A SNAPSHOT is an artifact (or project build result ) that is not pretended to be used anywhere, it's only a temporarily .jar, ear, ... created to test the build process or to test new requirements that are not yet ready to go to a production environment.
After you are happy with the SNAPSHOT artifact quality, you can create a RELEASE artifact that can be used by other projects or can be deployed itself.
In your project, you can define a SNAPSHOT using the version element in the pom.xml file of Maven:
<groupId>example.project.maven</groupId>
<artifactId>MavenEclipseExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<description>Maven pom example</description>
If you want to understand better Maven you can look into these articles too:
https://connected2know.com/programming/menu-maven-articles/
This is how a snapshot looks like for a repository and in this case is not enabled, which means that the repository referred in here is stable and there's no need for updates.
<project>
...
<repositories>
<repository>
<id>lds-main</id>
<name>LDS Main Repo</name>
<url>http://code.lds.org/nexus/content/groups/main-repo</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
Another case would be for:
<snapshots>
<enabled>true</enabled>
</snapshots>
which means that Maven will look for updates for this repository. You can also specify an interval for the updates with tag.
simply snapshot means it is the version which is not stable one.
when version includes snapshot like 1.0.0 -SNAPSHOT means it is not stable version and look for remote repository to resolve dependencies
Snapshot simply means depending on your configuration Maven will check latest changes on a special dependency. Snapshot is unstable because it is under development but if on a special project needs to has a latest changes you must configure your dependency version to snapshot version. This scenario occurs in big organizations with multiple products that these products related to each other very closely.
understanding the context of SDLC will help understand the difference between snapshot and the release. During the dev process developers all contribute their features to a baseline branch. At some point the lead thinks enough features have accumulated then he will cut a release branch from the baseline branch. Any builds prior to this time point are snapshots. Builds post to this point are releases. Be noted, release builds could change too before going to production if any defect spot during the release testing.
As the name suggests, snapshot refers to a state of project and its dependencies at that moment of time. Whenever maven finds a newer SNAPSHOT of the project, it downloads and replaces the older .jar file of the project in the local repository.
Snapshot versions are used for projects under active development. If your project depends on a software component that is under active development, you can depend on a snapshot release, and Maven will periodically attempt to download the latest snapshot from a repository when you run a build.
In development phase Maven snapshots everyday looks for newer higher version if available in nexus repository n download it locally for next build.
Four option you can set in respository defination
Always,
Daily (default),
Interval,
Never,
Note: In production release we should not have dependency on snapshot version.
The SNAPSHOT value refers to the 'latest' code along a development branch and provides no guarantee the code is stable or unchanging. Conversely, the code in a 'release' version (any version value without the suffix SNAPSHOT) is unchanging.
In other words, a SNAPSHOT version is the 'development' version before the final 'release' version. The SNAPSHOT is "older" than its release.
During the release process, a version of x.y-SNAPSHOT changes to x.y. The release process also increments the development version to x.(y+1)-SNAPSHOT. For example, version 1.0-SNAPSHOT is released as version 1.0, and the new development version is version 1.1-SNAPSHOT.

Categories