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

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

Related

Maven update policy snapshots with regards to local and remote snapshots

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

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

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.

Maven: Manually install a Jar from local folder and then go online and grab & install all its dependencies

In my project's pom file I have a dependency that I can see in Maven central repository, javax.enterprise:cdi-api:jar:1.0-SP4 but for some reason I am getting on some of my computers the following error while building the project (hence the build fails):
[INFO] Unable to find resource 'javax.enterprise:cdi-api:jar:1.0-SP4' in repository central (http://repo1.maven.org/maven2)
Any idea why I get this error only on some of my computers (I can say all the computers are using the same network)?
Why do I get this error at all? As far as I can see the jar IS in the maven central repository.
Even though maven could not locate/download the jar on some of the computers, I was able to download it manually through the browser on these computers. How could it be?
Okay, so I've downloaded the jar manually through the browser at one of the problematic computers. I want to install it manually to the local repository on this computer. So from the command line I do:
mvn install:install-file -DgroupId=javax.enterprise -DartifactId=cdi-api -Dversion=1.0-SP4 -Dpackaging=jar -Dfile=path/to/file
...but none of its dependencies has been downloaded as well. Is there some maven plugin to install the file to the local repository AND download & install all its dependencies to the local repository?
If so, please show me how to use it.
Please check in the computers where the jar are not downloaded if the settings.xml file present in .m2 folder is having the url of the jar needed. If not add them.
You are not able to download because maven searches in the urls defined in the settings.xml file only. So if the url is not present there, even if the jar is in the central repository it wont be downloaded.
In your browser you can navigate to that link and download. Maven wont be able to do it for the reason given in the second point
Ok, looks like you need to mention your repository path in your pom file, What is the url of the repository? is it local to your network or some open url? for example: http://repo2.mvn.org/???
Sample example would be like this::
<repositories>
<repository>
<id>codehausSnapshots</id>
<name>Codehaus Snapshots</name>
<releases>
<enabled>false</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
<url>http://snapshots.maven.codehaus.org/maven2</url>
<layout>default</layout>
</repository>
</repositories>
If you could paste the pom file, it would be easier to help you.
To answer your 3 point: Check the settings.xml file in .m2\settings.xml, make sure that same content is present. Sometimes settings.xml are modified directly in maven installation directory. so you better check in that location also.
To Answer your 4th point: mvn install:install installs (in simple terms copies) an artifact (jar/ear/zip/any artifact that meant for distribution) into maven local repository or into remote repository. So in your command, you just tried to install only cdi-api jar.
Whenever you run mvn compile, mvn package, mvn install, maven will scan your pom file and downloads all dependency mentioned into your local repository. I would suggest you to look your local repository and see how is it creating directory structure.

When maven says "resolution will not be reattempted until the update interval of MyRepo has elapsed", where is that interval specified?

With maven, I occasionally hit an artifact that comes from some 3rd-party repo that I haven't built or included in my repository yet.
I'll get an error message from the maven client saying that an artifact can't be found:
Failure to find org.jfrog.maven.annomojo:maven-plugin-anno:jar:1.4.0
in http://myrepo:80/artifactory/repo was cached in the local
repository, resolution will not be reattempted until the update
interval of MyRepo has elapsed or updates are forced -> [Help 1]
Now, I understand what this means, and can simply re-run my command with -U, and things usually work fine from there on out.
However, I find this error message to be extremely unintuitive and am trying to spare my co-workers some headaches.
I am trying to figure out if there is some place that I can modify this update interval setting.
Is the update interval that is mentioned in this error message a client-side or server-side setting?
If client-side, how do I configure it?
If server-side, does anyone know how/if Nexus/Artifactory expose these settings?
I used to solve this issue by deleting the corresponding failed to download artifact directory in my local repo. Next time I run the maven command the artifact download is triggered again. Therefore I'd say it's a client side setting.
Nexus side (server repo side), this issue is solved configuring a scheduled task.
Client side, this is done using -U, as you already pointed out.
What basically happens is, according to the default updatePolicy of maven, maven will fetch the jars from the repo on a daily basis. So if during the first attempt your Internet was not working, then it would not try to fetch this jar again until 24hours has passed.
Resolution:
Either use
mvn -U clean install
(where -U will force update the repo)
or use
<profiles>
<profile>
...
<repositories>
<repository>
<id>myRepo</id>
<name>My Repository</name>
<releases>
<enabled>false</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
</repository>
</repositories>
...
</profile>
</profiles>
in your settings.xml
you can delete the corresponding failed artifact directory in you local repository. And also you can simply use the -U in the goal. It will do the work. This works with maven 3. So no need to downgrade to maven 2.
I had a related problem, but Raghuram's answer helped. (I don't have enough reputation yet to vote his answer up). I'm using Maven bundled with NetBeans, and was getting the same "...was cached in the local repository, resolution will not be reattempted until the update interval of nexus has elapsed or updates are forced -> [Help 1]" error.
To fix this I added <updatePolicy>always</updatePolicy> to my settings file (C:\Program Files\NetBeans 7.0\java\maven\conf\settings.xml)
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled><updatePolicy>always</updatePolicy></releases>
<snapshots><enabled>true</enabled><updatePolicy>always</updatePolicy></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled><updatePolicy>always</updatePolicy></releases>
<snapshots><enabled>true</enabled><updatePolicy>always</updatePolicy></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
While you can resolve this with a clean install (overriding any cached dependencies) as #Sanjeev-Gulgani suggests with mvn -U clean install
You can also simply remove the cached dependency that is causing the problem with
mvn dependency:purge-local-repository -DmanualInclude="groupId:artifactId"
See mvn docs for more info.
According to the settings reference:
updatePolicy: This element specifies how often updates should attempt to occur. Maven will compare the local POM’s timestamp (stored
in a repository’s maven-metadata file) to the remote. The choices are:
always, daily (default), interval:X (where X is an integer in minutes)
or never.
Example:
<profiles>
<profile>
...
<repositories>
<repository>
<id>myRepo</id>
<name>My Repository</name>
<releases>
<enabled>false</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
</repository>
</repositories>
...
</profile>
</profiles>
...
</settings>
This works after you delete the related dependency from your local maven repository
/user/.m2/repository/path
This error can sometimes be misleading. 2 things you might want to check:
Is there an actual JAR for the dependency in the repo? Your error message contains a URL of where it is searching, so go there, and then browse to the folder that matches your dependency. Is there a jar? If not, you need to change your dependency. (for example, you could be pointing at a top level parent dependency, when you should be pointing at a sub project)
If the jar exists on the remote repo, then just delete your local copy. It will be in your home directory (unless you configured differently) under .m2/repository (ls -a to show hidden if on Linux).
If you are using Eclipse then go to Windows -> Preferences -> Maven and uncheck the "Do not automatically update dependencies from remote repositories" checkbox.
This works with Maven 3 as well.
You need to delete all "_maven.repositories" files from your repository.
I had a similar error with a different artifact.
<...> was cached in the local repository, resolution will not be reattempted
until the update interval of central has elapsed or updates are forced
None of the above described solutions worked for me. I finally resolved this in IntelliJ IDEA by
File > Invalidate Caches / Restart ... > Invalidate and Restart.
For Intellij users the following worked for me:
Right click on your package
Maven > Reimport
and
Maven > Generate Sources and Update Folders
If you use Nexus as a proxy repo, it has "Not Found Cache TTL" setting with default value 1440 minutes (or 24 hours). Lowering this value may help (Repositories > Configuration > Expiration Settings).
See documentation for more info.
Maven has updatePolicy settings for specifying the frequency to check the updates in the repository or to keep the repository in sync with remote.
The default value for updatePolicy is daily.
Other values can be always / never/ XX (specifying interval in minutes).
Below code sample can be added to maven user settings file to configure updatePolicy.
<pluginRepositories>
<pluginRepository>
<id>Releases</id>
<url>http://<host>:<port>/nexus/content/repositories/releases/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
How I got this problem,
When I changed from Eclipse Juno to Luna, and checkout my maven projects from SVN repo, I got the same issues while building the applications.
What I tried?
I tried clean Local repository and then updating all the versions again using -U option. But my problem continued.
Then I went to Window --> Preferences -> Maven --> User Settings --> and clicked on Reindex button under Local Repository and wait for the reindex to happen.
That's all, the issue is resolved.
To finally answer the title question: It is (a client side setting) in (project, profile or settings)
[plugin]?[r|R]epository/[releases|snapshots]/updatePolicy
... tag.
The (currently, maven: 3.6.0, but I suppose "far backwards" compatible) possible values are :
/**
* Never update locally cached data.
*/
public static final String UPDATE_POLICY_NEVER = "never";
/**
* Always update locally cached data.
*/
public static final String UPDATE_POLICY_ALWAYS = "always";
/**
* Update locally cached data once a day.
*/
public static final String UPDATE_POLICY_DAILY = "daily";
/**
* Update locally cached data **every X minutes** as given by "interval:X".
*/
public static final String UPDATE_POLICY_INTERVAL = "interval";
The current (maven 3.6.0) evaluation of this tag is implemented as follows:
public boolean isUpdatedRequired( RepositorySystemSession session, long lastModified, String policy )
{
boolean checkForUpdates;
if ( policy == null )
{
policy = "";
}
if ( RepositoryPolicy.UPDATE_POLICY_ALWAYS.equals( policy ) )
{
checkForUpdates = true;
}
else if ( RepositoryPolicy.UPDATE_POLICY_DAILY.equals( policy ) )
{
Calendar cal = Calendar.getInstance();
cal.set( Calendar.HOUR_OF_DAY, 0 );
cal.set( Calendar.MINUTE, 0 );
cal.set( Calendar.SECOND, 0 );
cal.set( Calendar.MILLISECOND, 0 );
checkForUpdates = cal.getTimeInMillis() > lastModified;
}
else if ( policy.startsWith( RepositoryPolicy.UPDATE_POLICY_INTERVAL ) )
{
int minutes = getMinutes( policy );
Calendar cal = Calendar.getInstance();
cal.add( Calendar.MINUTE, -minutes );
checkForUpdates = cal.getTimeInMillis() > lastModified;
}
else
{
// assume "never"
checkForUpdates = false;
if ( !RepositoryPolicy.UPDATE_POLICY_NEVER.equals( policy ) )
{
LOGGER.warn( "Unknown repository update policy '{}', assuming '{}'",
policy, RepositoryPolicy.UPDATE_POLICY_NEVER );
}
}
return checkForUpdates;
}
..with:
private int getMinutes( String policy )
{
int minutes;
try
{
String s = policy.substring( RepositoryPolicy.UPDATE_POLICY_INTERVAL.length() + 1 );
minutes = Integer.valueOf( s );
}
catch ( RuntimeException e )
{
minutes = 24 * 60;
LOGGER.warn( "Non-parseable repository update policy '{}', assuming '{}:1440'",
policy, RepositoryPolicy.UPDATE_POLICY_INTERVAL );
}
return minutes;
}
...where lastModified is the (local file) "modified timestamp" of an/each underlying artifact.
In particular for the interval:x setting:
the colon : is not that strict - any "non-empty" character could do it (=, , ...).
negative values x < 0 should yield to "never".
interval:0 I would assume a "minutely" (0-59 secs. or above...) interval.
number format exceptions result in 24 * 60 minutes (~"daily").
..see: DefaultUpdatePolicyAnalyzer, DefaultMetadataResolver#resolveMetadata() and RepositoryPolicy
In my case the solution was stupid: I just had incorrect dependency versions.
Somewhat relevent.. I was getting
"[ERROR] Failed to execute goal on project testproject: Could not resolve dependencies for project myjarname:jar:1.0-0: Failure to find myjarname-core:bundle:1.0-0 in http://repo1.maven.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced -> [Help 1]"
This error was caused by accidentally using Maven 3 instead of Maven 2. Just figured it might save someone some time, because my initial google search led me to this page.
I had the same error, (resolution will not be reattempted...) but I had different requirements, as I have files in my local repository, that are currently not available remotely (old outdated libraries and internal libraries), and my company nexus system is down, but they do exist in my .m2 repos.
Maven still refused to build, producing the same error above.
For the offending libraries, I just removed the corresponding file:
_remote.repositories
exmple path: users\[username]\.m2\[offending jar
path]\[versionnumber]\_remote.respositories
knowing that these files are only available locally.
Note: Long term resolution, I should probably get our previous nexus system up and running, and for those jars that are legacy, check them into the project under a lib folder (or something like that)
I had this problem and the comprehensive descriptions proposed in this helped me to fix it.
The second declared problem was my issue. I used a third-party repository which I had just added it do the repository part of the pom file in my project. I add the same repository information into pluginrepository to resolve this problem.
I ran into the same problems with uploaded third party libraries on my private repository. Sometimes the described fixes worked for me, but sometimes they did not.
I think the root cause of the problem is a missing pom.xml file for the artifact. (The pom.xml for the third party artifact not your pom.xml in your project). I assume Maven expects for every artifact a pom.xml, so it can resolve the dependencies for all artifacts. Sometimes it works without a pom.xml, but sometimes it does not (I have not identified, when it does not).
I use Nexus3 as a private repository. When you upload an artifact, you can check an option to generate a pom.xml file for the artifact.
Changing the localRepository path in my settings.xml solved the issue
I have resolved it!
I have encountered this issue earlier and after reviewing some comments it worked.
we only have to correct settings.xml file under {m2_home}/.m2
**<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>.m2/repository</localRepository>
<profiles>
<profile>
<repositories>
<repository>
<id>projectid</id>
<url>http://localhost</url>
<name>Project name</name>
<releases>
<enabled>false</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
</repository>
</repositories>
</profile>
</profiles>
</settings>**
and execute maven clean install command.
**/maven_home/mvn -f project_directory/pom.xml -DskipTests clean install**
Make sure that the artifact you are looking for is exist , if its on your local project run :
cd ..
cd project name
mvn clean install
Then you will have it locally.
for better practice do :
mvn clean deploy so you can use it again without this problem

Resources