Maven unique snapshots and dependency convergence - maven

I have a project in which the maven-enforcer rule fails with a multi-module build using non-unique snapshots (which are annoyingly the only kind of snapshot supported in Maven 3).
For example, assume -> is a "depends on" relationship, and:
Module-A -> Module-B -> Module-C
Module-A -> Module-C
and that Module B and Module C are present in the snapshot repository as unique builds. All declared Module versions in the POM are currently 1.0-SNAPSHOT.
Now, building Module A fails:
mvn -pl Module-A install
results in:
[INFO] --- maven-enforcer-plugin:1.0.1:enforce (enforce) # Module-A ---
[ERROR]
Dependency convergence error for com.vivosys.project:Module-C:1.0-SNAPSHOT paths to dependency are:
+-com.vivosys.project:Module-A:1.0-SNAPSHOT
+-com.vivosys.project:Module-B:1.0-20111228.032527-8
+-com.vivosys.project:Module-C:1.0-SNAPSHOT
and
+-com.vivosys.project:Module-A:1.0-SNAPSHOT
+-com.vivosys.project:Module-C:1.0-20111228.032527-6
The transitive dependency is resolved as a non-unique snapshot build, but the direct dependency is resolved as a unique snapshot build.
I am using maven 3.0.3, maven-enforcer 1.0.1. The repository is Artifactory 2.4.2 using the unique snapshots option (as recommended by Artifactory since Maven 3 no longer supports non-unique snapshots).
Solutions?
Update: Looks like artifactory allows overriding the maven client behavior and storing the non-unique snapshot in the repository. However, for some reason Artifactory does not recommend this (see the "Maven 3" blurb at http://wiki.jfrog.org/confluence/display/RTF/Local+Repositories) so other solutions are still welcome.

This bug has been fixed (MENFORCER-118) and released in version 1.1.

You have hit this enforcer plugin bug (raised as enhancement).
Perhaps, strictly as a workaround you can explicitly declare the transitive dependency C as a dependency of A?

The only solution available until MENFORCER-118 is resolved appears to be to configure the repository server to use non-unique snaphots. In Artifactory, this can be done via: Admin, Repositories, select the snapshot repository and choose Edit. Then select Nonunique under Maven Snapshot Version Behavior.

Related

Setting up maven to compile (instead of downloading) dependencies

I cloned the git repository of Apache ActiveMQ Artemis project (https://github.com/apache/activemq-artemis) and then typed
mvn -Ptests test -pl :integration-tests
I was surprised to see log messages like the following
...
Downloading: http://repository.apache.org/snapshots/org/apache/activemq/artemis-selector/1.4.0-SNAPSHOT/artemis-selector-1.4.0-20160625.030221-11.jar
Downloading: http://repository.apache.org/snapshots/org/apache/activemq/artemis-core-client/1.4.0-SNAPSHOT/artemis-core-client-1.4.0-20160625.030211-11.jar
...
Since e.g. artemis-core-client is contained in the git repository I cloned in the beginning, I'd have expected maven just builds it from there.
That way, when I make changes in the core client source, they get picked up by the integration tests.
Instead, maven is downloading the jar from the repository.
Question: How do I configure maven to always build all modules that are in the git repository and download only "true" dependencies, which I mean things not in the git repository?
You are not executing the Maven build on the main project, on the main pom.xml which indeed defines the artemis-selector and artemis-core-client modules, among others.
You are executing the Maven build on the tests and its pom.xml, where only tests modules are defined. This is a side/test project, which has as parent the previous pom file, but it doesn't play any role in its parent modules definition. Hence, dependencies are not resolved as modules but as Maven dependencies.
You should firstly install (via mvn clean install) the former project, so that libraries will be available in your local Maven cache (hence no downloading would be triggered), then execute the tests project.
Check the Maven docs for a inheritance vs aggregation difference to further clarify it.
From the Stack Overflow, the follow threads could also be interesting:
What is the difference between using maven -pl option and running maven from module level?
Maven multi module project cannot find sibling module

Building a p2 repository by resolving Tycho features from a Maven repository

I'm trying to build a p2 repository from Tycho feature artifacts which are deployed in a remote Maven repository, without having to install the artifacts into the local Maven repository first (as in Tycho fails to resolve reference from product to eclipse-feature from a different reactor build), and without having to build all features and the repository together in a single reactor build.
Background
I have a multi-module Tycho project that builds several Eclipse plugins and features.
So that I can build each module separately - and so that I can reference OSGI artifacts in our Nexus Maven repository - I have enabled <pomDependencies>consider</pomDependencies> in my target platform, and added Maven dependencies between the modules or to the repository artifacts as usual with <dependency/> elements.
This works well - I can build the features or run the plugin tests without their dependant plugins being either in my local Maven repository or in the same reactor build. For example, when I run mvn test on a plugin test project, the relevant dependencies will be downloaded from Nexus and Tycho will happily resolve the Import-Packages in my manifest against these, build everything and run the tests. So far so good.
I would like to generate a p2 repository from these features so that I can install them in Eclipse from an update site, and the advertised way to do this is with the eclipse-repository packaging type. But here the plan falls down - Tycho doesn't seem to be able to resolve feature dependencies when building repositories in the same way as it can resolve plugin dependencies when building features. All attempts yield:
[ERROR] Cannot resolve project dependencies:
[ERROR] Software being installed: my.eclipse.repository raw:0.0.1.'SNAPSHOT'/format(n[.n=0;[.n=0;[-S]]]):0.0.1-SNAPSHOT
[ERROR] Missing requirement: my.eclipse.repository raw:0.0.1.'SNAPSHOT'/format(n[.n=0;[.n=0;[-S]]]):0.0.1-SNAPSHOT requires 'my.prj.eclipse.project.feature.feature.group 0.0.0' but it could not be found
There are two ways I have successfully built the p2 repository:
As part of the same reactor build. If I make the eclipse-repository a module within the Tycho multi-module project, and build the whole project at once with e.g. mvn verify, the features are resolved fine. But I don't want to do this. I would prefer to build modules individually. This means our CI can have an indicator for each module, and we can immediately see what module tests have failed in; it gives us opportunities for parallelising builds; and we avoid having to be constantly running builds on modules that haven't changed. It would be a shame to have to use a monolithic Maven build.
If I install the Tycho project into my local Maven repository, by running mvn install on the dependency. But I don't want to do this either, because this would mean the build is inherently irreproducable, as it would be sensitive to the state of the local repository. Our CI is currently set up to maintain a Maven repository per job and to completely wipe it at the start of execution, to shield us from this potential messiness.
So my question is: is there a third way? Is there any way I can get the Tycho plugin responsible for building eclipse-repository packaging types to download features from a remote Maven repository? Or any other way I can build the p2 repository from plugins that have been individually built and deployed to the Maven repository?
Things I've tried include:
specifiying the Maven feature depedencies as both jar and eclipse-feature
explicitly adding the features to the target platform, like
...
<artifactId>target-platform-configuration</artifactId>
<version>${tycho.version}</version>
<configuration>
<dependency-resolution>
<extraRequirements>
<requirement>
<type>eclipse-feature</type>
<id>my.prj.eclipse.project.feature</id>
<versionRange>0.0.0</versionRange>
</requirement>
...
The closest thing I've found to a decent solution is have a multi-module Tycho project that just contains the repository and features.
feature-project
|- feature1 (eclipse-feature)
|- feature2 (eclipse-feature)
|- repository (eclipse-repository)
Building this works - all plugins added to the top-level POM are downloaded from Nexus, available for inclusion in each feature and included in the generated repository.
However this is far from ideal because I can no longer store my features logically alongside my plugins; they need to be in separate project hierarchies. Attempting to build the features and repository separately, like with mvn clean verify -pl :feature1,feature2,repository, fails presumably due to Bug 380152.
Is there a better way? Any help would be gratefully received.
Many thanks
(As an aside: building the repository with mvn clean verify -Dtycho.localArtifacts=ignore will succeed if the features are present in the local Maven repository, and won't show you the warning that artifacts are being resolved from the local repo... is this a bug?)
I am pretty impressed by your thorough analysis. You've almost got everything covered which is possible with the current Tycho version (0.22.0) - except for the solution which is so unintuitive that I wouldn't have expected anyone to be able to guess it (see below). Note however that there is a small fix required to also make the solution work for SNAPSHOT artifacts.
But first, I'd like to provide some technical (and historical) background for what you have observed:
pomDependencies=consider only works for plug-ins: The use case for this functionality was to allow referencing plug-ins (or more precisely OSGi bundles) from Maven repositories. So when the flag is set and the project has dependencies to JARs, Tycho will check if they are OSGi bundles, generate the p2 metadata for them on-the-fly, and add them to the target platform. There is no similar support for feature JARs because these usually don't exist in Maven repositories.
But what about Tycho-built projects? These may deploy into Maven repositories! Yes, this is true, and this is why I tried to extend the pomDependencies concept to allow for what you are trying to do. The idea was that every time Tycho considers a POM dependency for the target platform, it also checks if the p2 index files ...-p2metadata.xml and ...-p2artifacts.xml exist. However this turned out to infer a massive performance penalty because it generally takes very long for a Maven repository server to figure out that an artifact does not exist. So the remote download was disabled, and replaced with a look-up in the local Maven repository. In this way, two Tycho builds could set -Dtycho.localArtifacts=ignore and would still be able to exchange the artifacts specified in the POM via the local Maven repository.
Knowing these implementation details, we get to the following solution: Instead of only adding a POM dependency from the repository to the feature artifact, you also need to add dependencies to the p2metadata and p2artifacts files. Example:
<dependencies>
<dependency>
<groupId>myproject</groupId>
<artifactId>myproject.feature</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>myproject</groupId>
<artifactId>myproject.feature</artifactId>
<version>0.1.0-SNAPSHOT</version>
<classifier>p2metadata</classifier>
<type>xml</type>
</dependency>
<dependency>
<groupId>myproject</groupId>
<artifactId>myproject.feature</artifactId>
<version>0.1.0-SNAPSHOT</version>
<classifier>p2artifacts</classifier>
<type>xml</type>
</dependency>
</dependencies>
This makes Maven also download these p2 index files, so Tycho recognizes the main artifact as Tycho artifact. In this way, you can also get an eclipse-feature into the target platform via POM dependencies - at least almost: With 0.22.0, the repository build passes, but the feature.jar artifact is missing. I already debugged this issue, and it is easy to fix.
Obviously the syntax with three <dependency> elements for every actual dependency is not nice. It should be possible to boil this down to a single p2artifacts element - but this is more work. In case you are interested in this feature, you could open an enhancement request in Tycho's issue tracker.

Maven uses different timestamps when building snapshot artifacts in a large project

We have a large maven 3 project with around 250 modules. All modules have version 1.0-SNAPSHOT and modules tree has single parent module with the same version as a tree root.
Project is built with Bamboo nightly and artifacts are installed to a Nexus repository using command "mvn clean install".
It happens that part of modules are built with one timestamp while the rest with the other, something like:
module1-1.0-20121127.150154-7.jar
module100-1.0-20121127.150527-7.jar
In another project I was trying to set dependency to artifacts of this project using specific version of a snapshot dependency (as discussed in this question Maven specific version of a snapshot dependency) but failed to build due to the problem described above.
Does anyone know why maven would use different timestamps and how to fix that?
MNG-6754 was finally fixed in 3.8.2.

Maven build : How to resolve the workspace artifacts without installing them to repo and without using m2eclipse

I've worked a little with m2eclipse in Eclipse Indigo and now I'm trying to use Maven from command line without Eclipse and without m2eclipse plugin. The m2eclipse has abililty to resolve the artifacts from the workspace without installing them to repository and this feature allows me to run my build without problems in Eclipse , but in CMD I'm getting the errors of missing jars.
[WARNING] The POM for AAA_7.1.1:ConfigurationView:jar:0.0.1-SNAPSHOT is missing, no dependency information available
[WARNING] The POM for AAA_7.1.1:Beans:jar:0.0.1-SNAPSHOT is missing, no dependency information available
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[ERROR] Failed to execute goal on project Client: Could not resolve dependencies for project AAA_7.1.1:Client:pom:0.0.1-SNAPSHOT:.......
Our goal is to keep the repo clean as much as possible , that's the reason why I'd like to keep it working in a such way.
So my question is how to resolve the dependencies without installing them to repo and if it's possible at all?
IMO, the standard way to go with Maven is mvn clean install.
But if I understand well your problem, you want to keep your local repository as clean as possible ?
One way to do that would be to use multiple local repositories, but I don't think it's possible at the moment (Maven 3.0).
However you can use alternate local repo with -Dmaven.repo.local or alternate settings with mvn --settings (see answer).
See also :
Previous question : maven workspace local repository
JIRA : Allow multiple local repositories (Unresolved)
Local repository separation -> workspaces don't seem to be implemented at the moment...
Basically you want a maven build, where the reactor contains all your 97 modules. To do this:
Create a parent, which contains all those 97 modules as children (if you are already multi module, you just need to configure the already existing parents to be the children of this new parent). Than start your build at that new parent. The convention is normally to have the parent in the upper directory. But you may also use relative paths that contain .. for the module location specification. There is also no need to inherit from the new parent in the existing parents. So you do not need to change any of the existing poms.

Tycho resolves the wrong version of my own manifest-first artifacts

Consider the following scenario: My application has some dependencies on my own POM-first artifacts (built with pure Maven) and some dependencies on my own manifest-first artifacts (built with Tycho). For the POM-first artifacts, Tycho resolves the exact the version I specified in the POM. For the manifest-first artifacts, Tycho resolves the locally built units which may have a higher version.
In my concrete case, I specified a dependency in the pom.xml to the manifest-first artifact in version 1.2.0, but I get warning "The following locally built units have been used to resolve project dependencies" with version 1.3.0.2012xxx.
I have already found following bugs and discussions, but I don't understand why there is a difference in Tycho resolving POM-first and manifest-first dependencies.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=355367
http://dev.eclipse.org/mhonarc/lists/tycho-user/msg01673.html
Dependency-resolution is a two-step process in Tycho:
First, Tycho computes the so-called target platform, which is
the set of artifacts that are considered for dependency resolution.
In this step, Tycho evaluates the POM dependencies according to the
Maven rules and adds the result to the target platform. Also, all
Tycho artifacts you have built locally with mvn install are added
to the target platform.
Then, Tycho resolves your project's dependencies (from the
MANIFEST.MF, feature.xml, etc.) according to the OSGi rules. Unlike
in Maven dependencies, OSGi dependencies are typically specified as
version ranges. So if you write
Require-Bundle: my.bundle;bundle-version="1.2.0"
you are saying that you want version 1.2.0 or later. You typically don't want to specify an exact version here, because this would have implications on the runtime. But you do want to control what happens at build time, which is why there are various ways to control the content of the target platform.
In your particular case, you have your POM-first artifacts in the target platform in the version specified in the POM. Then, you also seem to be specifying a POM dependency to your Tycho artifacts (which is uncommon, but okay), so you will have the Tycho artifacts in the specified version in the target platform. But since you have also built a newer version of the Tycho artifacts locally with mvn install, these will also be in the target platform. The dependency resolution (step 2) hence has a choice between two versions, an will typically pick the later version.
To prevent the locally built artifacts from being added to the target platform, you can delete the file ~/.m2/repository/.meta/p2-local-metadata.properties. (I'm assuming you already know this, but just to be sure. Bug 355367 will also bring a alternative, more convenient option in 0.16.0.)
And now I finally get to your question why the behaviour is different for POM-first artifacts compared to Tycho artifacts:
Assume multiple Tycho artifacts are built together in the same reactor. Then each artifact can use the other artifacts as dependencies without needing any specific target platform configuration, e.g. you don't need POM dependencies to the artifacts in the same reactor. (Or in other words: upstream artifacts from the same reactor are automatically part of a module's target platform.) So in order to support re-builds of parts of a Tycho reactor (after a mvn install of the full reactor), locally installed Tycho artifacts need to be added to every module's target platform. Tycho can't know if they were originally part of the same reactor, so it just adds them all.
For POM-first artifacts, the reference to the artifact is always there (through the Maven configuration inheritance), even if only a part of a Tycho reactor is built. Therefore there doesn't need to be any mechanism for picking up any version of the locally built POM-first artifacts, but Tycho can add the exactly specified version to the target platform.
For those interested to force tycho to ignore local artifacts when resolving the target platform, add the CLI tycho.localArtifacts=ignore as in e.g.
mvn clean install -Dtycho.localArtifacts=ignore
More details can be found on the Tycho-Target Eclipse Wiki

Resources