Classifiers not working in Maven Snapshot repo for IVY - maven-2

So I have got my Maven build deploying both Java5 and Java6 versions to my snapshot repo (Nexus). I do this with build profiles and classifiers. All is good in the Maven side of things.
However, if I try to resolve the Java5 dependency from my IVY based project it will not work if the most recent Maven deploy was for the Java6 profile/classifier. I guess this is because the timestamp in maven-metadata.xml picks out the Java6 version. It does work if the most recent deploy was for Java5.
This is the resolver:
<ibiblio name="snapshot-repo-name"
m2compatible="true"
root="snapshot-repo-root"
pattern="[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"
usepoms="true"
checkmodified="true"
changingPattern=".*SNAPSHOT"/>
Deploying Java6 of the dependency therefore breaks the build of IVY-built application.

The work-around is to mark the Maven snapshot as non-unique versions in the <distributionManagement/> element. That is, there are no longer timestamped versions in the Maven snapshot repository.
<distributionManagement>
<repository>
<id>PROJECT-RELEASE</id>
<name>PROJECT-RELEASE</name>
<url>http://foo.bar:8081/nexus/content/repositories/PROJECT-RELEASE</url>
</repository>
<snapshotRepository>
<id>PROJECT-SNAPSHOT</id>
<name>PROJECT-SNAPSHOT</name>
<uniqueVersion>false</uniqueVersion>
<url>http://foo.bar:8081/nexus/content/repositories/PROJECT-SNAPSHOT</url>
</snapshotRepository>
</distributionManagement>

Is it the resolution that is failing or the retrieve? (Retrieve does an implicit resolve).
My build once failed because the following pattern wasn't unique (Needed a classifier in the name pattern to cater for source and javadoc artifacts):
<ivy:retrieve pattern="lib/[artifact].[ext]"/>

Related

Running unit tests in Tycho fails: resolves google-collections instead of Guava

