Publishing to Maven Central Repository

One of the core contributions of the Maven ecosystem is the Central Repository which is the de facto place for publishing JVM-based libraries. It lets you declare in a project file those library versions you depend on, and then all the tools will automatically find them for you. It’s easy to check for new versions of your dependencies and maybe your IDE even provides code completion for dependency IDs and versions.

The benefits of the Central Repository over other Maven repositories are that it has some minimum requirements to ensure good quality artifacts, and the confidence that it won’t disappear in the future, unlike many other repositories which have disappeared in the past. Thankfully some of the biggest long-buried repositories have been migrated into the Central Repository, for example Java.net and Scala-tools.org, keeping the artifacts available and also improving their meta data.

Now if you have an open source library that you would like to publish to the Central Repository, how should you proceed? The OSSRH Guide will tell you everything about using Sonatype’s OSS Repository Hosting, but some have found its documentation hard to read, so I’m writing this article in hopes of explaining it more simply. This article gives an overview of what is needed - for more details follow the links to the official OSSRH documentation.

One-Time Setup

At first you will need to register at Sonatype’s JIRA and create a ticket for claiming your groupId. If you own the domain example.com, just register the top-level groupId com.example and you can use any sub-groupIds for your projects without needing a ticket for each of them (e.g. com.example.foo and com.example.bar).

You will need to wait for a human to respond to your ticket, because Sonatype wants to make sure that nobody will claim your domain or project address without your permission.

After your first release is ready, you will need to go write a comment to the same JIRA ticket, so that Sonatype will do some final manual checks before enabling the automatic syncing of your groupId to the Central Repository.

Per-Project/User Setup

Central Requirements

There are some minimum requirements for artifacts which are published to the Central Repository:

  • The pom.xml needs to contain some project and license information. It may not contain <repositories> or <pluginRepositories> elements.
  • In addition to the binary artifact you must also publish the source code and Javadocs as separate artifacts.
  • All the artifacts must be signed with GPG/PGP, which requires generating and distributing a key.

An easy way to configure the necessary Maven plugins for producing those artifacts is to extend the org.sonatype.oss:oss-parent POM which contains the profile sonatype-oss-release for activation on release. Or for added flexibility, enable the Source, Javadoc and GPG plugins yourself.

Deployment Configuration

Deploying to OSSRH can be done with all the major build tools. To deploy with Maven you can use the Nexus Staging Maven Plugin. The deployment works so that (1) the build artifacts are uploaded to OSSRH’s Nexus into a temporary staging repository, (2) the staging repository is closed for modifications, and finally (3) the staging repository is either dropped or released into the Central Repository. At step 2 the artifacts are available under a temporary URL to allow integration testing them.

You will need to store your Sonatype username and password (the ones for logging into the Sonatype JIRA) in Maven’s user-specific ~/.m2/settings.xml file, under the <servers> element.

<servers>
  <server>
    <id>ossrh-releases-com.example</id>
    <username>example</username>
    <password>secret</password>
  </server>
</servers>

In the project’s pom.xml you will need to configure the plugin to use OSSRH’s Nexus instance with your credentials.

<build>
  <plugins>
    <plugin>
      <groupId>org.sonatype.plugins</groupId>
      <artifactId>nexus-staging-maven-plugin</artifactId>
      <version>1.6.4</version>
      <extensions>true</extensions>
      <configuration>
        <nexusUrl>https://oss.sonatype.org/</nexusUrl>
        <serverId>ossrh-releases-com.example</serverId>
        <stagingProfileId>46cd48d84135</stagingProfileId>
      </configuration>
    </plugin>
  </plugins>
</build>

The <stagingProfileId> in the above code sample is specific to your groupId and you can find it out by logging into https://oss.sonatype.org where you will need to (1) click Staging Profiles, (2) select your groupId from the list, and (3) copy the hexadecimal ID from the browser’s address bar.

How to find your stagingProfileId

The plugin will hook into Maven’s deploy command and stage the artifacts automatically. Additionally it provides goals for releasing or dropping the staging repositories, so that you can fully automate the release. To find out the Nexus plugin’s available goals and parameters, use the mvn nexus-staging:help and mvn nexus-staging:help -Ddetail=true -Dgoal=<goal-name> commands.

Per-Release Actions

When everything is configured as shown above, releasing a new version happens like this:

  1. Set the release version number
  2. mvn clean deploy -P sonatype-oss-release
  3. Login to https://oss.sonatype.org
  4. Select your just created staging repository under Staging Repositories
  5. Click the Release button to release it

The artifacts will be immediately available under https://oss.sonatype.org/content/groups/public/ and in a couple of hours it will be synced into the Central Repository (assuming you have done the one-time setup of commenting on the JIRA ticket on your first release).

Automating the Release

I recommend you to write a shell script for doing all the above mentioned release steps. The shell script should just take the version number as parameter and do everything else automatically. Have a look at this release script for a complete example.

Releasing the staging repository can be automated with the Nexus Staging Maven Plugin. With more complex projects it may be useful to stage the artifacts into a local directory, which is then uploaded as a whole to Nexus:

# save the artifacts under the "staging" directory
mvn clean deploy \
    --errors \
    -P sonatype-oss-release \
    -DaltDeploymentRepository="staging::default::file:staging"

# upload everything from the "staging" directory into a Nexus staging repository
mvn nexus-staging:deploy-staged-repository \
    --errors \
    -DrepositoryDirectory=staging \
    -DstagingDescription="any description of the release"

# release the Nexus staging repository (reads repository ID from 'staging/*.properties' under altStagingDirectory, as generated by deploy-staged-repository)
mvn nexus-staging:release \
    --errors \
    -DaltStagingDirectory=. \
    -DstagingDescription="any description of the release"

Summary

Releasing open source libraries to the Central Repository is not hard. It just requires reading relatively much documentation, but thanks to that everybody can benefit from good quality artifacts. Once all the steps of a release are automated, you can easily push out multiple releases per day without hassle.