How do I fix incorrect checksums in my Nexus repository? - maven-2

Some of the artifacts in my local Nexus repository don't have the correct checksum. For example (wrong checksum):
cat central/org/codehaus/plexus/plexus-compiler-api/1.8/plexus-compiler-api-1.8.pom.sha1
95f3332c2bbace129da501424f297e47dd0e976b
vs (correct checksum):
sha1sum central/org/codehaus/plexus/plexus-compiler-api/1.8/plexus-compiler-api-1.8.pom
4c2947f7e2d09b6e13da34292d897c564f1f9828
It looks like I have a few artifacts in my repository that were downloaded when this bug was active.
Maven Central has the correct checksum (4c29...) now, but the checksums in my local Nexus repository remain stale. I don't know how to get my local repository to verify and / or re-download the correct checksum from central.
What is the correct way of fixing my local repository. There aren't too many artifacts with this problem, so I think I could (by hand) verify they still exist in central and delete them from my local repository. They should get re-cached with the correct checksums. Is there a better way?
Update:
I've looked at this more and I'm almost positive I know what the source of my problem is. One of the artifacts I'm having trouble with is this one (plexus-compiler-api:1.8):
In my repository, both the .pom and .pom.sha1 are timestamped as 29-Mar-2010. At central, the .pom is timestamped as 29-Mar-2010 while the .pom.sha1 is timestamped as 21-Apr-2010. I was reading about Nexus maintenance. I assume that, on 21-Apr-2010, Maven Central rebuilt metadata and verified checksums which fixed the incorrect .sha1 for the plexus-compiler-api:1.8 artifact.
According to the Sonatype link above, I should be able to expire the caches for Maven Central and have my local installation pull new copies of anything with newer timestamps than the originally cached artifacts. However, based on the behavior I've observed, I think it's only checking timestamps for artifact files, not checksum files.
As far as my local Nexus repository is concerned, I have the most recent version of the artifact (29-Mar-2010), so there's no need to re-download anything.
I've noticed my version of Nexus is quite old (1.5 vs 1.9.1), so I'll try updating and see if the newer version does a better job of expiring caches. If not, I'll probably see what the Sonatype guys think (maybe it's a bug?).

Nope, what you face is the defined behaviour of Nexus and Maven.
First, expiring caches does not delete anything from local cache of Nexus, it just marks them "old". The effect of marking items as "old" is shown on next incoming request asking for those same artifacts (if never asked for, the "old" artifacts just sits there). Meaning, expire cache alone will not cause Nexus to download remotely changed (newer) files. Nexus never downloads on it's own (if we leave out the index from this discussion). You have to force a client (Maven) ask for them – and that will result following chain of action: "cache content old", remote change detection and finally re-download and caching of the new file.
Next, what happens here is that Maven, since artifact (the JAR file) is not changed, not even asks for checksum file either, hence nothing "triggers" the "old" marked checksum refetch on Nexus side. Other to note, if we talk about released artifact (and Maven Central does contains released artifacts only), Maven will never re-check them, unless they are not present in local repository (once brought into local repository, Maven will never try to refetch them). Meaning, you need to remove them from local repository to be sure that Maven will ask for them from Nexus, and finally, that Nexus will detect the checksum file changes on remote and do what you actually want.
Re-download should happen, for example if you nuke your Maven's local repository and rebuild with a clean/empty one. In this case, Maven should ask for both, JAR artifact and checksum file – but from your description it's not clear how did you (or did you?) invoke Maven after expiring caches on Nexus.
Try this:
a) run expire caches on Nexus "Maven Central" proxy repository
b) nuke local repository (or just redirect it to a new clean folder by tampering ~/.m2/settings.xml
c) make Maven build your project, and it should refetch both, the JAR and checksum files (by using empty/nuked local repository)
Hope this explains some of the stuff you wrote.
Reference to JIRA issue discussing same thing.

