# Maven Plugin

version 6.5-milestone-1

| This chapter describes deploying artifacts to Maven repositories using the original, deprecated publishing mechanism available in Gradle 1.0: in Gradle 1.3 a new mechanism for publishing was introduced. This new mechanism introduces some new concepts and features that make Gradle publishing even more powerful and is now the preferred option for publishing artifacts. You can read about the new publishing plugins in Publishing Ivy and Publishing Maven.

The Maven plugin adds support for deploying artifacts to Maven repositories.

## Usage

To use the Maven plugin, include the following in your build script:

Example 1. Using the Maven plugin
build.gradle

    plugins {
        id 'maven'
    }

build.gradle.kts

    plugins {
        maven
    }

## Tasks

The Maven plugin defines the following tasks:

`install` — Upload

  Depends on: All tasks that build the associated archives.

  Installs the associated artifacts to the local Maven cache, including Maven metadata generation. By default the install task is associated with the `archives` configuration. This configuration has by default only the default jar as an element. To learn more about installing to the local repository, see Installing to the local repository

## Dependency management

The Maven plugin does not define any dependency configurations.

## Convention properties

The Maven plugin defines the following convention properties:

`mavenPomDir` — `File`

  The directory where the generated POMs are written to. Default value: `${project.buildDir}/poms`

`conf2ScopeMappings` — `Conf2ScopeMappingContainer`

  Instructions for mapping Gradle configurations to Maven scopes. See Dependency mapping.

These properties are provided by a MavenPluginConvention convention object.

## Convention methods

The maven plugin provides a factory method for creating a POM. This is useful if you need a POM without the context of uploading to a Maven repo.

Example 2. Creating a standalone pom.
build.gradle

    task writeNewPom {
        doLast {
            pom {
                project {
                    inceptionYear '2008'
                    licenses {
                        license {
                            name 'The Apache Software License, Version 2.0'
                            url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                            distribution 'repo'
                        }
                    }
                }
            }.writeTo("$buildDir/newpom.xml")
        }
    }

build.gradle.kts

    task("writeNewPom") {
        doLast {
            maven.pom {
                withGroovyBuilder {
                    "project" {
                        setProperty("inceptionYear", "2008")
                        "licenses" {
                            "license" {
                                setProperty("name", "The Apache Software License, Version 2.0")
                                setProperty("url", "http://www.apache.org/licenses/LICENSE-2.0.txt")
                                setProperty("distribution", "repo")
                            }
                        }
                    }
                }
            }.writeTo("$buildDir/newpom.xml")
        }
    }

Amongst other things, Gradle supports the same builder syntax as polyglot Maven. To learn more about the Gradle Maven POM object, see MavenPom. See also: MavenPluginConvention

## Interacting with Maven repositories

### 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 you using the dependency information it has.

### Deploying to a Maven repository

Let’s assume your project produces just the default jar file. Now you want to deploy this jar file to a remote Maven repository.

Example 3. Upload of file to remote Maven repository
build.gradle

    plugins {
        id 'maven'
    }

    uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: "file://localhost/tmp/myRepo/")
            }
        }
    }

build.gradle.kts

    plugins {
        maven
    }

    tasks.named<Upload>("uploadArchives") {
        repositories.withGroovyBuilder {
            "mavenDeployer" {
                "repository"("url" to "file://localhost/tmp/myRepo/")
            }
        }
    }

That is all. Calling the `uploadArchives` task will generate the POM and deploys the artifact and the POM to the specified repository.

There is more work to do if you need support for protocols other than `file`. In this case the native Maven code we delegate to needs additional libraries. Which libraries are needed depends on what protocol you plan to use. The available protocols and the corresponding libraries are listed in Protocol JARs for Maven deployment (those libraries have transitive dependencies which have transitive dependencies).[1] For example, to use the ssh protocol you can do:

Example 4. Upload of file via SSH
build.gradle

    configurations {
        deployerJars
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        deployerJars "org.apache.maven.wagon:wagon-ssh:2.2"
    }

    uploadArchives {
        repositories.mavenDeployer {
            configuration = configurations.deployerJars
            repository(url: "scp://repos.mycompany.com/releases") {
                authentication(userName: "me", password: "myPassword")
            }
        }
    }