I am having an issue running tests using tycho due to an incorrect dependency resolution that, somehow, is placing the the old Google Collections .jar on the classpath and not the Guava one, despite the fact that at no point in any of my poms do I specify a dependency on collections (only guava).
My unit tests fail due to things like NoSuchMethodError (ImmutableList.copyOf), NoClassDefFoundError (Joiner), which I pretty much narrowed down to 'finding the wrong jar'. These same tests pass when ran manually in Eclipse.
Here is the relevant part of the pom:
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>14.0.1</version>
</dependency>
...
</dependencies>
The phrase 'google collections' appears no where. The only other repository I specify is:
<repositories>
<repository>
<id>helios</id>
<layout>p2</layout>
<url>http://download.eclipse.org/releases/helios</url>
</repository>
</repositories>
My plugin imports 'com.google.common.base' and 'com.google.common.collect' as imported packages. I have my own bundled version of Guava 14 in my workspace for debugging, but in the POM I elect to not use my local module.
I followed Sean Patrick Floyd's answer on this question (JUnit throws java.lang.NoSuchMethodError For com.google.common.collect.Iterables.tryFind), and had my test throw an exception with the location of the .jar that the Iterables class was loaded from. It spat back out:
java.lang.IllegalArgumentException: file:/C:/Documents and Settings/Erika Redmark/.m2/repository/p2/osgi/bundle/com.google.collect/0.8.0.v201102150722/com.google.collect-0.8.0.v201102150722.jar
This is where I am now stuck. This google-collections jar is coming seemingly out of no where, and I don't know how to stop it. As long as it is being resolved, my unit tests will fail. How can I stop Tycho from trying to get the old Google Collections?
Just to clarify, this has not stopped building and deployment; the plugin update site is on an CI platform and we have been able to install the plugin on different Eclipse IDEs, so this issue is only affecting the tests.
Please let me know if additional information is needed.
The plug-in com.google.collect 0.8.0.v201102150722 is part of the Helios p2 repository that you have configured in your POM. This means that this plug-in is part of the target platform and so may be used to resolve dependencies.
If you want to ensure that the bundle is not used, make sure that it is not part of the target platform. In your case, the easiest way to do this is to explicitly remove the plug-in from the target platform:
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>target-platform-configuration</artifactId>
<version>${tycho-version}</version>
<configuration>
<filters>
<filter>
<type>eclipse-plugin</type>
<id>com.google.collect</id>
<removeAll />
</filter>
</filters>
</configuration>
</plugin>
Next, you need to make sure that the guava plug-in is part of the target platform. You can add an artifact from a Maven repository to the target platform in the following way:
Declare a Maven dependency to the artifact in the dependencies section of the POM. You already have done this correctly.
Set the configuration parameter <pomDependencies> to consider on Tycho's target-platform-configuration plug-in.
Note that this will generally only work if the referenced artifact is already an OSGi bundle. This is the case here: com.google.guava:guava:14.0.1 seems to have all manifest headers needed by OSGi.
This should give you the result you wanted: In the test runtime, guava should now be used to match your com.google.common.* package imports.
And another general remark on declaring dependencies in Tycho: In Tycho, you can only declare dependencies in the PDE source files META-INF/MANIFEST.MF, feature.xml, etc.
The normal Maven-style dependencies declared in the POM do not add dependencies to the project. As explained above, the POM dependencies may only add artifacts to the target platform, i.e. the set of artifacts that may be used by Tycho to resolve the dependencies declared in the PDE source files. So in the end, the POM dependency may become part of the resolved dependencies, but only if the dependency resolver picks it for matching one of the declared dependencies.
by default, tycho will add any p2 artifacts you installed in your local maven repo to the target platform. If bundle com.google.collect exports the package which you import, it may be wired.
To stop tycho from including any locally installed artifacts, you can use -Dtycho.localArtifacts=ignore (or, remove the unwanted bundle from your local maven repo)
See http://wiki.eclipse.org/Tycho/Release_Notes/0.16#Improvements_and_Fixes

Question about maven

Why is maven downloading dependencies from repository even if the jar exists on my local repository(one reason could be that jar doesn't have a pom), is there a way to get bypass that except with the -o option?
Why is maven downloading [SNAPSHOT] dependencies from repository even if the jar exists on my local repository
Because that's the expected behavior with SNASPSHOT dependencies. Unlike fixed versions, Maven will periodically try to download the most recent version of a given SNAPSHOT. That's extremely useful when you're depending on a project that is under active development. From the Maven Reference:
3.3.1.2. SNAPSHOT Versions
Maven versions can contain a string
literal to signify that a project is
currently under active development. If
a version contains the string
“SNAPSHOT,” then Maven will expand
this token to a date and time value
converted to UTC (Coordinated
Universal Time) when you install or
release this component. 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.
Why would you use this? 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.4", your project would have a
version "1.4-SNAPSHOT" until it was
formally released.
As a default setting, Maven will not
check for SNAPSHOT releases on remote
repositories. To depend on SNAPSHOT
releases, users must explicitly enable
the ability to download snapshots
using a repository or pluginRepository
element in the POM.
When releasing a project, you should
resolve all dependencies on SNAPSHOT
versions to dependencies on released
versions. If a project depends on a
SNAPSHOT, it is not stable as the
dependencies may change over time.
Artifacts published to non-snapshot
Maven repositories such as
http://repo1.maven.org/maven2 cannot
depend on SNAPSHOT versions, as
Maven's Super POM has snapshot's
disabled from the Central repository.
SNAPSHOT versions are for development
only.
If you really want to change this behavior, you can change the updatePolicy of your snapshot enabled repository:
<repositories>
<repository>
<id>my-repo</id>
<name>My Corporate Repository</name>
<url>http://repo.mycompany.com/maven2</url>
<layout>default</layout>
...
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
</repository>
Switching to never will force you to use a manual update (using mvn -U). But beware, this is usually not what people want and expect with SNAPSHOTs.
For the record, Maven 3 has a -nsu, --no-snapshot-updates command line option allowing to Suppress SNAPSHOT updates.
See also
3.2. The POM
Repositories in the POM reference
You could generate a pom in your local repository by installing the file manually:
mvn install:install-file
-Dfile=[FILE]
-DgroupId=[GROUP]
-DartifactId=[ARTIFACT]
-Dversion=[VERSION]
-Dpackaging=jar
-DgeneratePom=true
-DcreateChecksum=true
EDIT: You wouldn't want to do this for snapshots.

Maven Repository With More Recent Versions?

Is there a Maven repository with more recent versions of the jars that I need? The main repository is often behind a few minor releases... Also, how do I go about adding additional repositories in my pom.xml file?
Is there a Maven repository with more recent versions of the jars that I need? The main repository is often behind a few minor releases...
Since I can't read minds, I don't know :) There is no general answer, be more specific. But in a corporate environment, one would typically run a repository manager like Nexus and deploy anything non available in public repositories (but approved) in it.
Also, how do I go about adding additional repositories in my pom.xml file?
To add a repository for dependencies, you need to specify a repositories element as follows:
<project>
...
<repositories>
<repository>
<id>my-internal-site</id>
<url>http://myserver/repo</url>
</repository>
</repositories>
...
</project>
And if you want to add a repository for plugins, you need to specify a pluginRepositories element (its structure is similar to the above one).
Related questions
Maven, how to add additional libs not available in repo
References
Introduction to Repositories
POM Reference
5.5 Repositories
5.6 Plugin Repositories
Nothing precludes you from creating your own artifacts, in fact maven supports adding 3rd party jars to your local repository:
http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html

