# Chapter 26. Artifact Management

## 26.1. Introduction

This chapter is about how you declare what are the artifacts of your project and how to work with them (e.g. upload them). We define the artifacts of the projects as the files the project want to provide to the outside world. This can be a library or a distribution or any other file. Usually artifacts are archives, but not necessarily. In the Maven world a project can provide only one artifact. With Gradle a project can provide as many artifacts as needed.

## 26.2. Artifacts and configurations

Like dependencies, artifacts are grouped by configurations. In fact, a configuration can contain both, artifacts and dependencies, at the same time. To assign an artifact to a configuration, you can write:

Example 26.1. Assignment of an artifact to a configuration

`build.gradle`

    task myJar(type: Jar)

    artifacts {
        archives myJar
    }

What do you gain by assigning an artifact to a configuration? For each configuration (also for the custom ones added by you) Gradle provides the tasks `upload[ConfigurationName]` and `build[ConfigurationName]`. [25] Executing those tasks will build or upload the artifacts belonging to the respective configuration.

Table Table 16.3, “Java plugin - dependency configurations” shows the configurations added by the Java plugin. Two of the configurations are relevant for the usage with artifacts. The `archives` configuration is the standard configuration to assign your artifacts to. The Java plugin automatically assigns the default jar to this configuration. We will talk more about the `default` configuration in Section 26.4, “More about project libraries”. As with dependencies, you can declare as many custom configurations as you like and assign artifacts to them.

It is important to note that the custom archives you are creating as part of your build are not automatically assigned to any configuration. You have to explicitly do this assignment.

## 26.3. Uploading artifacts

We have said that there is a specific upload task for each configuration. But before you can do an upload, you have to configure the upload task and define where to upload. The repositories you have defined as described in Section 25.5, “Repositories” are not automatically used for uploading. In fact some of those repositories are not even capable of uploading, there are just capable of reading from a repository. Here is an example how you can configure the upload task of a configuration:

Example 26.2. Configuration of the upload task

`build.gradle`

    repositories {
        flatDir(name: 'fileRepo', dirs: "$projectDir/repo")
    }

    uploadArchives {
        uploadDescriptor = false
        repositories {
            add project.repositories.fileRepo
            add(new org.apache.ivy.plugins.resolver.SshResolver()) {
                name = 'sshRepo'
                user = 'username'
                userPassword = 'pw'
                host = "http://repo.mycompany.com"
            }
        }
    }

As you can see, you can either use a reference to an exisiting repository or create a new repository. As described in Section 25.5.6, “More about Ivy resolvers”, you can use all the Ivy resolvers suitable for the purpose of uploading.

## 26.4. More about project libraries

If your project is supposed to be used as a library, you need to define what are the artifacts of this library and what are the dependencies of this artifacts. The Java plugin adds a `default` configuration for this purpose. This configuration extends both the `archives` and the `runtime` configuration, with the implicit assumption that the `runtime` dependencies are the dependencies of the `archives` configuration. Of course this is fully customizable. You can add your own custom configuration or let the the existing configurations extends from other configurations. You might have different group of artifacts which have a different set of dependencies. This mechanism is very powerful and flexible.

If someone wants to use your project as a library, she simply needs to declare on which configuration of the dependency to depend on. A Gradle dependency offers the `configuration` property to declare this. If this is not specified, the `default` configuration is used (see Section 25.3.8, “Dependency configurations”). Using your project as a library can either happen from within a multi-project build or by retrieving your project from a repository. In the latter case, an ivy.xml descriptor in the repository is supposed to contain all the neccesary information. If you work with Maven repositories you don't have the flexibility as described above. For how to publish to a Maven repository, see the section Section 26.5, “Interacting with Maven repositories”.

## 26.5. Interacting with Maven repositories

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

### 26.5.2. 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 26.3. Upload of file to remote Maven repository

`build.gradle`

    usePlugin 'maven'

    uploadArchives {
        repositories.mavenDeployer {
            repository(url: "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 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. Which libraries depend on the protocol you need. The available protocols and the corresponding libraries are listed in Table 26.1, “Protocol jars for Maven deployment” (those libraries have again transitive dependencies which have transitive dependencies). [26] For example to use the ssh protocol you can do:

Example 26.4. Upload of file via SSH

`build.gradle`

    configurations {
        deployerJars
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        deployerJars "org.apache.maven.wagon:wagon-ssh:1.0-beta-2"
    }

    uploadArchives {
        repositories.mavenDeployer {
            name = 'sshDeployer' // optional
            configuration = configurations.deployerJars
            repository(url: "scp://repos.mycompany.com/releases") {
                authentication(userName: "me", password: "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 another bean elements to its parent, you use a closure. In the example above repository and authentication are such bean elements. Table 26.2, “Configuration elements of the MavenDeployer” 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 26.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 | -

Table 26.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

### 26.5.3. Installing to the local repository

The Maven plugin add 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.

### 26.5.4. Maven Pom generation

The Maven Poms are automatically generated by Gradle. You can find the generated poms in the directory `<buildDir>/poms`. 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.

#### 26.5.4.1. Changing non-dependency elements of the pom

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 26.5. Customization of pom

`build.gradle`

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

To learn about all the customizable attributes of a pom have a look here: `MavenPom` . If you have more than one artifact to publish, things work differently. See Section 26.5.4.2, “Multiple artifacts per project”.

To customize the settings for the maven Installer (see Section 26.5.3, “Installing to the local repository”), you can do:

Example 26.6. Customization of Maven installer

`build.gradle`

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

#### 26.5.4.2. 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 26.7. 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'
        }
    }

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 `GroovyPomFilterContainer` and its associated classes.

#### 26.5.4.3. 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. One can assign also 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 26.8. Accessing a mapping configuration

`build.gradle`

    task mappings << {
        println 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). Right now excludes-per-configuration are not converted to the Maven Pom.

#### 26.5.4.4. Planned future features

We plan support for excludes-per-configuration. 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.

[25] To be exact, the Base plugin provides those tasks. The BasePlugin is automatically applied, if you use the Java plugin.

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