Peter has posted 1 posts at DZone. View Full User Profile

Five tips for successfully deploying Maven

05.04.2009
| 9375 views |
  • submit to reddit

Maven is one of those things that people seem to hate rather intensely, but nevertheless adoption is steadily rising in the Java community. I've worked with Maven almost daily since the 1.0 betas, and here are five things that I think could help your team working more efficiently with Maven.

Use a repository manager

A repository manager is basically an on-demand mirroring repository cache that you set up inside your IT infrastructure and use as primary repository for your builds. They basically work like this: if you build a project that depends on, for example, commons-lang-2.4.jar, the repository manager will download the artifact from the main Maven repository on the web, cache it locally and return it to the build client that asked for it. All subsequent builds that use the same managed repository will get the commons-lang jar delivered from the cache, not from the web.

This has many advantages. First of all, it's fast. All project members, except the first one, will download any given dependency at LAN speed, which is especially nice when you're setting up a build environment from scratch (new project member, staging a clean build, etc). And of course it saves external bandwidth for other purposes and to lower costs.

Second, it's safer. It allows you to run centralized and incremental backups on all external dependencies that you projects use, and you reduce your dependency on the availability of public repositories.

Third, it's convenient. From time to time you will need a library that's not (yet) available in any public repository, so you have to publish it somewhere. A repository manager makes that really easy. And if you're sharing internal libraries or interfaces between projects, it's extremely handy to deploy to the managed repository. You can even set up your continuous integration build to automatically deploy snapshots.

I've had a pleasant experience working with Nexus, but there are others. A repository manager should be as natural a part of you infrastructure as SCM and CI if you're using Maven.


Specify plugin versions
By default, Maven will automatically download a new version of any given plugin whenever there is one available. Given that Maven is 99% made up of plugins (there's even a plugin plugin!), this is a potential point of breakage over time and in my opinion a design mistake.

As of version 2.0.9, the default behaviour is improved by locking down the versions of the core plugins (where "core" is defined by this list). However, you still need to explicitly define versions for all non-core plugins, and that can be done at the top level pom.xml in a hierarchial project using the pluginManagement section.

<pluginManagement>
<plugins>
<plugin>
<artifactid>maven-assembly-plugin</artifactid>
<version>2.2-beta-2</version>
</plugin>
<plugin>
<artifactid>maven-antrun-plugin</artifactid>
<version>1.2</version>
</plugin>
</plugins>
</pluginManagement>

Do this for the plugins that you actually use. Note that for plugins with group id org.apache.maven.plugin, you can omit the groupId element.

This will make your builds more stable and eliminate a fairly rare but very annoying and confusing set of problems.

Learn how to use the dependency plugin

Maven introduced the concept of transitive depedencies to the Java community, and has been a source of confusion ever since. The dependency plugin is an invaluable tool for analyzing the results of the dependency algorithm, and to handle dependencies in various ways. Here are a couple of things you can do with it:

  • dependency:tree
    shows (you guessed it) the dependency tree for the project, what dependencies are being pulled in and why. It's a nice overview and can help you tweak the dependency structure by excluding artifacts or override versions and so on. Example output:
    [INFO] +- org.apache.activemq:activemq-core:jar:5.2.0:compile
    [INFO] | +- org.apache.camel:camel-core:jar:1.5.0:compile
    [INFO] | +- org.apache.geronimo.specs:geronimo-jms_1.1_spec:jar:1.1.1:compile
    [INFO] | +- org.apache.activemq:activeio-core:jar:3.1.0:compile
    [INFO] | | \- backport-util-concurrent:backport-util-concurrent:jar:2.1:compile
    [INFO] | \- org.apache.geronimo.specs:geronimo-j2ee-management_1.0_spec:jar:1.0:compile
  • dependency:go-offline
    Downloads all project dependencies and plugins, transitively. It's a good command to run both if you want to work offline for a while and if you want to get as many of the external dependencies in place in a single shot with no manual intervention while you go grab a cup of coffee and/or read another item in Effective Java ;-)
  • dependency:copy
    dependency:copy-dependencies
    If you ever need to handle artifacts as files, copying all or some of them to a custom location for whatever reason, this is a good approach.
There are many more things you can do with it, and mastering it will help you get on top of the transitive dependency situation.

Use the documentation

Well, duh. But a weak point of Maven in the eyes of many people is the lack of documentation and the sometimes poorly organized information. There are a few good points of reference though, that you can spread around you team by setting up links on the Wiki for example:

  • The Definitive Guide to Maven: a free book from Sonatype, available both as HTML and PDF. Good for the beginner, and sometimes as a reference. If you don't know where to start, start here.
  • The plugin list: a comprehensive list to the official plugins, with links to each project page and JIRA subsection. Most of the core functionality is actually performed by one of these plugins, and you can learn a lot by studying things like the resources plugin documentation.
  • The POM reference: for the slightly more advanced user. Every element in the POM is explained. Don't forget to specify the XSD information in your POM file to get the most help from your XML editor.

Understand the conventions
Maven is a conventions-based tool, relieving you from scripting common task like compiling source code, running tests or packaging a web application into a war file. Learning the conventions - directory structure, build phases - and working along them will make your life easier a lot of the time.

There are definitely situations even in moderately sized projects to customize the build however, and Maven can sometimes be quite cumbersome to work with when you need to break the conventions. But by understanding the conventions and having the mindset that there is a good chance what you're trying to do can be accomplished within the realms of the conventions, you might be able to find a different approach than you otherwise might have.

Perhaps that ugly jar-splitting, file-copying, token-replacing antrun hack that you spent an agonizing week writing could be replaced by extracting part of the project into a separate module and included as a dependency instead? It's a lot easier to swim downstream than upstream.
Maven is not perfect by any means, but it has brought standardization and conventions to the world of Java development. Project structure, directory structure, public metadata and artifact repository publishing to name a few. There are lots of plugins available, both central and third-party ones, and most IDEs and continuous integration servers support Maven very well.

A lot of the standardization may even outlive the Maven tool itself, as demonstrated by two newer build system for Java: Buildr and Gradle. They both use many of the same conventions, and could challenge Maven by perhaps being able to scale down in complexity more easily and have a lower threshold for newcomers. Progress on Maven slowed down a bit after 2.0, but recently the 2.1.0 version was released with a number of important improvments, for example parallel resolution of depenencies.
References
Published at DZone with permission of its author, Peter Backlund. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Ivan Lazarte replied on Mon, 2009/05/04 - 10:58am

What numbers are you using to prove Maven is steadily rising. Open source projects? Or is it totally anecdotal.

Mark Thornton replied on Mon, 2009/05/04 - 12:43pm

"Maven introduced the concept of transitive depedencies to the Java community"

Both OSGI and WebStart manage transitive dependencies and long predate Maven.

Peter Backlund replied on Mon, 2009/05/04 - 12:56pm

It's a guesstimation based on open source projects, my own professional experience as a consultant (and that of my co-workers'), increasing level of tool support in IDEs, things like that. In other words, I pulled the numbers out of my ass :-)

 