Maven release JAR

How can i make a project jar release and maven repository strucuture(md5hash,distribution pom,etc) to put this in my own repository? Maven have a plugin to do it? Note, i need to generate this structure in my local machine, i don't have CI and others to do it!
Hopes!!!
Check the deploy plugin, I think this is what you're looking for. Quoting the documentation:
As a repository contains more than the artifacts (POMs, the metadata, MD5 and SHA1 hash files...), deploying means not only copying the artifacts, but making sure all this information is correctly updated. It's the reponsibility of the deploy plugin.
You'll need to declare a <distributionManagement> element to use it, something like this:
<distributionManagement>
<repository>
<id>internal.repo</id>
<name>MyCo Internal Repository</name>
<url>Host to Company Repository</url>
</repository>
</distributionManagement>
Where the url can be a "local" file://.
And if the question is about installing a (third party) jar in your local repository (the question is not totally clear), have look at the Maven Install Plugin, install:install and install:install-file both admit a createChecksum optional parameters.

How to force maven to download poms for offline use

my problem with maven is that if the maven repository is not responding, one cannot build. It seems to fetch every "mvn package" time some poms, which won't change, because they are of the same version.
How can I say to maven that please don't look them up from server, and instead download them permanetly to offline repository?
Thanks!
You can run maven with the -o flag:
-o,--offline Work offline
This will cause Maven to never look for dependencies in remote repositories. On the other hand, your build will fail if the dependencies are not found in the local repository.
You can configure the repository to only check for updates occasionally, or never by setting the updatePolicy element on the repository declaration. From the settings documentation:
The frequency for downloading updates - can be "always", "daily" (default), "interval:XXX" (in minutes) or "never" (only if it doesn't exist locally).
Adding the following to your POM or the settings will configure the central repository to only download if the artifact doesn't exist locally:
<repositories>
<repository>
<id>central</id>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</repository>
</repositories>
If the repository in question is an internal remote repository, you need to ensure the maven-metadata.xml is configured correctly in the remote repository or Maven will attempt to download it each time. The simplest way to do this is to use a repository manager that will manage the metadata automatically