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.
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.