Introduction
You can push your own Java packages to Maven Repository - Central and make it available to everyone. It's a tricky process to set up the first time, but once you get it ready, it is incredibly easy to push updates. This tutorial will walk you through the basics of registering and pushing projects to Maven central using Sonatype's OSSRH (OSS Repository Hosting)
Helpful Links
Usually these go at the end but these are such valuable links, all your answers are probably found within these links:
- The Central Repository Search Engine
- Maven Repository - Central
- Official Maven instructions for publishing
- Official Sonatype instructions for publishing with OSSRH
- Sonatype JIRA
- Sonatype Nexus Repository Manager
- Sonatype package requirements
- My DevDungeon namespace request in Sonatype JIRA
Prerequisites
Before pushing to the central repository you need to have proper access and a GPG key on a public server.
Sign up with Sonatype JIRA
Before publishing to the central repository, you must have a reserved namespace.
The namespace is typically a domain name, but could also be a GitHub or BitBucket
namespace like com.github.nanodano
. To request your namespace, you need
an account on the Sonatype JIRA first.
Sign up for Sonatype JIRA and follow the instructions to request your namespace.
Here is a link to my DevDungeon namespace request in Sonatype JIRA if it helps as a reference.
Create a GPG key
You will need a private GPG key to sign the code to verify you are the author and it has not been tampered with. Create a private key and save it somewhere secure and publish your public key to a trusted server.
If you don't know how to use GPG, check out my GPG Basics tutorial for a walkthrough of how to install gpg, generate keys, import and export, and push your private key to MIT's (and other) public key servers.
Here's a couple of the most important commands:
gpg --gen-key # Create a new private key
gpg --list-keys # To get the key id
gpg --export-secret-keys --armor <key_id> > private_gpg_key_backup.asc
gpg --keyserver hkp://pgp.mit.edu --send-keys <key_id>
Set up settings.xml
You can configure your GPG key and Sonatype password in the settings.xml
file.
The file should go inside your project directory next to your pom.xml
or in $HOME/.m2/settings.xml
. The server and profile provided here will be
utilized in the pom.xml
later.
Here is a sample settings.xml
:
<settings>
<servers>
<server>
<!-- Match the server id used in <distributionManagement> and <serverId>
for sonatype staging plugin in `pom.xml` -->
<id>ossrh</id>
<username>nanodano</username>
<password>secretpass</password>
</server>
</servers>
<profiles>
<profile>
<id>sonatype-oss-release</id>
<properties>
<gpg.keyname>NanoDano</gpg.keyname>
<!-- GPG should prompt for passphrase if not provided here. -->
<!-- <gpg.passphrase>secretpassphrase</gpg.passphrase> -->
<!-- <gpg.executable>/path/to/gpg.exe</gpg.executable> -->
</properties>
</profile>
</profiles>
</settings>
Create a package that meets the requirements
Once you have been granted access in the Sonatype JIRA from the previous step, you need to create a package that meets the Sonatype package requirements before you can push it up to the central repository.
Some of the requirements include:
- Required fields in the
pom.xml
- Javadoc and Sources (
<package>-javadoc.jar
,<package>-sources.jar
) - GPG signature (
*.asc
for each file) - License info (e.g. MIT, Apache)
- Developer information
- Source code URLs
Building and deploying a package
You can run each of these steps individually or just run the last one which will call all previous ones in the build step.
mvn clean # Delete build contents
mvn compile # Compile classes
mvn package # Build JAR
mvn verify # Will sign/check GPG
mvn install # Install to local maven repo
mvn deploy # Push to Sonatype->maven central
Sample project pom.xml
This is an example pom.xml
for a Maven project that is intended
to be published on Maven central. It has all of the plugins and
required fields in the template. It also has the Sonatype repository
addresses configured.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.devdungeon.tools</groupId>
<artifactId>http</artifactId>
<version>1.0.1</version>
<name>${project.groupId}:${project.artifactId}</name>
<description>An HTTP utility library</description>
<url>https://www.devdungeon.com/projects</url>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<developers>
<developer>
<name>NanoDano</name>
<email>nanodano@devdungeon.com</email>
<organization>DevDungeon</organization>
<organizationUrl>https://www.devdungeon.com</organizationUrl>
</developer>
</developers>
<dependencies>
<!--
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.4</version>
</dependency>
-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<!-- GPG keyname var set in the settings.xml maven file -->
<keyname>${gpg.keyname}</keyname>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.8</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId><!-- Server config in settings.xml -->
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
</plugins>
</build>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id><!-- Server config in settings.xml -->
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id><!-- Server config in settings.xml -->
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<scm>
<connection>scm:git:git://github.com/DevDungeon/tools-http.git</connection>
<developerConnection>scm:git:ssh://github.com:DevDungeon/tools-http.git</developerConnection>
<url>https://github.com/DevDungeon/tools-http/tree/master</url>
</scm>
</project>
Conclusion
You should know have an understanding of how to publish a package to the Maven central repository using Sonatype's OSSRH.