This was a bug.
As explained by Tamas, when a proxied repository cache is expired, Nexus will check the remote repository for newer timestamps. The locally cached artifacts are essentially flagged dirty and the check for updated artifacts happens on demand as artifacts are requested from the local Nexus server.
Nexus (1.9.1) is making the assumption that if an artifact timestamp is unchanged, the checksums should be unchanged as well. Most of the time this will be true, but, due to the old bug in Maven that was deploying artifacts with incorrect checksums, there are rare cases where an artifact can be unchanged yet have an updated checksum.
I think the best way to deal with this for now will be to move any bad checksums and let Nexus try to re-resolve them the next time they are requested:
mv plexus-compiler-api.pom.sha1 plexus-compiler-api-1.8.pom.sha1.bak
Thanks for the help Tamas.

Related

Trouble deploying snapshot from Bamboo to Artifactory

I would like to deploy snapshot builds from Bamboo to Artifactory. My repository's Handle Snapshots option is checked and it's Maven Snapshot Version Behavior is set to Unique. The repository's layout is gradle-default.
My goal is for a build plan to deploy an artifact at a location similar to the following:
repo-local:com.company/project/1.0-SNAPSHOT/project-1.0-20120612.101600.txt
In Bamboo I have a Artifactory Generic Deploy Task, configured with the following for the Edit Published Artifacts field:
project-1.0-SNAPSHOT.txt=>com.company/project/1.0-SNAPSHOT
However Artifactory rejects my build artifacts, saying The repository 'repo-local' rejected the artifact 'repo-local:com.company/project/1.0-SNAPSHOT/project-1.0-SNAPSHOT.txt' due to its snapshot/release handling policy.
How do I get Artifactory to accept the artifact and automatically replace SNAPSHOT with a timestamp in the filename?
Your problem is most likely the fact that the path you deploy to is not considered a valid integration revision by the layout you've selected (gradle-default).
The gradle-default layout expects integration revisions like:
org/module/1.0-12345678912345/module-1.0-12345678912345.jar
That is, for a 14 digit long time stamp to be appended after the base revision;
While your path contains SNAPSHOT instead of a 14 digit long timestamp.
If you want to have pattern like:
com.company/project/1.0-SNAPSHOT/project-1.0-20120612.101600.txt
You will have to customize the layout to accept -SNAPSHOT as the folder integration revision and modify your artifact to contain a timestamp as the file integration revision.
I'm guessing your assumption was that Artifactory will convert the non-unique integration revision to a unique one; Artifactory performs this conversion only when the repository is set to the default Maven layout and when the artifacts adhere to Maven's layout.
This is due to the fact the while Maven actually has defined standards for integration revisions, Gradle do not have such a standard; So basically, a Gradle revision could be practically anything.
On top of that, the concept of unique and non-unique integration revisions doesn't really exist in the Gradle world, it doesn't actually have any built-on functionality to support these features; and so when you see a Mavenized path in Gradle, it's just basically mimicking the pattern.

Maven is using incorrect location for downloading plugin pom