build.gradle.kts

    val deployerJars by configurations.creating

    repositories {
        mavenCentral()
    }

    dependencies {
        deployerJars("org.apache.maven.wagon:wagon-ssh:2.2")
    }

    tasks.named<Upload>("uploadArchives") {
        repositories.withGroovyBuilder {
            "mavenDeployer" {
                setProperty("configuration", deployerJars)
                "repository"("url" to "scp://repos.mycompany.com/releases") {
                    "authentication"("userName" to "me", "password" to "myPassword")
                }
            }
        }
    }

There are many configuration options for the Maven deployer. The configuration is done via a Groovy builder. All the elements of this tree are Java beans. To configure the simple attributes you pass a map to the bean elements. To add bean elements to its parent, you use a closure. In the example above repository and authentication are such bean elements. Configuration elements of Maven deployer lists the available bean 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.

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

Table 1. Protocol jars for Maven deployment
Protocol | Library
--- | ---
http | org.apache.maven.wagon:wagon-http:2.2
ssh | org.apache.maven.wagon:wagon-ssh:2.2
ssh-external | org.apache.maven.wagon:wagon-ssh-external:2.2
ftp | org.apache.maven.wagon:wagon-ftp:2.2
webdav | org.apache.maven.wagon:wagon-webdav:1.0-beta-2
file | -

Table 2. Configuration elements of the MavenDeployer
Element | Javadoc
--- | ---
root | MavenDeployer
repository | org.apache.maven.artifact.ant.RemoteRepository
authentication | org.apache.maven.artifact.ant.Authentication
releases | org.apache.maven.artifact.ant.RepositoryPolicy
snapshots | org.apache.maven.artifact.ant.RepositoryPolicy
proxy | org.apache.maven.artifact.ant.Proxy
snapshotRepository | org.apache.maven.artifact.ant.RemoteRepository

### Installing to the local repository

The Maven plugin adds an `install` task to your project. This task depends on all the archives task of the `archives` configuration. It installs those archives 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.

### Maven POM generation

When deploying an artifact to a Maven repository, Gradle automatically generates a POM for it. The `groupId`, `artifactId`, `version` and `packaging` elements used for the POM default to the values shown in the table below. The `dependency` elements are created from the project’s dependency declarations.

Table 3. Default Values for Maven POM generation
Maven Element | Default Value
--- | ---
groupId | project.group
artifactId | uploadTask.repositories.mavenDeployer.pom.artifactId (if set) or archiveTask.archiveBaseName.
version | project.version
packaging | archiveTask.archiveExtension

Here, `uploadTask` and `archiveTask` refer to the tasks used for uploading and generating the archive, respectively (for example `uploadArchives` and `jar`). `archiveTask.archiveBaseName` defaults to `project.archivesBaseName` which in turn defaults to `project.name`.

| When you set the “`archiveTask.archiveBaseName`” property to a value other than the default, you’ll also have to set `uploadTask.repositories.mavenDeployer.pom.artifactId` to the same value. Otherwise, the project at hand may be referenced with the wrong artifact ID from generated POMs for other projects in the same build.

Generated POMs can be found in `<buildDir>/poms`. They can be further customized via the MavenPom API. For example, you might want the artifact deployed to the Maven repository to have a different version or name than the artifact generated by Gradle. To customize these you can do:

Example 5. Customization of pom
build.gradle

    uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: "file://localhost/tmp/myRepo/")
                pom.version = '1.0Maven'
                pom.artifactId = 'myMavenName'
            }
        }
    }

build.gradle.kts

    tasks.named<Upload>("uploadArchives") {
        repositories.withGroovyBuilder {
            "mavenDeployer" {
                "repository"("url" to "file://localhost/tmp/myRepo/")
                "pom" {
                    setProperty("version", "1.0Maven")
                    setProperty("artifactId", "myMavenName")
                }
            }
        }
    }

To add additional content to the POM, the `pom.project` builder can be used. With this builder, any element listed in the Maven POM reference can be added.

Example 6. Builder style customization of pom
build.gradle

    uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: "file://localhost/tmp/myRepo/")
                pom.project {
                    licenses {
                        license {
                            name 'The Apache Software License, Version 2.0'
                            url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                            distribution 'repo'
                        }
                    }
                }
            }
        }
    }

build.gradle.kts

    tasks.named<Upload>("uploadArchives") {
        repositories.withGroovyBuilder {
            "mavenDeployer" {
                "repository"("url" to "file://localhost/tmp/myRepo/")
                "pom" {
                    "project" {
                        "licenses" {
                            "license" {
                                setProperty("name", "The Apache Software License, Version 2.0")
                                setProperty("url", "http://www.apache.org/licenses/LICENSE-2.0.txt")
                                setProperty("distribution", "repo")
                            }
                        }
                    }
                }
            }
        }
    }

