Chapter 21. Interacting with Maven Repositories

21.1. Introduction

With Gradle you can deploy to remote Maven repositories or install to your local Maven repository. This includes all Maven metadata manipulation and works also for Maven snapshots. In fact, Gradle's deployment is 100 percent Maven compatible as we use the native Maven Ant tasks under the hood.

Deploying to a Maven repository is only half the fun if you don't have a pom. Fortunately Gradle can generate this pom for your, from the dependency information it has.

21.2. Deploying to a Maven Repository

Let's assume your projects libs bundle produces just one jar file. Now you want to deploy this jar file to a remote Maven repository.

uploadLibs {
    uploadResolvers.addMavenDeployer('maven-deployer') {
        repository(url: "file://localhost/tmp/myRepo/")
    }
}

That is all. Calling the uploadLibs task will generate the pom and deploys the artifact and the pom to the specified repository.

There is some more work to do if you need support for other protocols than file. In this case the native Maven code we delegate to needs additional libraries. Those libraries depend on the protocol you need. The available protocols and the corresponding libraries are listed in Table 21.1, “Protocol jars for Maven deployment”. Those libraries have again transitive dependencies which have transitive dependencies. You need to provide the complete list of those to the MavenDeployer{ [29] }. The easiest way to do this is the following:

dependencies {
    addConfiguration('deployerJars')
    addMavenRepo()
    deployerJars "org.apache.maven.wagon:wagon-ssh:1.0-beta-2"
}
uploadLibs {
    uploadResolvers.addMavenDeployer('maven-deployer') {
        repository(url: "scp://repos.mycompany.com/releases")
        addProtocolProviderJars(dependencies.resolve('deployerJars'))
    }
}

Table 21.1. Protocol jars for Maven deployment

Protocol Library
http org.apache.maven.wagon:wagon-http:1.0-beta-2
ssh org.apache.maven.wagon:wagon-ssh:1.0-beta-2
ssh-external org.apache.maven.wagon:wagon-ssh-external:1.0-beta-2
scp org.apache.maven.wagon:wagon-scp:1.0-beta-2
ftp org.apache.maven.wagon:wagon-ftp:1.0-beta-2
webdav org.apache.maven.wagon:wagon-webdav:1.0-beta-2
file -

21.2.1. Configuration of the Maven Deployer

There are many configuration options for the Maven deployer. The configuration is done with a nested tree. Here is a configuration with all existing elements of this tree. Table 21.2, “Configuration elements of the MavenDeployer” lists the available elements and a link to the javadoc of the corresponding class. In the javadoc you can see the possible attributes you can set for a particular element.

uploadLibs {
    uploadResolvers.addMavenDeployer('maven-deployer') {
        uniqueVersion = true
        repository(url: "ssh://localhost/tmp/myRepo/") {
            authentication(userName: "me", password: "myPassword")
            releases()
            snapshots()
            proxy()
        }
        snapshotRepository(url: "ssh://localhost/tmp/mySnapshotRepo/") {
            authentication(userName: "me", password: "myPassword")
            releases()
            snapshots()
            proxy()
        }
    }
}

In Maven you can define repositories and optionally snapshot repositories. If not snapshot repository is defined releases and snapshots are both deployer to the repository element. Otherwise snapshots are deployed to the snapshotRepository element.

21.2.2. Installing to the local repository

The easiest way to install to the local Maven repository is by using the maven plugin:

usePlugin('maven')

This plugin adds an install task. This install task depends on the libs task of the Java plugin. It installs your libraries to your local Maven repository. If the default location for the local repository is redefined in a Maven settings.xml, this is considered by this task.

21.3. Maven Pom Generation

The Maven Poms are automatically generated by Gradle. You can find the generated poms in the <buildDir>/lib-poms and <buildDir>/dist-poms directory. In many scenarios it just works and you don't have to do anything. But there are situations were you want or have to customize the pom generation.

21.3.1. Changing non-dependency elements of the pom

You might want that the artifact deployed to the maven repository has a different version or name than the artifact generated by Gradle. In such a case you can apply custom settings.

uploadLibs {
    uploadResolvers.addMavenDeployer('maven-deployer') {
        repository(url: "file://localhost/tmp/myRepo/")
        pom.version = '1.0Maven'
        pom.artifactId = 'myName'
    }
}

To learn about all the customizable attributes of a pom have a look here: MavenPom .

To do this for the Maven Installer added by the Maven plugin (see Section 21.2.2, “Installing to the local repository”), you can do:

install {
    configure(uploadResolvers.get('maven-installer')) {
        pom.version = '1.0Maven'
        pom.artifactId = 'myName'
    }
}

21.3.2. Multiple Artifacts per project

Maven can only deal with one artifact per project. This is also reflected in the structure of the Maven pom. We think there are many situations where it makes sense to have more than one artifact per project. Obviously just for the fact that those artifacts have different names but belong to the same group, they need different poms. Another use case is that you might not want to publish all project artifacts to the Maven Repository but only a subset. If your project libs or dists have more than one artifact you have to assign each artifact you want to publish. The MavenDeployer and the MavenInstaller both provide an API for this:

uploadLibs {
    uploadResolvers.addMavenDeployer('maven-deployer') {
        repository(url: "file://localhost/tmp/myRepo/")
        addFilter('api') { artifact, file ->
            artifact.name == 'api'
        }
        addFilter('service') { artifact, file ->
            artifact.name == 'service'
        }
        pom('api').version = 'mySpecialMavenVersion'
    }
}

To learn more about this have a look at GroovyPomFilterContainer and its associated classes.

21.3.3. Dependency Mapping

The Java plugin configures the a default mapping between Gradle configuration and Maven scopes. Most of the time you don't need to touch this and you can safely skip this section. A Gradle-Maven dependency mapping is not trivial, as in Gradle dependencies can belong to more than one configuration. Our mapping works like the following. You can map a configuration to one and only one scope. Different configurations can be mapped to more than one scope. One can assign also a priority to a particular configuration-to-scope mapping. The default mapping is accessible via the dependency manager like dependencies.defaultMavenScopeMapping. Have a look at Conf2ScopeMappingContainer to learn how you can use the returned instance. Let's look at different mapping scenarios:

  • A dependency belongs to only one configuration: The first thing Gradle checks is whether there is a mapping for this configuration. If there is none, the dependency is by default not added to the pom. By setting the mapping property includeUnmappedConfigurations to true, such a dependency will be added. If the configuration is mapped, the corresponding scope is obvious and the dependency is added.

  • A dependency belongs to more than one mapped configuration: If the mapped configurations map to the same scope the situation is clear. If the mapped configurations map to different scopes the configuration mapping with the highest priority is chosen. If there is more than one configuration with a highest priority and they map to different scopes an exception is thrown.

Gradle exclude rules are converted to Maven excludes if possible. Such a conversion is possible if in the Gradle exclude rule the organisation as well as the module name is specified (as Maven needs both in contrast to Ivy). Right now Global Excludes are not converted to the Maven Pom.

21.3.4. Planned future features

We plan support for conversion of global excludes. We also plan support for the new Ivy override element, which corresponds to the dependencyManagement element of a Maven pom. Last but not least we want to make the customization more powerful, by enabling to add custom dependency elements to the pom and remove/modify auto-generated ones.



[29] It is planned for a future release to provide out-of-the-box support for this