(This question is asked on Maven User mailing list too)
I have recently faced a strange problem, that I cannot even able to judge the cause or source of problem. It will be great if someone can give me some direction:
(The story may be a bit long)
I am using Nexus 1.8.0 as our company's repository manager. I use it as proxy of external repo, and hosting our own repository.
There are many repositories in Nexus. I have one repository group (let's call it PUBLIC) which groups all public repositories, including maven central, codehaus etc.
There is another repository group (let's call it EXT) which we put 3rd party artifacts.
In our project, we used org.codehaus.mojo:native2ascii-maven-plugin.
Due to a bug at that time, instead of using the publicly available org.codehaus.mojo:native2ascii-maven-plugin:1.0-alpha-1, I have fixed the bug and deploy it to our EXT repository, and called it org.codehaus.mojo:native2ascii-maven-plugin:1.0-alpha-1.1 (i.e. used a new version number 1.0-alpha-1.1 instead of 1.0-alpha-1)
This have been running fine for several years.
However recently a new developer tries to get the code and build, using Maven 2.2.1. Strange things happened: the build failed. By inspecting result of mvn -X clean install, it states that POM of native2ascii-maven-plugin:1.0-alpha-1.1 cannot be downloaded from PUBLIC, therefore it will use a default emtpy POM, which cause the build problem.
By inspecting the local repository, I found that only the JAR of native2ascii-maven-plugin:1.0-alpha-1.1 was downloaded. I am sure that there is no native2ascii-maven-plugin:1.0-alpha-1.1 in PUBLIC repository, and the SHA of the JAR matches with native2ascii-maven-plugin:1.0-alpha-1.1 in EXT. It seems that, Maven is capable to download the JAR correctly from EXT repo, but when it tries to download the POM afterwards, Maven mistakenly think that it should be downloaded from PUBLIC. Because PUBLIC do not contains 1.0-alpha-1.1, Maven assume there is no POM.
I have EXT repo defined before PUBLIC in my settings.xml. What even more strange is, I tried to block accessing in Nexus for native2ascii-maven-plugin from PUBLIC. Maven, instead of getting the POM from repository EXT, it get from central directly. At last I add PUBLIC as mirror for central, and Maven can build correctly, because EXT is the the only repo that contains native2ascii-maven-plugin. Maven seems tries to download the POM from every repository else which contains native2ascii-maven-plugin in despite of the version number, except from EXT
I simply cannot understand why this will happen. This have been used for years, and it used to be fine even several weeks before (I have other new developers, who can correctly download the plugin, several weeks ago). May anyone guide me the possible cause of the problem? I have neither changed anything in my repo, nor changed version of Maven. Why Maven's "download" behavior suddenly changed?
It's hard to say.
First my theory on why it no longer works. I am guessing this "worked for years" because at one time it worked, and afterwards everything was in your local repository (<home>/.m2/repository). Later, something broke, but you never noticed because you had everything local. The new developer did not have a populated local repository so when they built for the first time, they had failures.
Now my suggestion which may not work out for you. When using Nexus, I think its best to create a single "group" repository that links in all other repositories, and configure the group to order the priority of the linked repositories. So for you, in the group, you would list EXT first, then PUBLIC. Your POMs and/or settings would reference only the group repository. This may just duplicate what you are already doing through other means, but at least it is moving the ordering rules up into Nexus. I would rename your local repository (so you can revert back if necessary) and try re-building to see if everything resolves correctly.
You might want to consider a continuous build tool like Hudson that periodically deletes its own local repository so you can catch issues like this sooner.
At last I managed to find out the "cause" of the problem. It is due to my fault, combined with still-unknown behavior of Maven. I add this as an answer to ease future reference for other people.
They key problem is that I missed plugin version for this specific project (I did put corresponding pluginManagement for other projects, and other plugins for this project... I wonder how come I made this mistake this time)
The way to reproduce the problem:
A separate repository to store the plugin (in my case, org.codehaus.mojo:native2ascii-maven-plugin:1.0-alpha-1.1)
In project POM, add plugin, without version. For example,
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>native2ascii-maven-plugin</artifactId>
<plugin>
</plugins>
in settings.xml, avoid defining mirrors (i.e. the settings.xml contains list of repositories and pluginRepositories only)
With such setup, first purge the local repository. Then build the project. After build, inspect the directory in local repository for that plugin (in my case .m2\repository\org\codehaus\mojo\native2ascii-maven-plugin\1.0-alpha-1.1), you will find only the JAR presents, without corresponding POM. (Caused by Maven successfully get the plugin JAR corresponding to the pluginRepositories in settings.xml, but trying to get the POM from a weird location)
With the same setup, put the version in project POM, clean up the local repo, and build again. Everything is fine now.
The reason for work fine even for a recently clean CI environment, is probably due to other "correct" project made the plugin downloaded correctly, which can be used by this "incorrect" project. A periodic purge in local repository in CI won't necessary help much on this too because for that many projects, the chance is always very high for other "correct" project build earlier than that "incorrect" project.
The reason behind such behavior of Maven is still unknown, but at least in a "correct" POM (with plugin version correctly declared), Maven works fine. I will raise this as a issue for Maven though.
I'd start off by agreeing with SingleShot in that Continuous Integration - even a simple smoke test where you simply compile and run unit tests on the trunk - would have prevented you getting into the situation of assuming that the because the build works on one machine, it does not work on the other.
This have been running fine for several years.
That's the kicker with Maven repositories - all you need to do is download it once succesfully, and you'll be forever good to go. Just because it's been working successfully from your local repository doesn't mean it was working.
It is fine several months ago (coz I have migrated our CI server and I have a clean env to build, and everything is fine).
Interesting. So my theory would be then to go and make sure the new developer is set up correctly - that the settings.xml file is in place and is being read (I've had instances that the settings.xml is THERE, but in the wrong place!). It's a simple one, but Maven does not fail if there's no settings.xml, it just uses a default that may have you seeing ghosts.
You mentioned that you use maven 2.2.1 and I can only ask you to doublecheck, we had some strange behavior concerning downloading jars from internal repo that was caused by OSX Lion update that comes with maven3. Our fix was to redeploy affected project.

Apache Ivy Terms & Ambiguities

I'm learning how to augment my build with Ivy using a "brute force" method of just trying to get a few sample projects up and running. I've poured over the official docs and read several online tutorials, but am choking on a few terms that seem to be used vaguely, ambiguously and/or in conflicting ways somehow. I'm just looking for an experienced Ivy connoisseur to help bring some clarity to these terms for me.
"Resolution" Cache vs. "Repository" Cache vs. "Ivy" Cache
The "Ivy Repository", as opposed to my normal SCM which is a server running SVN
What's the difference between these 3 types of cache? What's the difference between the "Ivy Repository" and my SVN?
Thanks to anyone who can help!
"Resolution" Cache vs. "Repository" Cache vs. "Ivy" Cache
The ivy cache is basically a folder, where ivy stores artifacts and configurations. If not configured differently it can be found in UserHome/.ivy2
The ivy cache consists of the resolution cache and a repository cache.
The repository cache contains the artifacts from a repository, that were downloaded by ivy. It is caching the repository, so that ivy won't need to query the repository every time it tries to resolve/download an artefact. If it finds an suitable artifact in the repository cache it will not query the repository. Thus saving the cost to query the repository. If and how the cache is used is a bit more complicated and depends on the dependencies/configuration.
The resolution cache is a collection of ivy-specific files, that tell ivy how an artifact was resolved (downloaded).
The "Ivy Repository", as opposed to my normal SCM which is a server running SVN
A Repository in the ivy world is a location, which contains artifacts(jar) files. This can be the local filesystem or a web server. It has no versioning system. Each version of an artifact is contained in a seperate folder. You can't commit artifacts, you just add them to the file system. See the terminology
org\artifact\version1\artifact.jar
org\artifact\version2\artifact.jar
A repository is accessed via a resolver, which has to know the layout of the repository.
From the doc on caches:
Cache types
An Ivy cache is composed of two different parts:
the repository cache
The repository cache is where Ivy stores data downloaded from module repositories, along with some meta information concerning these artifacts, like their original location.
This part of the cache can be shared if you use a well suited lock strategy.
the resolution cache
This part of the cache is used to store resolution data, which is used by Ivy to reuse the results of a resolve process.
This part of the cache is overwritten each time a new resolve is performed, and should never be used by multiple processes at the same time.
While there is always only one resolution cache, you can define multiple repository caches, each resolver being able to use a separate cache.

Maven downloads corrupted Jars

I am running into a maven problem that's killing all my hairs.
So at the beginning all my maven project works fine. And then when I switched to a new computer today and trying to compile them all.
The first error I see from Eclipse is IO error reading jar files from the local maven repository. Then I googled and someone suggested this is some corrupted files, simply delete them and let maven rebuild the repository.
That solves the problem for a while. And then it keeps popping up again and again.
I got tired and removed the whole local repository and did everything all over again. Then I found out the cause:
The maven remote repository is BAD.
So here is part of the console messages.
[INFO] Unable to find resource 'org.apache.ws.commons.axiom:axiom-dom:jar:1.2.8'
in repository eclipse-repo (http://repo1.maven.org/eclipse)
Downloading: https://maven-repository.dev.java.net/nonav/repository//org.apache.
ws.commons.axiom/jars/axiom-dom-1.2.8.jar
373b downloaded (axiom-dom-1.2.8.jar)
[WARNING] *** CHECKSUM FAILED - Checksum failed on download: local = '2c6102c2c3
70e0b993e897e981618ed448651147'; remote = '
The file contains an http redirect.
301 Moved Permanently
Moved Permanently
The document has moved here.
Apache Server at maven-repository.dev.java.net Port 443
I am stuck. How can I get the real dependency jars? How can I tell maven to avoid this? This is really annoying.
There is king of bug in maven, simply because maven does not skip taking an artifact if one
of the maven repo sends a 301(MOVED PERMANANTLY) and it simply take that message and write it as the pom file. Simply if the maven repo sends 404 it skip that repo and go for another, but here with 301 it just dump the message as the pom file and later on this failes.
I assuming you're using Maven 2.2.1? If yes try, to downgrade to Maven 2.2.0 or use additional setting. In 2.2.1 was change in wagon implementation.
Maven 2.2.1 aims to correct several critical regressions related to the selection of the HttpClient-based Wagon implementation for HTTP/HTTPS transfers in Maven 2.2.0. The new release reverts this selection, reinstating the Sun-based - or lightweight - Wagon implementation as the default for this sort of traffic.
However, Maven 2.2.1 goes a step further to provide a means of selecting which provider - or implementation - the user wishes to use for a particular transfer protocol.
So, try run maven with additional params.
mvn -Dmaven.wagon.provider.http=httpclient clean install
One answer: avoid dev.java.net. It's often broken in one way or the other. If you need things from there, install them in a local repository manager.
I've seen this error with IntelliJ IDEA 13.1.5 and Ubuntu 14.04.
Maven 2.2.? saves the 301 response body as a jar file in the ~/.m2 cache, which causes problems later on during the build.
The fix for me was to install Maven 3. Instructions for Ubuntu 14.04 are here:
http://www.sysads.co.uk/2014/05/install-apache-maven-3-2-1-ubuntu-14-04/

Maven attempts to use wrong snapshot version

I'm trying to deploy the snapshot version of a 3rd party library to our local repo (for legacy reasons this is and old version which is no longer hosted at any online repo, and for the time being I can't replace it, hence I have to host it locally).
Now, I think I've misunderstood the SNAPSHOT-concept, so I'd be very thankful if somebody could set me straight. The jar I have is named foo-0.5.0-20090612.124.jar, and I try uploading it using maven deploy:deploy file to org.bar.foo under version 0.5.0.
The version dependency in my POM is 0.5.0-SNAPSHOT
Each time I upload the jar file to our local repo the number following the date in the filename is iterated (i.e to 125), but when I run maven install, maven attempts to download a jar with the previous number (i.e. 124).
So, is there any way of getting maven to download the correct snapshot version, or should I have no business uploading 3rd party SNAPSHOT files to our repo?
The use case you have is fine. I believe the best practice recommended by the Maven folks is that once you are uploading a SNAPSHOT version of a jar to a shared repository, you should stop treating it as a SNAPSHOT, and instead as a release.
This makes sense because you want people to depend on that specific version of that artifact. The artifact is not under active development and is not expected to change arbitrarily at any point in time and for that reason it should be considered a release. Just one to which you give your own personal fancy name, and one that someone else considered a SNAPSHOT.
When you ask for the dependency foo-0.5.0-SNAPSHOT, I don't believe Maven looks for foo-0.5.0-. I believe it literally looks for foo-0.5.0-SNAPSHOT in the repository, and that is why you are not finding it. (Not 100% sure about this though, as we don't timestamp our SNAPSHOTS. We simply continually overwrite -SNAPSHOT jars with newer versions as they are made.)
So, put foo-0.5.0-20090612.124.jar into your third party repository (which should only contain releases for the reason above). Then in your pom, reference the "released" artifact foo-0.5.0-20090612.124 explicitly, and everything should work fine.
I'm not sure I follow, you should have an artifact called myartifact.jar attached to a POM with a version of 0.5-SNAPSHOT.
When deploying, your repository should change the -SNAPSHOT into a timestamp and update the repository metadata to reflect that this is the most current SNAPSHOT version, so that it can properly serve a SNAPSHOT request.
Do you use a repository such as Archiva or Nexus or just a FTP/HTTP server?