Publish Java Artifacts to Maven Central

Zack Teater
5 min readMay 14, 2021

Maven dependency management has become an industry standard for Java development. It has simplified and standardized the way Java libraries are built and managed. Java developers can pull and use any of the 6.7m artifacts from Maven Central. In this guide, we will take a deep-dive in how to create a new artifact on Maven Central. We will step through setting up a domain, registering with GPG, and publishing a release candidate to Nexus.

Register Domain with Sonatype

In order to publish artifacts, you must own the domain associated with your artifacts. A single domain can be used to publish multiple artifacts to Nexus.

Once you have a domain, raise a Jira ticket with Sonatype to register your domain. This is a one-time request which can take several days.

You will be asked to prove ownership of your domain. This can be done by temporarily modifying the TXT record or by changing the CNAME record to point to your GitHub repository.

If you choose CNAME, consider creating a GitHub organization to house the repository instead of your personal account. Then you can host any number of OSS projects in the future with the same organization. For instance, I changed whelk.io to redirect to my GitHub organization: github.com/whelk-io.

GNU Privacy Guard

All artifacts published to Nexus must be signed with GPG. Once you have created a private key, you must publish your public key to one of the global key servers. Afterwards, the public key is automatically distributed to the other key servers within 1–2 days.

Generate a new key pair.

gpg2 --gen-key

List your keys to see your newly created public key

$ gpg2 --list-keys/Users/zteater/.gnupg/pubring.kbx
---------------------------------
pub rsa2048 2020-09-04 [SC]
CBD4A688527344A89DA698A667E4BA1596973688
uid [ultimate] Zack Teater <zteater@gmail.com>
sub rsa2048 2020-09-04 [E]

Publish your public key to the GPG key servers

$ gpg2 — keyserver hkp://pool.sks-keyservers.net — send-keys CBD4A688527344A89DA698A667E4BA1596973688

Once you have published your public key, it may take 2–3 days for it to propagate to all of the other GPG key servers.

Configure Maven Password Encryption

Create a master password to seed encryption for other passwords.

$ mvn --encrypt-master-password

When prompted, provide a password of your choice and you will receive an encrypted value in response

{foaG444L5k8HfeBBQJ9CPwoInd52AZ58HBJQ9Xha/04=}

Note: You can pass a plain-text password as an argument to this command, however this is not recommended since the command will be stored in history.

Open or create ~/.m2/settings-security.xml.

Add the encrypted master password.

Note: If the master password is changed, other encrypted passwords must be re-encrypted.

Configure settings.xml with Nexus Login

Encrypt Nexus password

Maven does allow for plain-text passwords to be stored in settings.xml, but it is recommended to use encrypted passwords.

$ mvn --encrypt-password

When prompted, provide your Nexus password and you will receive an encrypted value in response.

$ {Qet4qKbuSQYHJh3YprA/kgfG40fD/ki+U9TRy/+oltk=}

Note: If your Nexus password changes, you will need to re-encrypt this value.

Configure Nexus login

Open or create ~/.m2/settings.xml.

Add your Nexus username and encrypted password.

Add the Sonatype release and snapshot repository.

Note: The repository.id must match the server.id

The final settings.xml should look like this:

Configure pom.xml with Artifact Details

The pom.xml of your library must be configured with artifact, license, developer, and SCM details. This meta data will be publicly available in Maven Central, however if not configured your artifact could be rejected by Nexus.

Add Artifact Details

groundId— must be start with the TLD and domain name you own. For example, all artifacts published under http://whelk.io would start with with io.whelk. The groupId can have additional subdomains as needed.

artifactId— must be unique for your groupId

version — project version should follow Semantic Versioning to enable auto-versioning later

name — human-readable name for artifact

description — short description of artifact, usually 1–3 sentences

url — GitHub project URL (not to be confused with the SCM URL)

Add License Details

All artifacts should have a license describing acceptable use, distribution, and liability. The license defined in pom.xml should match the LICENSE file at the root of the repository.

Add Developer Details

Artifacts should have at least one developer listed. This is not meant to be an exhaustive list of contributors, but should list the core team of maintainers. If your project is hosted within an organization, then also include the organization and organizationUrl fields.

Add SCM Details

Find the .git URL for your project.

And add it to the SCM details.

Add Java Release Version

By default, your project should already define project.build.sourceEncoding, maven.compiler.source, and maven.compiler.target. However, you will additionally need to identify the maven.compiler.release version.

Configure pom.xml for Release

Add Distribution Management

At a minimum, the release repository must be defined. Optionally, a snapshotRepository can be added for incremental or beta testing.

Add Staging Plugin

When publishing to Nexus, the files (jar, pom, sources, javadoc) are initially staged in temporary folder on the remote server. After your artifact has been scanned, the file are moved to the snapshotRepository or repository depending on the type of release. The nexus-staging-maven-plugin facilitates this initial staging.

The serverId must match the repository id in the distributionManagement.

Add Sources Plugin

Sources file is not required for publishing to Nexus, but highly encouraged. When present, it allows your library consumers to easily step through your Java code during debug. When it is not present, the consumers will still be able to debug your library, but they will be looking at the decompiled version of the code, which is not always human-readable.

Add Javadoc Plugin

Javadoc is not required for publishing to Nexus, but again highly encouraged. It will give your library consumers thoughtful information on how to use your public classes and methods.

Add GPG Plugin

All releases to Nexus must be signed using GNU Privacy Guard (GPG). The actual passphrase and key are configured in the settings.xml.

Publish to Maven Central

Increment to next patch version using build-helper. Unlike the release plugin, this will not post-fix the version with -RELEASE or -SNAPSHOT.

mvn build-helper:parse-version versions:set -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.nextIncrementalVersion} versions:commit

Release to maven central.

mvn deploy

Upon success, the artifact will be loaded into a staging environment. Navigate to https://search.maven.org/ and search for your groupId:artifactId. It may take several hours for the artifact to show up in the search results.

Maven Central extracts meta-data from your pom.xml to populate the artifact details page.

Your artifact is now hosted on Maven Central is accessible by any Java developer from anywhere in the world. You can easily increment versions and publish your artifact to Nexus. In future articles, I’ll discuss how this process can be automated using GitHub Actions.

--

--

Zack Teater

I am a Java architect currently working at CapTech Consulting. I enjoy developing web applications and integrating enterprise systems.