Monday, January 14, 2013

Java PathFinder Maven repository how-to

I set up a Maven repository for Java PathFinder projects in the past few days. I spent long hours to figure out the solution for some problems, so I decided to share my experiences.

Install a Maven repository manager

The first step is to install a Maven repository manager. There are many good open-source candidates like Artifactory or Apache Archiva, but my favourite is Sonatype Nexus. There is a standalone version which runs in a Jetty container, but it is also distributed as a war file that can be deployed in almost any JavaEE container. Its install process is very straightforward, consisting of a few easy steps.
After you have a working repository manager, you should create a Maven repository for JPF. It can be done using the web-based admin interface of Nexus. (Do not forget to change the default password of admin and deployment users.)
At the left panel you find the "Repositories" link which opens the "Repositories" tab. Click the "Add" button on the toolbar and choose the "Hosted Repository" from the list, then fill the "Repository ID" and "Repository Name" fields. After you save the configuration, your repository can be accessed in {URL of your Nexus deployment}/content/repositories/.

Generate and upload the artifacts

At first, clone the Mercurial repositories of JPF that you want to hosts in your Maven repository. Then you should run Ant build for each project to create the jar files that you upload to the Maven repository.
After this step, you are ready to upload the artifacts. It can be done using the admin UI of Nexus or from command line by executing mvn deploy for each jar file:
mvn deploy:deploy-file -Durl={URL of your Nexus deployment}/content/repositories/{repository ID} -DrepositoryId={repository ID} -Dpackaging=jar -Dfile={jar file} -DgroupId=gov.nasa.jpf -DartifactId={name of the jar without the extension} -Dversion={JPF module version number}
Before issuing this command, make sure that your Maven settings contain a repository entry for the repository ID and the corresponding username/password entries are set.


The JPF projects are constantly changing, so you might want to update your Maven repository with the artifacts containing these changes. The next step is to create a script to poll the Mercurial repositories, compile the sources and upload the jar files to the Maven repository. I created a small Bash shell script for this task:

nexus_repo='{URL of your Nexus deployment}/content/repositories/{repository ID}'
jpf_home='{path to your local Mercurial repositories}'
repo_id='{repository ID}'
module_version='{JPF module version number}'

for repo in $jpf_home/jpf-*; do

    cd $repo
    changesets=$(hg incoming)
    if [ -v "$changesets" ] || [ ! -d build ]; then

        hg pull -u && ant || continue
        for jar in build/jpf*.jar; do
            if [ -f $jar ]; then

                mvn deploy:deploy-file -Durl=$nexus_repo -DrepositoryId=$repo_id -Dpackaging=jar -Dfile=$jar -DgroupId=$group_id -DartifactId=$artifact_id -Dversion=$module_version -Ddescription="$changesets"

This script updates the local Mercurial repositories, executes the Ant build task for each JPF project and uploads the resulting jars to the Maven repository. In case you want to run the script periodically, you may create a cron job running couple of times a day or a week.

..and done.