Unexpected dependency resolution with mixed maven and ivy repositories

We want to publish the modules of new projects in a Maven repository instead of the Ivy repository we used before. The old artifacts will still be in the Ivy repository. Many of the Ivy projects publish different artifacts using classifiers.

We have module A in the Ivy repository and module B also in the Ivy repository. Module B has many artifacts with different classifiers. In module A is a dependency on module B defined (using Ant/Ivy):

If a dependency on module A is defined in another project X (now using Gradle): compile (“com.example:a:1.0.0”) {

artifact { name=“a”; type=“jar” } } we only get the main artifact (the one without classifier) of module B as expencted.

Now we create a new version of modul A using gradle instead of Ant/Ivy and publish the artifacts into the Maven repository (instead of the Ivy repository). In module A is still a dependency on module B (B is still in the Ivy repo): compile (“com.example:b:2.0.0”) {

artifact { name=“b”; type=“jar” } } If I look in Eclipse on the Gradle Dependencies of A only the artifact of B without classifier is resolved. This is as I expected.

But in module X all artifacts of module B are resolved. I still would expect that only B without classifier is resolved. I even tried ‘artifact { name=“b”; classifier=""; type=“jar” }’ but that makes no difference.

This is really a bummer for us, because now module X includes to many jars in the classpath and results in difficult to track down errors. We want this behavior to make a slow transition from Ant/Ivy to Gradle without changing all of out >200 modules at once.

Is my expectation wrong? How can I define the dependencies to get the result we need?

Couple of things. First, adding the ‘artifact {name = ‘b’; type = ‘jar’ }’ is at the very least, redundant. You may want to try removing that, however I don’t think it will affect resolution behavior. Second, are the artifact descriptors being generated properly? Are the dependencies listed in the POM generated by the new Gradle-based build correct?

Thanks for your answer. I should have made a few details clearer, which lead to the problem: 1) In Ivy, if a dependency specify just the dependency and no artifacts (like: ), then all artifacts of that dependency are resolved.

  1. If a dependency specifies artifacts:

< dependency org=“com.example” name=“a” rev=“1.0.0” >

< artifact name=“a” ext=“jar” / >

< /dependency >, then only the given artifacts of that dependency are resolved. In This case just the artifact without classifier.

This behaviour seams to work correctly in Gradle, when all my referenced project are in an Ivy repository. It fails, if one project is in an maven repository and refereces projects in an Ivy repository. This is described in the first entry.

With the (possibly) redunant ‘artifact’ statement I copied how Ivy works. The artifact descriptors looks correct. The ivy.xml from the Ivy repository is still the same and the pom from the module A in the maven repository looks like this:

< dependency>

< groupId >com.example< /groupId >

< artifactId >b< /artifactId >

< version >2.0.0< /version >

< scope >runtime< /scope >

< /dependency >

Hmm, this is probably the reason for my problem: Both cases look the same in the pom. And the default behaviour for Ivy repositories without classifier resolves all artifacts. I just tried with an empty ‘classifier’ and got the same behaviour.

Is there a way to describe in a pom, that only the artifact without classifier should be resolved from the Ivy Repository? Any other suggestions how to circumvent the problem? It is not realistic, to move all existing projects to a maven respository.

Thanks.

I think the simple answer to your question about being able to describe what artifacts you want in a pom.xml is, no, since Maven doesn’t support Ivy repositories. In effect, by publishing to a Maven repository you are doing a lossy conversion to the pom.xml, since Maven doesn’t support all the metadata constructs of Ivy.

In the mean time you may have to implement a hack where you iterate over the resolved configuration and remove the extra files. Take a look at ‘Configuration.getIncoming.afterResolve()’.

Thank you very much for your response. They made the dependency handling clearer for me. Next week I will try the possibilities with ‘afterResolve’. Thanks for the hint.

Wouldn’t it be reasonable, if Gradle would resolve a dependency from a pom file with the Maven resolving strategy, even if the module is resolved from an Ivy repository? In this case the result would be, that only the artifact without classifier would be retrieved from the Ivy repo. If it is resonable, can you give me a hint, where those functionality could be added in the gradle sources?

I think the behavior you are seeing is due to your Ivy artifacts all being published under the default configuration. That would explain why you are having to explicitly define the artifacts you want. As mentioned before, because Maven does not support the concept of declaring what particular artifacts it wants, the behavior is to get all artifacts associated with the default configuration.

Again, by publishing to a POM you are effectively losing that information. Gradle cannot assume that you only want a particular artifact when resolving the dependency declared in the POM, doing so would be a breaking change.

Changing the way your Ivy modules are published is probably not an option for you. Another option would be to define the “maven->ivy” dependencies as client module dependencies and explicitly define the transitive artifact dependencies.