Note: `groupId`, `artifactId`, `version`, and `packaging` should always be set directly on the `pom` object.

Example 7. Modifying auto-generated content
build.gradle

    def installer = install.repositories.mavenInstaller
    def deployer = uploadArchives.repositories.mavenDeployer

    [installer, deployer]*.pom*.whenConfigured {pom ->
        pom.dependencies.find {dep -> dep.groupId == 'group3' && dep.artifactId == 'runtime' }.optional = true
    }

build.gradle.kts

    val uploadArchives by tasks.getting(Upload::class)
    val installer = tasks.install.get().repositories.withGroovyBuilder { getProperty("mavenInstaller") as MavenResolver }
    val deployer = uploadArchives.repositories.withGroovyBuilder { getProperty("mavenDeployer") as MavenResolver }

    listOf(installer, deployer).forEach {
        it.pom.whenConfigured {
            dependencies.firstOrNull { dep ->
                dep!!.withGroovyBuilder {
                    getProperty("groupId") == "group3" && getProperty("artifactId") == "runtime"
                }
            }?.withGroovyBuilder {
                setProperty("optional", true)
            }
        }
    }

If you have more than one artifact to publish, things work a little bit differently. See Multiple artifacts per project.

To customize the settings for the Maven installer (see Installing to the local repository), you can do:

Example 8. Customization of Maven installer
build.gradle

    install {
        repositories.mavenInstaller {
            pom.version = '1.0Maven'
            pom.artifactId = 'myName'
        }
    }

build.gradle.kts

    tasks.install {
        repositories.withGroovyBuilder {
            "mavenInstaller" {
                "pom" {
                    setProperty("version", "1.0Maven")
                    setProperty("artifactId", "myName")
                }
            }
        }
    }

#### Multiple artifacts per project

Maven can only deal with one artifact per project. This is 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. In such a case you need to generate multiple POMs. In such a case you have to explicitly declare each artifact you want to publish to a Maven repository. The MavenDeployer and the MavenInstaller both provide an API for this:

Example 9. Generation of multiple poms
build.gradle

    uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: "file://localhost/tmp/myRepo/")
                addFilter('api') {artifact, file ->
                    artifact.name == 'api'
                }
                addFilter('service') {artifact, file ->
                    artifact.name == 'service'
                }
                pom('api').version = 'mySpecialMavenVersion'
            }
        }
    }

build.gradle.kts

    tasks.named<Upload>("uploadArchives") {
        repositories.withGroovyBuilder {
            "mavenDeployer" {
                "repository"("url" to "file://localhost/tmp/myRepo/")
                "addFilter"("api") {
                    getProperty("artifact").withGroovyBuilder { setProperty("name", "api") }
                }
                "addFilter"("service") {
                    getProperty("artifact").withGroovyBuilder { setProperty("name", "service") }
                }
                "pom"("api")?.withGroovyBuilder { setProperty("version", "mySpecialMavenVersion") }
            }
        }
    }

You need to declare a filter for each artifact you want to publish. This filter defines a boolean expression for which Gradle artifact it accepts. Each filter has a POM associated with it which you can configure. To learn more about this have a look at PomFilterContainer and its associated classes.

#### Dependency mapping

The Maven plugin configures the default mapping between the Gradle configurations added by the Java and War plugin and the Maven scopes. Most of the time you don’t need to touch this and you can safely skip this section. The mapping works like the following. You can map a configuration to one and only one scope. Different configurations can be mapped to one or different scopes. You can also assign a priority to a particular configuration-to-scope mapping. Have a look at Conf2ScopeMappingContainer to learn more. To access the mapping configuration you can say:

Example 10. Accessing a mapping configuration
build.gradle

    task mappings {
        doLast {
            println conf2ScopeMappings.mappings
        }
    }

build.gradle.kts

    tasks.register("mappings") {
        doLast {
            println(maven.conf2ScopeMappings.mappings)
        }
    }

Gradle exclude rules are converted to Maven excludes if possible. Such a conversion is possible if in the Gradle exclude rule the group as well as the module name is specified (as Maven needs both in contrast to Ivy). Per-configuration excludes are also included in the Maven POM, if they are convertible.

1. It is planned for a future release to provide out-of-the-box support for this