Publish Java Artifacts to Maven Central
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 theserver.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.
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.