Maven Repository Manager: Nexus Vs. Artifactory
My goal is to compare Sonatype Nexus and JFrog Artifactory,the two leading open source Maven repository managers.
My goal is to compare Sonatype Nexus and JFrog Artifactory,the two leading open source Maven repository managers. While there aremore than a handful of blogs and articles comparing these two products like this one, my focus is not necessarily on feature comparison or roadmap,but also on the ease of use, user experience and several other aspects I’mgoing to touch.
For fairness, my experience with both products is fairly equal (and not too thorough). I also have no intention to discuss the more advanced features that are shipped with Nexus Pro or Artifactory Add-ons Power Pack.I will refrain here from comparing features and capabilities which I’ve found those two products support in a similar manner.
I follow here with a case study. A customer of mine is considering using a repository manager for Maven artifacts management. My aim is to examine these two repository managers, giving my recommendation to the client. I’ve used latest stable versions: Nexus 1.4.0 and Artifactory 2.1.2.
I’ve downloaded both products. Both can be deployed using an embedded Jetty, wrapped using JSW, or as a standalone web application, nothing much to say about it. Both were installed on a single machine.
Nexus uses file system to store artifacts and metadata, whereas Artifactory uses Derby DB by default. I’m just mentioning a fact here, and don’t have intention to be caught in the crossfire, by giving my opinion over the dispute which method is better. Artifactory can also be configured to use a handful of RDMBS for artifact storage (MySQL, PostgreSQL, Oracle…) as well as using the file system.
Artifactory has somewhat more compact storage: binaries are stored by their checksums, thus stored only once. This way, copy and move operations are cheaper.
Nexus jar weighs about ~13M while Artifactory is about ~37M. I consider it a marginal issue though. How often will you download any or both? Initial memory footprint indicates Artifactory memory consumption is about 50% higher than Nexus, testing on few machines.
My initial aim is to use both products as a proxy repository and as a repository for project artifacts deployment (indeed, it’s what these product are aiming for). For comparison sake, I’ve cleared the local repository before each project build. The Maven project contains a parent pom and comprises of four modules. It contains about 3 dozen dependencies. Few of which I had to install on my local repository prior to using any repository manager.
I’ve started with Nexus. I had to edit my settings.xml to use Nexus as my releases and plugins repository, and built my project using mvn install, after enabling remote indexing on Nexus.
First module failed to build as it was missing a JTA dependency. No problem. I’ve added a new java.net proxy repository. Encountered a similar problem for few Google Code dependencies, again had to add a remote repository to Nexus repositories configuration.
Few other third party dependencies were uploaded to the 3rd party Nexus repository via the repository web UI “Artifact Upload” Tab.
One comment - After deleting an accidently uploaded file, the repository index was not updated to reflect that deletion.
Then, I’ve switched to Artifactory. Cleaned my local repository again, and deleted my settings.xml file.Unlike Nexus, one small but very useful feature Artifactory has is the ability to generate and save a settings.xml file - nice to have. Maybe not a big deal, but saves some troubles and protects you from typo’s and stuff.
Also I’ve noticed that I hadn’t a problem building using JTA or Google stuff. After a short puzzlement I’ve realized that Artifactory is configured using a handful of remote repositories: Java.net, JBoss, Google Code and others. Again, maybe not a big deal, but these are repositories we all use anyway. A small service for a big community, thumb up for the Artifactory guys.
Also, using Artifactory you can also import | export repositories definition (including metadata), meaning that you can easily replicate your repositories to other Artifactory instances. You can also import your repository from a zip file, meaning you can construct your repositories from your file system local repository.
I’ve used the mvn install goal to perform a preliminary benchmark. For Nexus I’ve turned on remote indexing, and for Artifactory I’ve turned on “Eagerly Fetch Jars” checkbox (eagerly retrieve related artifacts in parallel once a pom is required) for relevant hosted | remote repository. Both benchmarks were done using empty repository caches.
Building the project using Artifactory took about 5 minutes whereas building using Nexus took about 8.5 minutes. Not exact science kind of faster, but still good for initial impression.
Both Nexus and Artifactory have certain similar search features. Both allow you to search by keywords, classes within artifacts, and GAV: group, artifact and version (actually for Artifactory it’s GAVC where you can also search by a classifier).
For these searches, result list is fairly different: Nexus uses remote indexing to promote results from remote repositories. While sometimes you may want to browse a remote repository for results (for example: in the case when you want to look for a new release for a 3rd party artifact you’re using in a convenient manner), I find it quite frustrating: you are overwhelmed with search results you hadn’t anticipated and you are not interested in. In order to avoid remote repository inclusion, one has to switch off remote indexing. In my opinion, this should be controlled by a query term. Sorting by an artifact version for example proves to be unhelpful once search result contains much irrelevant data to your projects and organization. More ever, this actually becomes a nuisance especially in the case of Class Search. Search becomes unreliable and unusable.
Nexus has the option to search for an artifact by a checksum. It’s a nice to have, but I’m not sure how relevant it is.
It’s the POM/XML search feature of Artifactory where it really shines. You can search your artifacts POMs using XPath expressions, opening many interesting options: for example you can aggregate your artifacts by license information. This option is not restricted only to maven generated artifacts, but also to ivy.xml files (Indeed Artifactory is your choice as an Ivy repository manager).
In conjunction with this feature, Artifactory also provide a means to attach a metadata XML file with an artifact or a folder. This metadata is also searchable using XPath, making artifacts tracking, aggregation and management much easier. For example, you can search all artifacts that were deployed by a certain build (by build number), and promote it to a public repository. Currently the metadata association is only enabled via a REST, but searching is enabled in the Artifactory UI.
It’s time to deploy my artifacts to the repository manager, in order to make my artifacts available to other departments in the customer’s organization. My aim is to define the minimum reasonable security settings in order to deploy my releases and snapshot into the repository manager.
I’ll start with Artifactory this time. Using the web UI security settings, I’ve defined a new group named ‘Local Deployers’, for the purpose of deploying releases to the libs-releases-local and snapshots to the libs-snapshots-local local repositories. Then, I’ve added a new permission named ‘Deploy Locally’, associated the two aforementioned repositories with that new permission, and added the ‘Local Deployers’ group with deploy permission to it. Finally I’ve created a user named ‘ori’, and added that user to the ‘Local Deployers’ group. Very intuitive, nothing more than a minute labor.
Using mvn deploy, the 1.0.0-GA artifacts were deployed to the libs-releases-local local repository. No problem. Trying to redeploy, yielded 401 error code, but the Artifactory log showed me the reason for it: apparently I’d also needed ‘DELETE’ permission.
I’ve changed my artifacts version to 1.0.0-SNAPSHOT and redeployed, this time the artifacts were resolved correctly to libs-releases-local local repository.
And now for Nexus, it comes preconfigured with a handful of privileges in advance. This is very powerful, but not convenient to manage nor intuitive as we’ll soon see. My first aim was to define a new Repository Target privilege with deploy permissions to releases and snapshots repositories. Alas, unlike Artifactory where one can check | uncheck any local or remote repository or use a palette to add | remove a repository for a permission, Nexus allows you to include only a single repository or repository group as a target. So, I had to define a repository group named ‘Local Repository Group’ which included releases and snapshots repositories, followed by the creation of a new privilege, naming it ‘Deploy Locally’.
Then I created a new Role named ‘Local Deployers’ including the aforementioned privilege four targets: create, delete, read, update.
I’ve created a new user named ‘ori’ with the intention to associate it with the new ‘Local Deployers’ role, which was not apparent anywhere in the ‘Available Role’. I’ve restarted Nexus and Voila, it has appeared. Finally it worked.
The somewhat unintuitive process took me about 15 minutes to manage.
To recap, security policies and deployment settings are easier, and more intuitive using Artifactory. Artifactory also lets you easily define inclusion and exclusion patterns for a more fine grained control over what is available for deployment and by whom.
Repositories configuration and capabilities is an essence of both products. I’m now going to compare the varied features and configuration policies between the two products. I’ll start with proxy (Nexus) versus remote (Artifactory) repositories:
Nexus repositories can only server release or snapshot artifacts, while Artifactory also supports storing both. While Nexus approach is more concise, you’ll have to actually duplicate your proxy repository settings in case the remote repository serves both releases and snapshots, while Artifactory has settings to correctly handle snapshots whether the remote repository serves only snapshot artifacts or both.
Artifactory has a very nifty feature to include | exclude pattern for remote repositories which comes handy once you want to avoid looking up remote artifacts on repositories that will never contain those artifacts. Nexus doesn't have include | exclude patterns (you have to pay for it- it’s a part of their procurement plugin), and uses negative regular expressions, which can be more hard to follow.
Artifactory also has more policy options to handle bad or missing checksum, which I’m not going to get into here. Nexus on the other hand contains specific permissions to restrict a repository browsing and searching via a web browser.
Both Nexus and Artifactory have configurable caching policy for caching remote snapshot artifacts. Artifactory artifacts under a remote repository can be accessed via a URL pattern which serves only already cached artifacts without hitting the remote repository.
Artifactory has also a feature called “POM Consistency Checks”. Artifactory will check that the coordinates of POMs retrieved remotely match the GAV information inside the POM, and will reject conflicting POMs. This behavior can be disabled per repository.
The second field for comparison is hosted (Nexus) versus local (Artifactory) repositories:
Same here, Artifactory has a mixture of release | snapshot repositories, include | exclude patterns and POM Consistency Checks. One can also configure unique snapshot policy: unique snapshots using timestamp and build number, non-unique snapshots, or respect user snapshot policy. Nexus on the other hand can be configured to allow | disallow redeployment (default allow for snapshots, disallowed for releases) which is enforced by Artifactory only via permissions.
The third field for comparison is Repository Groups (Nexus) versus Virtual repositories (Artifactory):
This feature allows one to combine a group of repositories via a single URL. Thus, one can change the participating repositories and their rules without requiring any client-side changes. Artifactory has the ability to nest virtual repositories one inside another.
Audit and notifications:
Auditing is much easier using Artifactory, which contains an access log for security-related events. Specifically:logins, artifacts downloads and deployments. This log is viewable from the Artifactory UI, and can be downloaded. Nexus logs don’t contain such detailed information, at least not in a separate manner.
Nexus on the other hand contains a unique feature of RSS feeds for specific events. Namely: for downloaded and deployed artifacts, logins, system configuration changes and checksum errors. Artifactory currently does not support RSS feeds.
Artifactory – Hudson integration
As for now, I’ve pretty much made up my mind. You can jump to the conclusion section to see my own choice and the reasons for it. For now, I want to mention Artifactory unique feature of integration with CI servers.
JFrog has announced Artifactory Hudson Integration in the upcoming release (2.1.3) via Hudson Artifactory plugin, in a recent demo at Devoxx.The idea is that the reproducible information can only be captured at build time, typically done by a CI Server: version ranges, plugins and properties can change from build to build. The CI Server (Hudson in this case) has all necessary data to reproduce the build, and is the only mean to guarantee a release. The Hudson Artifactory plugin generates a “Build Info” which is deployed to Artifactory via REST. The Build info is tagged on Artifactory, the same way one can tag sources via SCM tagging.
That way, you can have bi-directional links between builds and binaries. You can watch and navigate your builds in Artifactory and link back and forth to Hudson. This is a unique and powerful feature. It’s the only, very efficient way I know to tag your builds, and guarantee their reproducibility.
True, I haven’t tested the plugin, as it’s not available to download yet. However, after watching the aforementioned demo, I was convinced by the plugin necessity and power.
It’s seems that Artifactory development and roadmap are driven from user and community needs, and many features (though some of those are small) were developed from getting repeated feedback and requirements from the community.
Artifactory is slightly easier to start with: settings.xml export, more remote repositories, import and export of repositories.
For most of the features I’ve compared throughout this article, Artifactory emerged as a winner.
Artifactory has more unique features to offer than what Nexus has to offers.
Artifactory UI is more intuitive, and easy to work with.
Artifactory has a richer feature set when it comes to configuring repositories and defining policies over these repositories.
Artifactory searching options, and search result reliability are superior. Searching by metadata and XML files using XPath expressions tremendously ease your artifacts management burden. By annotating, tagging and grouping your artifacts, those can be much easier to manage.
In terms of stability (at least from the web UI point of view), it seems that Nexus has few quirks, some I had described in this article.
Artifactory is currently your only choice if you build your project using Ant/Ivy or Gradle.
Hudson Artifactory plugin (and future integration with TeamCity); artifacts tagging and build reproducibility make Artifactory shine even brighter.
As for me, I’m pretty much convinced: Artifactory is the better choice.