Project Distribution

Let’s go through various ways to distribute Maven projects.

As Package

To manually distribute the project we can use mvn package command. Based on project type, Maven binds different goals to package phase which packages the code and resources as an archive file such as Jar, War etc., The built-in packaging types and the goal used for each of them is as follows:

  • JAR - it is the default packaging type and Maven binds jar:jar goal to package phase.

  • POM - it is the simplest packaging type and the artifact that it generates contains the pom.xml. Maven binds site:attach-descriptor goal to package phase.

  • EJB - Maven binds ejb:ejb goal to package phase.

  • WAR - packages a web app and binds war:war goal to package phase.

  • Maven Plugin - binds jar:jar and plugin:addPluginArtifactMetadata goals to package phase to package a Maven Plugin project.

All the above packaging plugins uses a share component called Maven Archiver Plugin.

Maven Assembly Plugin is the preferred way to manually distribute the project instead of mvn package. It allows to aggregate the project output along with its dependencies, modules, site documentation, and other files into a single distributable archive. Also, it can create distribution in various formats such as tar, zip, tar.gz etc., We will cover assembly in the next chapter.

Install in Local Repository

When you are a lone developer, you can use Maven local repository to share artifacts with your other projects. For example, suppose you have a utility library which is used by your other projects. Then, you can install the util library in local repository and add it as dependency, just like any other Maven dependency, in other projects .

The default location of the local repository is $HOME/.m2/repository. The command mvn install publishes the project to local repository.

 
 

Deploy to Shared Repository

Remote repository is handy to share artifacts with other developers. Maven Central Repository is an example of public remote repository. However, we can also setup a private shared repository to share artifacts among a small group developers on local network.

Maven phase deploy uses deploy:deploy goal of Maven Deploy Plugin to deploy the projects to remote repository. In this section, we explain the steps to setup a shared repository and access it through SSH.

Imagine a local area network with a server with hostname maven-repo and two clients - sue and ron. Sue wants to deploy her Simple Maven Project to shared repository at maven-repo so that Ron can use it as dependency in his project.

To push the artifacts to the repository, Sue has to add following lines to her pom.xml.

simple-app/pom.xml

  ...
  <!-- project build -->
  <distributionManagement>
      <repository>
         <id>ssh-repository</id>
         <url>scpexe://maven-repo/var/maven/shared-repo</url>
      </repository>
  </distributionManagement>

  <build>
      <extensions>
         <!-- Enabling the use of SSH -->
         <extension>
              <groupId>org.apache.maven.wagon</groupId>
              <artifactId>wagon-ssh-external</artifactId>
              <version>1.0-beta-6</version>
          </extension>
      </extensions>
  </build>
  ...

The distributionManagement defines repository located at /var/maven/shared-repo in server with hostname maven-repo and it uses SSH protocol. To enable the use of SSH, it adds Maven extension library Apache Wagon.

Now, if Sue tries mvn deploy she will get an error that Maven is unable to create directory on the server. SSH requires public/private key pair to authenticate and she has to generate the key pair with following command.

$ ssh-keygen -t rsa

Accept default at all prompts by pressing Enter key to generate RSA public/private key pair. The keys files id_rsa (private key) and id_rsa.pub (public key) are stored in $HOME/.ssh directory. Next, she has to send the public key file id_rsa.pub to the server admin. The admin of maven-repo has to create a user for Maven repository, create a directory for shared-repository and enable permissions with following commands.

$ useradd maven
$ mkdir /var/maven
$ chown maven.maven /var/maven
$ chmod 755 /var/maven

Here, admin is creating a user named maven but any other name would do. Next, admin has to add Sue’s public key as an authorized key with following commands.

$ cd /home/maven
$ mkdir .ssh 
$ cat id_rsa.pub >> .ssh/authorized_keys
$ chmod -R 700 .ssh

This authorizes Sue to ssh to server as user maven without any further authorization (password less ssh). She has to login to maven-repo once using following command to add the maven-repo as known host.

$ ssh maven@maven-repo

As a last step, Sue has to tell about remote user name and location of her private key by adding settings.xml, the Maven Settings file to $HOME/.m2.

$HOME/.m2/settings.xml

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                          http://maven.apache.org/xsd/settings-1.0.0.xsd">

     <servers>
        <server>
           <id>ssh-repository</id>
           <username>maven</username>
           <privateKey>${user.home}/.ssh/id_rsa</privateKey>
        </server>
     </servers>

</settings>

In this file Sue telling that for a remote repository with id ssh-repository, Maven has to use user maven and the private key file /home/sue/.ssh/id_rsa.

Now, Sue can deploy the project with mvn deploy command and it will push the Simple Maven Project artifacts to server maven-repo and stores them in shared repository at /var/maven/shared-repo. SSH uses the Sue’s private key and user name maven to authenticate with maven-repo. On deploy, the shared repository contents is as shown in the screenshot.

Maven Project Distribution - ssh, scp shared repository

To use the artifacts of shared repository as dependencies in the projects, Ron has to add following to his pom.xml.

simple-app/pom.xml

  ...
  <repositories>
    <repository>
      <releases>
        <enabled>true</enabled>
        <updatePolicy>always</updatePolicy>
        <checksumPolicy>warn</checksumPolicy>
      </releases>
      <id>ssh-repository</id>
      <name>Shared Repository</name>
      <url>scpexe://maven-repo/var/maven/shared-repo</url>
      <layout>default</layout>
    </repository>
  </repositories>

  <build>
      <extensions>
         <!-- Enabling the use of SSH -->
         <extension>
              <groupId>org.apache.maven.wagon</groupId>
              <artifactId>wagon-ssh-external</artifactId>
              <version>1.0-beta-6</version>
          </extension>
      </extensions>
  </build>

  <!-- project dependencies -->
  <dependencies>
      <dependency>
        <groupId>com.xyz</groupId>
        <artifactId>simple-app</artifactId>
        <version>1.0</version>
      </dependency>
  </dependencies>
  ...

He, too, has to generate the public/private key and share the public key with maven-repo admin who has to add it to the authorized_keys file as done for Sue. Also, Ron has to add settings.xml file (same contents as Sue) to his $HOME/.m2 directory and login to maven-repo once through ssh to add the server as known host.

When Ron runs Maven build command such as mvn compile, it will trigger the download simple-app artifacts deployed by Sue from the shared repository to Ron’s local repository.

 
 

Try out locally

If you don’t have local area network, you can try out the shared repository on your system by creating three users - maven, sue and ron.

In Sue’s and Ron’s pom.xml, for repository URL, instead of maven-repo, use localhost as hostname (or localhost.localdomain depending on your setup). The URL will be <url>scpexe://localhost/var/maven/shared-repo</url>.

We can also place the shared repository behind a FTP server and to configure FTP repository refer Deployment of artifacts with FTP.

The above method is fine as long as development team is small, but when team is large managing the users access to the repository becomes an issue. For enterprise level repository, it is suggested to use Maven Repository Managers such as Apache Archiva, Artifactory or Sonatype Nexus.

In the next chapter, we look at Maven Assemblies.