Nexus vs. Artifactory

Until now we didn’t use a repository manager for Maven. Our repos were a plain directory structure on the file system served by Apache. Uploading was done using Apache’s WebDAV capabilities with a simple authentication against our LDAP directory:

<Location /maven>
  Options Indexes

  DAV On
  AuthType Basic 
  AuthName "reucon Maven Repositories"
  AuthBasicProvider ldap
  AuthLDAPURL ldap://
  AuthLDAPBindDN uid=httpd,ou=techusers,o=myorg
  AuthLDAPBindPassword secret
  AuthzLDAPAuthoritative off

  Require valid-user
  FileETag None

We are maintaining four repositories: one for our public Open Source artifacts and one for proprietary internal artifacts along with corresponding snapshot repositories. Access to the internal repository was limited based on an IP address range.

There are multiple reasons for us to use a repository manager:

  • Unified access to repositories

    In the old days all you needed was the central repo (formerly known as ibiblio). Times have changed and now many of our projects require artifacts from a variety of different repositories. It seems many organisations prefer having their own repos instead of publishing to central. This includes SpringSource, JBoss, Codehaus and several snapshot repos like for Apache. Maintaing a list of these repos in each developers settings.xml is a pity and including them in the poms makes things even worse in the long run.
  • Finer grained access control
    On the one hand we need access to our internal repo from outside of our internal network, so IP based access control no longer works well. On the other hand not all developers should be allowed to publish releases. Some kind of role based access control was needed.
  • Automated creation of the Nexus index
    A Nexus index is basically a zip file containing a lucene index of the artifacts in a repository. Most Maven IDE plugins now support searching for artifacts when adding dependencies to a project. To make this work the IDE must be be able to download an up to date index of the repositories.
  • Web based artifact search
    You may know a web site to search for artifacts in the central repo. I’ve often used it to find the correct version and maven coordinates for a dependency. A similar solution for our internal repositories would be nice.

There are a lot more reasons to use a repository manager like faster builds through caching of artifacts, black- or whitelisting of artifacts based on corporate standards but those listed above were the key factors for us.

There are three products that can be used: Apache Archiva, Sonatype Nexus and JFrog’s Artifactory. There is a feature matrix
that shows their features.

I dropped Archiva because its development is rather slow and it is missing some important features like grouped repositories. So Nexus and Artifactory remained. I came across two blog postings from January:
Sonatype’s comparison and
JFrog’s response. Combined they provide a lot of insight. Here is my own comparison:


Good LDAP integration is a must have. Artifactory supports this out of the box, Nexus does not include LDAP support in its Open Source edition. It is a Nexus Pro feature. I do understand that Sonatype is trying to sell its Pro version but LDAP support is really a basic and vital feature. Fortunately it is not too difficult to implement a custom authenticator for Nexus and in fact there is already a project at Google Code called nexus-ldap that adds free LDAP support to Nexus. Both Artifactory and Nexus support fine grained role based authorization. One problem I faced with Artifactory was that requiring authentication seems to be a global setting, so you either require authentication for all repositories or for none. This is less flexible than Nexus which allows us to make our Open Source repository available without authentication and requires authentication only for deployment and for our internal repositories.
Artifactory has a nice additional feature that eliminates the need to store the user’s password in Maven’s settingx.xml in clear text by encrypting the password with a user specific key stored in Artifactory. This is an interesting approach and I would like to see this concept being used more widely (e.g. for Subversion).


How the repository manager stores artifacts and meta data is the biggest difference between Artifactory and Nexus. Artifactory uses a Java Content Repository (JCR) that can optionally be hosted in a MySQL database.
Nexus stores artifacts and meta data in the file system. It uses the maven layout so it is easy to access the repositories managed by Nexus externally. This becomes handy not only for migration but also when synchronizing to central through rsync. Though Artifactory offers an export feature having my repository data available directly on the file system makes me feel better.

Searching and Indexing

Both Nexus and Artifactory publish indexes (based on Lucene) and provide a web interface for searching artifacts stored in the repository. Nexus takes this one step futher and also allows searching for artifacts in proxied repositoreis not yet stores in the local repository. This is really handy and eliminates the need to use external sites to search for artifacts and they current version.


Before I found nexus-ldap I was about to choose Artifactory over Nexus. After that I prefer Nexus for the file system based storage and better searching.


Maven Release with Subversion 1.5 and 1.6

There is a problem with the maven-release-plugin when used with recent versions of Subversion. It stared at version 1.5.1 of Subversion and made the release:prepare command fail because Maven was no longer able to tag the release.

You may have encountered the following error with release:prepare:

svn: File '...' already exists

One reason for this can be SCM-406.

For some time I’ve worked around this issue by doing my releases on a machine with an older version of Subversion.

A better solution is to use the latest version of the maven-release-plugin (2.0-beta-9 at the moment) and set the remoteTagging property to true:

        <preparationGoals>clean install</preparationGoals>

Keep in mind that you should always specify the exact version of the plugins you are using. This not only makes sure you get what you need it also ensures that the build is reproducible in the future and works consistently accross different machines.

mvn deploy:deploy-file with WebDAV

Though most of the Java libraries are already in the official Maven repository you will from time to time encounter artifacts that are not available there. Reasons for this include licensing issues (e.g. Oracle JDBC drivers and some Sun Java APIs) and a lack of maintainers.
Most users of Maven run an internal repository for those artifacts and to distribute their own work products.

Recent versions of Maven support uploading artificats along with their sources directly into your internal repo through WebDAV:

mvn deploy:deploy-file \
        -DrepositoryId="internal" \
        -Durl="dav:https://server/repo" \
        -Dfile="oracle-jdbc.jar" \
        -DgroupId="" \
        -DartifactId="oracle-jdbc" \
        -Dversion="1.2.3" \
        -Dpackaging=jar \

