Maven update policy snapshots with regards to local and remote snapshots - maven

I would just like to understand definitely the behaviour of the snapshot functionality in maven if your local and remote snapshots differ. For instance, say I had project A, and project B were B depends on A, and I am changing both A and B locally. But also other developers are changing B and deploying the project to the repository where the artefacts are hosted.
How can I ensure that if I am changing B locally, that project A will be using the local B, instead of remote B, even if my local B is older than the remote B? So basically I want to ensure that if I have made any local changes to a dependency project, I want any projects which have the modified project as a dependency to use the local modified version rather than the remote version.
How can I do this? Is there an updatePolicy which does this?

While building with snapshots, Maven will compare the local POM’s timestamp to the remote.
You can control using the updatePolicy with value never , Maven will never try to retrieve another version. It will do that only if it doesn't exist locally
You need to set it in maven Settings.xml as follows
<repositories>
<repository>
<id>exampleSnapshots</id>
<name>example Snapshots</name>
<url>http://example.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
......
</snapshots>
</repository>
</repositories>
other options are always, daily (default), interval:X (where X is an integer in minutes).
Find more information in maven Documentation

Related

Maven: how to purge a custom local repository

Beside the local repository at the default location, I have another local repository with snapshots of a large number of jars of some projects which do not use Maven. It is defined in pom.xml as follows:
<repositories>
<repository>
<snapshots>
<updatePolicy>always</updatePolicy>
</snapshots>
<id>repo</id>
<url>file:///${project.basedir}/path/to/loca/repo</url>
</repository>
</repositories>
and has a distinct <groupId/> so that it is not confused with any other repository. Thanks to this, the main project can be compiled fast and with up-to-date jars on any system which sees its directory.
I would like to purge old snapshots from the custom repository, but
mvn dependency:purge-local-repository -DlocalRepositoryPath=./path/to/local/repo
purges the local repository at the default location, the custom one is left untouched.
How to purge only the repository in the custom directory?

Why is maven hitting repo.maven.apache.org for local jars?

