The previous labs covered how to add project visibility on quality and progress. Now let's add visibility on deliverables by publishing a project's artifacts. Let's consider the QOTD project. It has several artifacts: a JAR in qotd/core, a WAR in qotd/web, and a zip in qotd/packager. Imagine you want to deploy them to a Maven remote repository.
Several Maven plug-ins—including the JAR, WAR, EAR, and RAR
plug-ins—deploy the artifact they generate. Thus, to deploy a JAR you
use jar:deploy
, to deploy a WAR you
use war:deploy
, to deploy an EAR
you use ear:deploy
, etc.
Under the hood all these deploy goals use the Artifact plug-in's
artifact:deploy
Jelly tag to
perform the actual deployment. Thus, to properly deploy
an artifact you need to find out how to configure the Artifact
plug-in.
Let's practice by deploying the qotd/core JAR. The first thing to decide is what deployment protocol you're going to use. The Artifact plug-in supports several deployment protocols: SCP, file copy, FTP, and SFTP (see http://maven.apache.org/reference/plugins/artifact/protocols.html for more details).
You are going to use the SCP method to deploy the JAR artifact, as it is one of the most commonly used protocols, and it's secure. You also need to tell the Artifact plug-in where to deploy to. Let's imagine you'd like to publish to http://www.mavenbook.org, for example.
As these properties are true for any subproject in QOTD, add the following Artifact plug-in properties to common/project.properties:
maven.repo.list = mavenbook maven.repo.mavenbook = scp://www.mavenbook.org maven.repo.mavenbook.directory = /var/www/html/mavenbook/maven
Unfortunately, you won't be able to publish to http://mavenbook.org. If you want to try this, you'll need your own SSH server. Sorry!
Deployment properties are defined for the mavenbook
deployment repository using the
following syntax: maven.repo.[repository
name].*
, where [repository
name]
is mavenbook
. maven.repo.list
is a comma-separated list
containing all the repositories to deploy to, and in this case you are
publishing to only one remote repository—mavenbook
. The maven.repo.mavenbook
property defines both
the protocol to use (SCP here) and the deployment host. maven.repo.mavenbook.directory
specifies the
deployment directory on the host server.
You also need to specify deployment credentials. It's best to define those in a build.properties file, as this file is not meant to be checked in your SCM and you want your password to remain secret. If your deployment server uses username/password authentication, you'll define:
maven.repo.mavenbook.username = vmassol maven.repo.mavenbook.password = somepassword
Note
Simply define the following properties:
maven.repo.mavenbook = ftp://www.mavenbook.org maven.repo.mavenbook.directory = /var/www/html/mavenbook/maven maven.repo.mavenbook.username = vmassol maven.repo.mavenbook.password = somepassword
to publish using FTP.
If your SSH server supports private key authentication, you can
use the maven.repo.mavenbook.privatekey
and maven.repo.mavenbook.passphrase
properties
instead of a password. A more secure approach is to configure an
authentication key for SSH in a user account on the machine you want
to deploy from.
Note
The Artifact plug-in uses the JSch framework (http://www.jcraft.com/jsch/) under the hood for supporting the SSH protocol. You'll get the following kind of stack trace error:
com.jcraft.jsch.JSchException: Auth fail at com.jcraft.jsch.Session.connect(Unknown Source) at org.apache.maven.deploy.deployers.GenericSshDeployer...
if you have not configured authentication correctly.
Publish the core
JAR
artifact:
C:\dev\mavenbook\code\reporting\core>maven jar:deploy
[...]
jar:deploy:
[echo] maven.repo.list is set - using artifact deploy mode
Will deploy to 1 repository(ies): mavenbook
Deploying to repository: mavenbook
Deploying: C:\dev\mavenbook\code\reporting\core\project.xml-->mdn/poms/qotd-core-1.0.pom
Executing command: mkdir -p /var/www/html/mavenbook/maven/mdn/poms
Executing command: chmod g+w /var/www/html/mavenbook/maven/mdn/poms/qotd-core-1.0.pom
Deploying: C:\dev\mavenbook\code\reporting\core\project.xml.md5-->mdn/poms/qotd-core-1.0.pom.md5
Executing command: mkdir -p /var/www/html/mavenbook/maven/mdn/poms
Executing command: chmod g+w /var/www/html/mavenbook/maven/mdn/poms/qotd-core-1.0.pom.md5
Will deploy to 1 repository(ies): mavenbook
Deploying to repository: mavenbook
Deploying: C:\dev\mavenbook\code\reporting\core\target\qotd-core-1.0.jar-->mdn/jars/qotd-core-1.0.jar
Executing command: mkdir -p /var/www/html/mavenbook/maven/mdn/jars
Executing command: chmod g+w /var/www/html/mavenbook/maven/mdn/jars/qotd-core-1.0.jar
Deploying: C:\dev\mavenbook\code\reporting\core\target\qotd-core-1.0.jar.md5-->mdn/jars/qotd-core-1.0.jar.md5
Executing command: mkdir -p /var/www/html/mavenbook/maven/mdn/jars
Executing command: chmod g+w /var/www/html/mavenbook/maven/mdn/jars/qotd-core-1.0.jar.md5
BUILD SUCCESSFUL
The artifact:deploy
tag is
executing commands on the remote machine using SSH. The structure of
the repository is being created, and all directories and files are
made group-writable with chmod
. As
you can see from the console, the artifact:deploy
tag has deployed not only
the core
JAR, but also the core
project's POM. This is because the POM
is the identity of a Maven project and it may be useful for a user
browsing the repository to know more about the project producing the
artifacts he's looking for. In practice the POMs will also enable
Maven 2 to support transitive dependencies. This
means that in the future you'll be able to specify only the
direct dependencies your project is depending upon, and Maven will
auto-discover the dependencies of your dependencies.
Note
Transitive dependencies are going to be a huge timesaver.
Because you can never be too security conscious, the artifact:deploy
tag creates MD5 signatures
for every deployed artifact. Maven currently does not use them when
downloading artifacts, but they'll certainly be implemented in the
future.
...publishing the packager
's
zip file?
Publishing the JAR was easy because there's an existing jar:deploy
goal. However, there's no zip
plug-in, and thus no zip:deploy
goal! The solution is to write a custom goal in your maven.xml file. Edit the qotd/packager/maven.xml file and add the
code in bold:
<?xml version="1.0"?> <project default="qotd:build" xmlns:ant="jelly:ant" xmlns:artifact="artifact"> <goal name="qotd:build"> <ant:mkdir dir="${maven.build.dir}"/> <ant:zip destfile= "${maven.build.dir}/${pom.artifactId}-${pom.currentVersion}.zip"> <ant:fileset file="${pom.getDependencyPath('mdn:qotd-web')}"/> <ant:fileset dir="${maven.src.dir}/conf"/> </ant:zip> </goal> <goal name="qotd:deploy" prereqs="qotd:build"> <artifact:deploy artifact="${maven.build.dir}/${pom.artifactId}-${pom.currentVersion}.zip" type="zip" project="${pom}"/> </goal> </project>
The qotd:build
goal creates
the QOTD zip (see Chapter 3 for
a refresher). You've now added a qotd:deploy
goal that uses the artifact:deploy
Jelly tag to deploy the zip
file, and then passed in the artifact
attribute. The type
attribute corresponds to the artifact
extension that is used to decide in which directory to put the
artifact in the remote repository. You need to pass a reference to the
current project's POM in the project
attribute. Running qotd:deploy
deploys the zip to the remote
repository, in [REMOTE_REPO_ROOT]/mdn/zips/qotd-packager-1.0.zip,
following the standard repository mapping rule, [REPO_ROOT]/<groupId>/<type>s/<artifactId>-<currentVersion>.<type>
,
discussed in Section
1.1.
Get Maven: A Developer's Notebook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.