Generated pom.xml does not have all dependencies when using a configuration as a dependency

We want to generate pom.xml’s for a multi-project gradle build, for ease of import into other tools. When using the suggestion in the docs (http://gradle.org/docs/current/userguide/maven_plugin.html#newPom), we don’t get all the dependencies. While the normal case is multi-project, the problem can be demonstrated within a single project:

What we do, is define a number of configurations that are to be shared between all projects. In the build below, the configuration “slf4j” refers to a given slf4j-version, and is “imported” through a dependency on that configuration. For the example, we also do a direct dependency on commons-lang3.

apply plugin: 'java'
apply plugin: 'maven'
  // Normally defined in root project
allprojects {
    configurations { slf4j }
    dependencies { slf4j 'org.slf4j:slf4j-api:1.6.2' }
    repositories { mavenCentral() }
}
  // The sub-project choose the configurations they need
dependencies {
    compile('org.apache.commons:commons-lang3:3.1')
    compile(configurations.slf4j)
}
  task writeNewPom
<< {
    pom{}.writeTo("$projectDir/pom.xml")
}

This turns into the following pom, where the dependency to slf4j (introduced through the configuration) is missing, while the commons-lang3 dependency is present.

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId></groupId>
  <artifactId>gradle2pom</artifactId>
  <version>unspecified</version>
  <dependencies>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.1</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>

The question, then, is as follows: What do we need to do, in order to create a pom which includes all the required dependencies?

The problem is that you do the following:

compile(configurations.slf4j)

One of the valid dependency notations is a collection of files, which a configuration can be converted to. So what you are actually asking for here is to include a dependency on the files of the ‘slf4j’ configuration. This isn’t what you want as when you depend directly on files, Gradle has no information available to use to describe the dependency with the kind of notation required for a POM file.

You could reasonably argue that we should include special handling for ‘Configuration’ object but that’s a different issue.

There are two potential solutions to your problem.

The first is to use configuration inheritance:

configurations {
   compile.extendsFrom slf4j
}

However, given that we are talking about just one dependency I’d be tempted to do this:

deps = [
    slf4j: 'org.slf4j:slf4j-api:1.6.2'
]
  dependencies {
  compile deps.slf4j
}

That’s a pretty common pattern in Gradle builds.

Also works for multiple dependencies: deps = [ slf4j: [‘foo:foo:1.0’, ‘bar:bar:1.0’] ]

Great solution, much better than what we already used… Thanks a lot!

Note that when you do use

compile.extendsFrom slf4j

, you’d run into GRADLE-1042 (see http://gradle.1045684.n5.nabble.com/pom-generation-and-inherited-dependencies-td1436197.html for a workaround).