I have a project built and installed in the local maven repository ~/.m2 named com.example.project. From time to time, not always, when I build another project that depends on com.example.project, maven says in debug messages:
Downloading: https://repo.maven.apache.org/maven2/com/example/project/maven-metadata.xml
Why is maven querying that URL and why does this happen occasionally? First, there is nothing on that URL, second, the jar already exists on local repository, third, I didn't change the version number of the local jar dependency. So let us say I have 1000 local projects, will it query URL1, URL2, ..., URL1000. What is the logic of this query to a non-existing URL?
Why is maven querying that URL and why does this happen occasionally?
occasionally: is specifically daily, because it is the default updatepolicy for the maven builtin Central Repository.
If you take a look at the maven super POM, which all pom files inherited from, you will find the repository is configured as follows
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<release> element is not appearing here, so that means the repository will take the default values for it.
enabled (default is true)
updatePolicy (default is daily) --> possible values: "always", "daily" (default), "interval:XXX" (in minutes) or "never" (only if it doesn't exist locally).
hope this helps

maven: what does ` -U,--update-snapshots` really do?

In the command line help, I see that maven "checks" for updates:
-U,--update-snapshots Forces a check for updated
releases and snapshots on remote
repositories
However, most questions on Stack Overflow imply that this option forces Maven to update. Does this mean it forces a re-download of the dependencies?
e.g. https://stackoverflow.com/a/9697970/1119779
If you do not use -U, maven might cache results - even if a dependency could not be found previously (e.g. because your nexus [or alike] was unavailable, misconfigured, didn't contain the dependency [yet] or whatever). SNAPSHOT versioned jars are cached similarly.
If that's the case. Maven follows the repository's updatePolicy, which tells it how often (if ever) maven checks if a dependency has been updated (in the case of SNAPSHOT), or has become available, in the case of a released version. Default is daily therefore if a temp error causes maven to not download a dependency, it might take one day before maven tries again. -U overwrites that and tells it to check now.
-U does not re-download a SNAPSHOT dependency if it has already been downloaded and if the checksum is the same! It only checks for the checksum.
Update: as #Stas pointed out, if the checksum differs, it will re-download and override you local JARs with the ones from the remote repository.
** -U also checks for "updated" release versions if you specify a "version" range etc.
BTW: Maven uses a timestamp file that has the same name as the dependency + ".lastUpdated" to know when a dependency has been last checked on which server. E.g. ~/.m2/repository/org/springframework/spring-webmvc/3.1.2.RELEASE/spring-webmvc-3.1.2.RELEASE.jar.lastUpdated
Example for updatePolicy:
<repositories>
<repository>
<releases>
<enabled>false</enabled>
<updatePolicy>always</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
<!-- ... -->
</repository>
<!-- ... -->
</repositories>
See http://maven.apache.org/pom.html#Repositories for further information about the updatePolicy.
It's important to add that executing mvn -U will override your local SNAPSHOT jars with remote SNAPSHOT jars.
Without -U argument, local SNAPSHOTS won't be override.
when you will get https://repo.spring.io/milestone was
cached in the local repository, resolution will not be reattempted until the update interval of spring-milestones has elapsed or updates are forced
in that case you have to use mvn clean package -U

Is it possible for maven to not search snapshots in release repositories?

I've discovered today, while investigating a bug regarding my project being no more deployable, that maven tries to load dependencies from all available repositories.
I don't find it wise, specifically regarding our internal artifacts, that are searched on amven central, Sonatype FlexMojos, and other external release repositories (specificall when the last one provides a custom 404 page that maven wrongly interprets as valid content, replacing my valid artifact with an invalid one).
So, is is possible to tell maven which repositories to lookup for SNAPSHOTs artifacts, and which to lookup for RELEASE ones ?
Would it help if you made it explicit to not look for snapshots in your repo?
<repositories>
<repository>
<id>central</id>
<name>Maven Repository Switchboard</name>
<layout>default</layout>
<url>http://repo1.maven.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
My solution is to set up a repository mirror in the intranet. That way, Maven needs to know a single URL to download everything.
I then use the internal mirror to bundle repositories (local and remote ones). If snapshot repos are first in the search path, the mirror server will almost never publish the names of my internal artifacts (only when I forgot to deploy them).
On top of that, it will reduce the download times for the rest of the team plus it will make sure that everyone can still work even when there are network problems outside of your control.

Where should I define maven repositories given that I use mirrorOf * in settings.xml?

I have a nexus repo on my network. In settings.xml on the build server we have
<mirror>
<id>company.com</id>
<name>nexus</name>
<url>http://build.company.com/nexus/content/groups/public/</url>
<mirrorOf>*</mirrorOf>
</mirror>
On this build server we have a number of proxy repositories defined for public repos, and I have some commercially licensed artifacts in a hosted repo.
And a profile - Maven cannot resolve my parent pom (artifact in nexus) without this:
<profiles>
<profile>
<id>repos</id>
<repositories>
<repository>
<id>my-local-repo</id>
<name>bootstrapthingy</name>
<url>http://build.company.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<checksumPolicy>fail</checksumPolicy>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>repos</activeProfile>
</activeProfiles>
My question today:
I also have removed all my
<repositories>
tags from the parent pom that all projects (should eventually!) inherit, and everything seems to work.
Is this well and good? I seem to end up a lot thinking about best practice when I work with maven - lately, around where should information be kept?
As my repositories are now defined at Nexus level, there is an element of my build that is no longer source code controlled, and this bothers me.
Yes I would argue you're on the right track!
Maven recommends to think about your infrastructure and plan it! By that it splits project concerns from infrastructure aspects. Project specific configuration goes into the pom.xml while I would vote to put infrastructure configuration into settings.xml
So the company mirror / proxy goes into settings.xml (as infrastructure may change) along with its authentication and environment settings (that are project independant!)
Usually projects do not rely on a per-project repository. If they do they could in almost any case use the nexus server for that (lets say explicit SNAPSHOT dependencies). So the practice to not have repositories in a pom.xml is ok. URL's change and builds should not request artifacts at different locations. It endangers your build reproduce-ability (as does adding all kinds of unstable remote repos into nexus).
I think within a company you need to consider (or simply acknowledge) that builds in projects are not self-maintained. Most open-source projects are since they do not have a common shared infrastructure they may benefit from (or suffer under?). You need to do the best of it but having infrastructure issues solved in settings.xml also means that the project does not need to do that anymore. Has pro's and con's - no doubt about that :)

Resources