Saturday, November 21, 2009

Setting up a Maven repository proxy with Nexus

Background

Hey, quick hint: if you need quick get-to-the-point instructions on how to setup a free Maven repository proxy you can skip this section and scroll down to the next one. But, if you have some time to spare and are curious to know why one would need to setup his own Maven repository proxy, please bear with me a little and keep reading...

It should be a bit more than 3 years since I stopped using Ant in favor of Maven to automate builds, tests etc. After years using Ant for both personal and professional projects I got into a (then) new project where the dev team was using Maven. By that time I had already read about Maven and tried it briefly on minor prototypes just to evaluate it against Ant. In those first contacts it just seemed much more complicated than Ant, everything was considerably different etc.

Like I said, in this new project other analysts had already set it up the whole development environment, and since I had other pressing issues to focus on I did not learn much about it. The guys who set it up were amazing technical analysts, they picked excellent tools (they used AntHill Pro, among some others) and had a deep understanding of best practices for build management, test automation, quality control etc, and because of that I never had to trouble with nor had to deal with Maven or the build process myself.

Then, about another 1 and a half years ago, I began as the leading developer (and pretty much THE ONLY developer, designer, architect etc, I should add) on another project I wanted to stick with Maven. I guess I just got spoiled with things like automated dependencies download and the ability to integrate with such amazing apps like Hudson and Trac. Finally, the fact that AppFuse is heavily based on Maven also helped me made my mind.

A quick note on AppFuse: it is amazing how simple AppFuse makes it for us to kick-start our solutions rather than spend time on mundane things like defining your project hierarchy, setup Maven, Spring, Hibernate etc, but it comes with the price of being another level of abstraction – it help make things work even if you don't quite know how they work. Based on that, my advice is to use it or a similar super framework to save you time on redundant tasks but do take the time to learn how it does what it does!

So, long story short, that project I was working almost by myself grew, it got more developers and made its way to a production environment. During one of our code drops I got a message from the release manager that the build server was not able to build the application, something to do with a missing dependency. Well, yeah, if you ever worked with Maven you know one of the first things you learn is that it can download dependencies for you from the Internet. But this time it did not work. I built it locally, and it worked fine, no problem. I then removed my Maven repository, and that is when I got the exact same error we got in the build server – Maven was unable to contact one of the public Maven repositories the project depended on.

It is funny that I remember speaking to the build manager couple weeks before that incident that we should setup our project's own Maven repository to avoid something like that. But, as much as an outage of a Maven public repository is to be expected and therefore should be prevented, since I had never seen it before it got a very low priority in our To-Do list.

I found a quick fix for that by simply pointing the build server to my personal Maven repository, which had all required dependencies and did not need to download anything from the internet. So, in the end, there was no big harm other than me and the build manager having to spend about one hour to figure it out, upload files to build server and finally get the build completed.

What we can learn from this story? I don't know about you, but I learned that if we blindly depend on things beyond our control, as stable as they look like or use to be, they will fail us on unpredictable times.

It is my responsibility to shield my project from any outages on systems I do not control. The same way I always build simulators and stubs for external systems I must do something similar for external Maven repositories. And that is where a local project Maven repository fits in.

A Maven repository proxy is just a simple mechanism that acts as a mediator between your Maven-based applications and the Maven public repositories in the internet. It gives you control over your application dependencies – say, if you built your application yesterday with success, and assuming then that your Maven repository proxy is up to date, the public Maven repositories can burn and you will still be able to build your application. I hope they don't actually burn though, that was just an expression to make the point! Also, since you are not downloading hundreds of JAR files over the internet but from a local server, it may even improve your build times considerably.

So, which one to use? I tried 3 or 4 different Maven repository proxies and found Nexus to be the best one of the bunch, on my humble opinion. It could not be much simpler to install and set it up, and once you do you can forget about it, it just works!

If you are one of my 2 or 3 readers who might had the patience to get to this point with me, be happy this section is over. I will describe in the section below how easy it is to install and setup Nexus as your free-as-in-beer local Maven repository proxy.


To-the-point Nexus installation and configuration

Nexus is released both as a stand-alone server and as a standard WAR file. This section will describe how to install the WAR file release only.

To install Nexus as a WAR file just follow these instructions:

1. You need a servlet container to install Nexus WAR file. While any recent application server should work just fine I only tested it with Tomcat 6.0.20. If you do not have a servlet container I recommend you to download and install the latest stable release of Tomcat 6.x into your build server. For the purposes of this article I will assume you have Tomcat installed in $TOMCAT_ROOT (wherever it is) running on 127.0.0.1, port 8080. Make sure you replace IP address, port and paths on the next steps based on your environment.

2. Download the Nexus WAR file – usually I would recommend you to download the latest stable version but I had some trouble with Nexus 1.4.0 on Tomcat. The previous version, 1.3.6, works fine though and you can get it directly from this URL: http://nexus.sonatype.org/downloads/older/nexus-webapp-1.3.6.war

3. Rename the WAR file to nexus.war – this will make your Nexus portal URL much simpler.

4. With your Tomcat running, copy or upload the file nexus.war into “$TOMCAT_ROOT/webapps” - this should deploy Nexus in just few seconds, as shown in the image below.





If everything worked you should now be able to access Nexus web console in this URL: http://127.0.0.1:8080/nexus/




Click on Repositories link in the left menu to see which repositories are available and their URLs, as shown in the figure below. Nexus comes pre-configured with the most popular repositories including Maven Central, Codehaus and Apache. If your application requires only the most popular libraries the odds are that you may not need to change Nexus' configurations at all. If that is the case, the only thing you need to do is to edit your application's pom.xml to use Nexus repository paths (e.g. “http://127.0.0.1:8080/nexus/content/repositories/central/”). If you want to confirm exactly where each one of these URLs are pointing to or if you need to include new repositories you need to log in as an administrator.




To log in as an administrator and configure Nexus click on the link “Log In” on the top-right portal. It will ask for credentials, to witch you can use admin / admin123.




Once you log in, click on Repositories and select “Maven Central”. As an ADMIN you will see new tabs, click on “Configuration”. In this screen you will find that URL “http://127.0.0.1:8080/nexus/content/repositories/central/” is associated with a remote repository URL “http://repo1.maven.org/maven2/”, the Maven Central public repository. So, in essence, when your application tries to download a library from the Nexus URL that is not in your Nexus repository, Nexus will download it from Maven Central, but the next time it will not need to, since Nexus will keep the library in its local repository.

For my particular project I had to setup 2 or 3 additional repositories in Nexus. That was also easy, I just “cloned” one of the existing entries in the Nexus web console. I then updated the repositories section on my project's pom.xml to point to the repository paths listed in Nexus' web console. I was amazed my project got built successfully the first time, it was so simple even my humble self got it right the first time!

If you tried this but found that I missed some important step this may help - there is much more detailed information on how to install Nexus here: http://www.sonatype.com/books/nexus-book/reference/install-sect-as-a-war.html


References

• Nexus: http://nexus.sonatype.org/

• AppFuse: http://appfuse.org/

• AntHill Pro: http://www.anthillpro.com/

1 comment:

  1. Also, additional benefit of being able to publish project artifacts to the same proxy. Nice post.

    ReplyDelete