Peter Backlund replied on Mon, 2009/05/04 - 1:03pm in response to: Mark Thornton

Fair enough. That should probably be refined to specifically mention the context of build tools. I didn't mean to suggest it was an invention, rather that it introduced the concept to a wider audience.

Jilles Van Gurp replied on Mon, 2009/05/04 - 2:14pm

I'm a recent convert. I used to be 100% in the ant camp. Lately, I've been in a company where maven is the norm and so far I'm adapting well.

My main gripe has always been that, fundamentally, maven doesn't fix a problem I have: dependencies? Couldn't care less. I can download those & diskspace is cheap but my time isn't. Either way, you should be taking conscious decisions on things like versions for your dependencies and there's ways to ensure people use the same stuff other than letting maven automate the download process.

So, the second grip I have with maven is the endless amounts of time wasted watching maven download, redownload, and re-hit that poor cache over and over again for the same dependencies build after build, as well as the same mostly redundant things is driving me nuts (yes, I know about -o). It seems just about every command triggers a full run of our full test suite. I observe that most of the time maven chooses to run the test suite I can already predict exactly what is going to happen: the same as last time because I didn't change a thing. And yes I know how to set -Dmaven.test.skip=true but it gets such a pain having to type that. Maven defaults to doing everything unless you tell it not to. Turns out I spent a lot of time watching maven do its thing. I could have written some pretty cool ant scripts in the cumulative time wasted by maven.

But altogether, the pain is still worth it. Maven enforces a few good things:

- consistency in directory layout. I happen to find the layout annoying but I can work with it. But picking some convention and sticking with it is better than the endless goes at the perfect directory layout you get with Ant.

- it integrates testing into the build cycle, you can do the same with ant but people are lazy. Maven makes this so easy that you feel guilty not having a test suite.

- maven plugins actually do cover most of the usecases you will encounter. I have so far had no need for custom ant tasks and we use a lot of plugins.

- Easy to hook up to continuous integration environments. This is great. We have commit (compile install), integration (compile install integration-test) and nightly builds (compile integration-test deploy site-deploy).

- maven modules are a great way to break down stuff into components. Combined with a container like OSGI  that enforces provided and required APIs this is great for enforcing architectural saneness. With ant you always end up puting *.jar on the classpath. Sadly we are stuck using Spring, which doesn't enforce any API constraints like OSGI does (but it's great otherwise).

- a sane release process. For me the value of a local repository is not external dependencies (that's just a performance optimization) but the fact that it is a place for teams to deposit releases of their artifacts that are properly versioned and can be depended on to be there when you need them.

Yes, you, can do most of this with ant. Provided you have the right ant file of course. Maven does this out of the box. You get it for free. But ultimately somebody has to sit down and write (and then maintain) the pom file or ant file. It turns out without either a maven or ant expert you won't get very far. I haven't written an ant file lately but I used to be pretty good at this. With either ant or maven you end up with a lot of copy paste reuse. Most people I work with wouldn't get very far writing either ant or maven buildfiles without stuff to copy from.

Btw. coolness: mvn eclipse:eclipse, import project into netbeans -> get your ant buildfile for free. Ant is a lot faster doing the same stuff. 

 

Peter Karussell replied on Tue, 2009/05/05 - 11:39am

Nice Post! Especially the tip with the dependency plugin and the docs ;-) ...

Kathy John replied on Tue, 2012/02/21 - 1:01pm

For someone new to maven, since there is no way to ask maven for the list of available targets (and if there were, the list would be unusably long), it is a great help to document things like "how to run integration tests", "how to run one test", "how to compile only", etc. Determining these things is a baffling ordeal.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.