The -DgeneratePom=true option tells Maven to generate a basic but fully functional POM without any dependencies.

Using -Dclassifier=sources allows you to upload a corresponding -sources.jar file.

You can also easily automate downloading the original artifact (precompiles jar file, sources, whatever), compiling or repacking and uploading to your repo.
This is what I use for Openfire:


if [ "$#" != "1" ]
        echo Usage: $0 openfire_version
        echo Example: $0 3.6.0
        exit 1




wget -O "openfire-${VERSION}.tar.gz" "$BIN_URL"
wget -O "openfire-${VERSION}-sources.tar.gz" "$SRC_URL"

tar xvfz "openfire-${VERSION}.tar.gz"
unpack200 openfire/lib/openfire.jar.pack "openfire-${VERSION}.jar"

tar xvfz "openfire-${VERSION}-sources.tar.gz"
jar cvf "openfire-${VERSION}-sources.jar" -C openfire_src/src/java .

mvn deploy:deploy-file \
        -DrepositoryId="$REPO_ID" -Durl="$REPO_URL" \
        -Dfile="openfire-${VERSION}.jar" \
        -DgroupId="$GROUP_ID" -DartifactId="$ARTIFACT_ID" -Dversion="$VERSION" \
        -Dpackaging=jar -DgeneratePom=true

mvn deploy:deploy-file \
        -DrepositoryId="$REPO_ID" -Durl="$REPO_URL" \
        -Dfile="openfire-${VERSION}-sources.jar" \
        -DgroupId="$GROUP_ID" -DartifactId="$ARTIFACT_ID" -Dversion="$VERSION" \
        -Dpackaging=jar -Dclassifier=sources

Analyzing Module Dependencies

The declarative approach of Maven provides us with a lot of meta data of software modules that can lead to interesting insights when properly visualized. One attempt to do is by creating images of the dependency graph. JFrog Dependency Analyzer is an open source tool that does just that.

For very simple projects the result looks great:

The nodes represent Maven artifacts (groupId, artifactId and version), the edges represent dependencies. Next to an edge you see the scope of the dependency (usually compile or test).

For larger projects you can easily end up with an unmaintainable mess. For example have a look at this analysis of Confluence:

JFrog includes a few features to help you clean up a bit:

  • Reduce the scope to “compile” to exclude dependencies used only for unit tests.
  • Make sure “show excluded” is switched off otherwise you end up with a graph showing dependencies you already excluded in your POM.
  • Reduce the depth to which transitive dependencies should be resolved.
  • Use the “Filter by group id…” feature if you want to ignore dependencies to external libraries and only show dependencies between the modules of a larger project.

You’ll find more information on the JFrog Configuration page.

Maven vs Buildr

Jim Alateras talks about how Buildr could replace Maven in a blog entry titled “From Maven to buildr“.

Buildr claims to be a drop-in replacement of Maven as it uses the same file layout, artifact specifications, local and remote repositories.
For sure the best practices built into Maven are great and the central repository is a place where you’ll find almost every relevant open source java library but Maven is much more. Maven’s big advantage over ant is a declarative approach describing projects instead of describing (or programming) the build process. Buildr drops the Maven POM (project object model) and returns to coding the build process — this time not in XML as in ant but in Ruby. Apache ODE’s Rakefile may serve as an example.

Jim notes that Buildr seems to be faster than Maven and continues

All extension tasks (ala maven plugins) are written in Ruby so you get all the power and benefits of a turing complete language as opposed to the constraints of maven plugins.

Well since Maven 2 all its plugins are written in plain Java — seems like the author really should have invested some time to actually look at Maven’s design.

Can we learn from efforts like Buildr?

Well, the POM used by Maven to describe the projects is a bit verbose in some cases, this should be addressed in future versions. Besides that some performance optimizations might be a good thing tough I don’t think they are so badly needed. Maven already reduces the time to build by making it very easy to reuse pre-built snapshots of depentant modules.

Besides this it will remain a religious issue on whether you prefer a declarative or a procedural approach for your build process. If you prefer the later have a look at Buildr but don’t buy it as a drop-in replacement but as a different solution that reuses some of Maven’s achievements.

Using Maven with IntelliJ IDEA 7.0

IntelliJ IDEA 7.0 (Selena) which is currently available as part of Jetbrain’s Early Access Program now supports Maven out of the box.

The efforts of various previous third party plugins have been joined into a first class feature with support for

  • running Maven goals directly from the IDE similar to the ant integration
  • synchronizing pom and IDEA project files (updating depedencies, etc.)
  • a default project layout conforming to Maven standards in the project wizard.

Given the fact that Eclipse is still unable to ship out of the box support for Subversion – not to talk about Maven – this makes choosing the right IDE quite easy.

Attach Sources to your Maven Artifacts!

One of the key advantages of open source software besides being available free
of charge is – well – that its source is available to developers reusing existing
open source libraries.

Having the source available in your IDE when developing against an API is such
a great thing that I wonder why so few open source projects care to make this
asset easily available to their “customers”.

Maven and its central repository (aka ibiblio) provides a great facility to
publish sources along with the jars. All it takes is a small snippet added to
your project’s POM (or its parent POM) before you upload the bundle to the


I really wonder why this isn’t the default in Maven and encourage all open
source developers to provide sources for their releases.

Consuming the sources is handled by the IDE plugins Maven provides but again
this is not the default:

mvn -DdownloadSources=true idea:idea


mvn -DdownloadSources=true eclipse:eclipse

Et voilà: all sources attached to the jars and available through
Shift-Click or whatever your IDE’s shortcut is.