Agile Zone is brought to you in partnership with:

Julian writes by night as The Build Doctor, a poorly disguised non de plume. By day he is a freelance build engineer, systems administrator and all round useful guy. Julian lives near London with his fiance and children. He enjoys balancing a love of real ale and Indian food with cycling. Julian has posted 16 posts at DZone. View Full User Profile

Should you move to Maven 2?

06.23.2010
| 8123 views |
  • submit to reddit

I’ve seen many a company try to migrate from Ant to Maven with varied success.  There is a change in mindset that has to come about when making the transition.  Here are some of the highlights.

Standard Findings

Monolithic build structure

This is the first big shift in thinking.  Typical (obviously, not ALL) Ant projects work by syncing some massive amount of code from source control, CD-ing into some top level directory and then telling Ant to build just the module you plan on testing.  What’s so bad about this, you may ask?  Well, for one, you’re likely syncing large amounts of code that you’ll never run locally.  You’re probably building up (and unit testing, right?) packages that don’t change or the rate of change is very low as well.  Ideally, these packages and libraries would be built for the user already.  Now look at this through, say, a webdev’s eyes.  If your webdev group is responsible for things like CSS, HTML or JSP changes, why should they be concerned about building up your oodles-of-utils package?  Or, if a unit test starts failing on them (you’re unit testing, right?), why should they have to dive in and figure out what’s missing or broken.  In a perfect world, any tier of development could be substituted for another (how great would it be if everyone knew everything?).  In in the real world, the one with interruptions and families and deadlines, that’s unrealistic (especially in larger companies).

So decommissioning a monolith a few modules at a time is the best thing to do, once you’ve decided to go the Maven route.  There are two ways of doing this work.  You can take the atomic, all-or-nothing approach; going directly from a monolith to a more modular code base in one fell swoop.  If you can get sign off on this, then this is a wonderful thing.  I’ve had to restrain both myself and others from biting off too much.  What I like to do is pull a few things out at once, maybe three to four modules.  Of those four, let three be low cycling libraries and one a high cycle library.  This way, people learn the new location of the parts that make up your libraries that are combined to make your deployable unit.  Think of it more as an evolutionary process versus a revolutionary process.

Having smaller bite-sized chunks is also a better way to get to know Maven.  If you introduce people to a massive monolith with customizations all over the place with a dozen attached assemblies, then people are going to poke at it with a stick and hate it quickly.  Clearly seeing how a web application goes together and the resulting artifact is created is much more digestible, and you’ll get fewer complaints about your Maven implementation.

Need everything to build always (as it is all always changing)

Another fear that emerges as people start considering modularization is with multiple deployable units, how does anyone know what is compatible with other internal code when the process isn’t always building the same thing all time?  Well, that can be answered a few ways, but the simplest answer is once a library is released (or otherwise frozen) for a deployable unit, then that deployable unit need not upgrade its version of this library.  If shared functionality in the library changes, then you will have to retest, but that begs the question – is your application code in the right module?  Shouldn’t a shared module stay somewhat generic and each deployable unit extend/implement those features instead of baking-in that logic at such a low level?  I’ve found that over time, if you make the library a separate module from the larger deployable unit builds, the code starts migrating in the correct direction versus where ever it’s easiest to add it (no more massive search/replaces in the code base via an IDE).

Confusion with regard to building artifacts

Once everything is pulled out, there may be confusion on the developer’s part with regard to which modules should be built in which order.  This, to me, is an educational thing.  At any point, the developer can run a “mvn dependency:tree” and see:

- What dependencies make up their project
- Where those dependencies were resolved from
- What order they are needed to be built in

When moving from a world where people operate at a very high level directory and build everything to a world where every module is very light weight and each move is a tactical one, people often don’t know how to get that app server up or that daemon running locally. With every application as its own standalone build, people just need to sync what they want to run and rely on a repository manager for the rest (app server bits, database bits, etc).

Shortcuts to repository management

A repository manager is part of the Maven 2 process, end of story.  Trying to use a corporate file share or keeping everyone working in offline mode is just not the Maven way.  Using a repository manager also helps to minimize configuration people will have to manage locally in their settings.xml as well as help enforce the Maven way of life (banning redeploys, pushing releases to one repository and snapshots to another, not deleting artifacts, etc.).  With something like one of the big three (Nexus, Archiva, Artifactory), you simply have a grouped repository everyone points at.  That “grouped” repository is a representation of all the other repositories your company will use.  This way, you can have something like this:

<snip>
<mirrors>
<mirror>
<id>nexus-test</id>
<mirrorOf>*</mirrorOf>
<url>http://server/nexus/url</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus-test</id>
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</snip>

And that’s it.  This one setting covers every remote repository we use – from Codehaus to Repo1.  If you’re really ambitious, although Sonatype doesn’t recommend it, you can even tidy up the url so if you switch repository managers, devs don’t need to touch their settings.xml file.  While this configuration can be rolled into the MAVEN_HOME/conf/settings.xml file, I personally like to keep my configuration maven-version-independent (putting this in my user home directory’s version of settings.xml).

Custom things done in Ant that (is thought) can’t be done in M2

Everyone has one little dark corner of their build world.  Usually it was some quick hack to make things work through Ant.  Possibly a custom task or maybe some shell-out, or something crazier.  These little dark corners should have light shed on them, in fact, flood them with light.  Instead of letting this be a choking point, start by looking at the common repositories for plug-ins that do what you’re looking for.  There are very few problems someone else hasn’t already solved and even if you searched a while back, a solution may exist now that didn’t then.  In the past, I’ve done exhaustive searches and found no plugin that suited my needs.  Then I find some plug-in has changed a few months after to do exactly what I was looking for, or someone wrote one and contributed it back to google/codehaus/repo1.  If that route fails for you, just build a Maven 2 plug-in and deploy it to your local repository.  You can even have a transition period where Maven calls Ant to do just this little bit, then move the Ant tasks inside of Maven 2, then finally migrate to a Maven 2 plug-in.  Don’t use the argument that “you should be writing code, not a Maven 2 plug-in”.  Do you want your system to be robust and clear when there are successes and failures?  Then write the plug-in.  You can start quickly by typing “mvn archetype:generate”, then select “maven-archetype-mojo” (option 12 as of this writing).

Other things to consider when moving to Maven

CI compatibility – some are designed around Maven

The original cruise control’s Maven integration was very poor (I’d say the opensource version is still pretty bad).  It doesn’t understand the different life-cycles or the output from each.  Hudson understands the life-cycles, and will inherently do things depending on what it sees in the build output.  So far in my travels and exploration of various CI servers/tools, Hudson is head and shoulders above the rest with regard to Maven integration.  Have site output you’d like to share?  Maven can publish that quickly with a link off of your project’s page.  You have artifacts you’d like made available to another downstream job (or later process)?  Hudson picks up on those artifacts and tucks them away (maybe/maybe not to your liking).  All other products need to have these various things called out, you need to tell them, “look here for this tar.gz file” versus knowing based upon what Maven has logged.

Lack of understanding of how to upgrade (from one version of Maven to another)

Here’s another big disconnect, you can’t just fling a new version of Maven down like you could with Ant.  With Ant, you could generally look at the release notes, then install and add your custom tasks and then build.  With Maven 2, for the most part, you’re protected from a lot of things, but you also need to watch for plugin versions, core changes to dependency resolution, etc..  I personally sleep better installing locally and building, then diffing against the artifacts that are generated by the build server.  Some changes to Maven (2.0.5 to 2.0.6) required users to review their dependencies for example.

Should you move to Maven 2?

Well, that question is best answered by you, dear reader. If you can modularize your codebase, then you’ll see the biggest improvement both in development time (better throughput) as well in stability – no more broken unittests that when fixed, reveal more broken unittests ultimately convincing all developers to turn them off.  If you can’t (or don’t see any benefit), I’d submit your development team isn’t mature enough to realize the many benefits to a highly modular codebase.  In the end, you have to choose what gets product out the door.

(image via ePublicist)


References
Published at DZone with permission of its author, Julian Simpson. (source)

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

Comments

Ronald Miura replied on Wed, 2010/06/23 - 7:51am

>> Should you move to Maven 2? No, you should move to Maven 3, even if it's still beta :)

Zqudlyba Navis replied on Wed, 2010/06/23 - 7:55am

Maven2 XML hell? No thanks.

We switched from Ant to Gradle - dynamic language DSL based on Groovy.

Much easier to read than XML.  Less noise and clutter.

David Lee replied on Wed, 2010/06/23 - 8:52am

For every compelling reason to use Maven there is an equally compelling reason not to.  Personally, I would not advise any team to move to maven unless the team was completely unable to set their own standards on how to layout and build a project.  Standardization is the main benefit imo.  If you can do it without maven, I would.

Jonathan Fisher replied on Wed, 2010/06/23 - 9:01am

>>Should you move to Maven2? Absolutely, without a doubt, yes. Why? Enforces/Enables good Design. Having a EASY way to group classes by domain in separate jars gives you the power to make hundreds of granular projects and import them without a sweat. Add in the bonus that maven resolves them from your corporate repository automatically, and you've got a 2x winner. Reporting. I haven't found a suite that puts a code test coverage, a checkstyle enforcement, static analysis, copy/paste detector, and more in one place. As a bonus, when those reporting plugins detect an error, they link back to your source xref and documentation. You can't beat this kind of insight into your code! Need to tarball up your build and make a script unix executable (from a windows manchine)? No problem. Need to automatically generate your ejb-client when building an EJB? No problem. Maven, despite it's weakenesses, is probably the best thing that's happened to Java besides spring.... Check it out for yourself, there are at least 1.7x10^9 more reasons!

Yannick Menager replied on Wed, 2010/06/23 - 10:52am

I've tried to move to maven many times over the years.

The *concepts* that underlie maven are good.

The implementation however, is a very voluminous pile of manure.

Pet peeve on top of the list:

Maven build just "break" with time.

It might be the next build, it might be a week later, or even months later... but maven builds just break after a while, I've seen that happen more times than i can count.

That is UNACCEPTABLE

Builds must be *reproducible*. A tool that doesn't provide reproducible builds is useless

And that's only the tip of iceberg, for example, does compiling a simple hello world program really requires downloading god knows how many jars and plugins ? I've wasted more time with maven problems (over maybe a total of 8months of projects using it, over the years) than with ant over a whole decade !

Fundamentally, the problem with maven is one of overall quality.

They should do like the Ant team and put quality and reliability on top of their priorities.

Until such a time, I'll stick with Ant + Ivy (which provides all the benefits of modularization you mentioned above)

John J. Franey replied on Wed, 2010/06/23 - 12:31pm in response to: Yannick Menager

@Yannick:

I read your comment wondering how Ivy can guarantee reproducible builds. I don't know much about Ivy so I browsed its project page and found this comment in its 'Best Practice' section.

Unfortunately Ivy does not by its own allow to have such reproducible builds out of the box, simply because Ivy is a dependency manager, not a build tool.

I think your comment suffers from logical inconsistency. You say ability to reproduce builds is a quality metric. If so, it simply cannot be that Ivy is good quality and maven is 'manure' if both are vulnerable to the problem.

So, I'm still wondering.

Regards, John

Roger Parkinson replied on Wed, 2010/06/23 - 2:55pm in response to: John J. Franey

I think I can help here. Ivy is often (usually I think) used with ant. We use the combination of the two in our builds, with ant handling all the scripting issues and invoking ivy to pull dependencies. The builds are reproducable, especially now that we have a local repository. Before that we were pulling dependencies from the on-line Maven repos (ivy talks to Maven repos just fine) and they were sometimes unstable. That wasn't a Maven issue, though, just a repo issue.

Because we use ivy with ant our projects are segmented into smaller ones. Each project publishes its jar file to our ivy repo, and downstream projects pull their dependencies from there. This way we avoid the one huge code heap problem you mentioned in the article.

Yannick Menager replied on Thu, 2010/06/24 - 3:41am

Yup, like Roger explained, Ivy is not a standalone tool, but rather an "addon" to Ant.

It's specialized in dependency management (and in fact is even compatible with maven's pom, although it's own meta-data format is more powerful and flexible).

It can be used standalone... but I don't think i've never seen or heard of anyone doing so :-)

 

Igor Laera replied on Thu, 2010/06/24 - 6:17am in response to: Yannick Menager

 

How people can say that Maven builds "break" over time, I must always wonder what
they are doing? If everbody in the project is allowed to tinker with maven options and/or
artifact-resolution, you will have problems. It's also not a very intuitive beast, you have
to train, explain the project participants how to use it. Just installing the eclipse plugin without
explaining the concepts behind the applied build management will cause horror breaks
at the most inconvenient times.

The real point of maven2 isn't being a fancy Ant replacement. If you want extensive
code/test-reports, code/style/packaging-checking, pre/post-actions (like instantiating
a large database dump so your automatic tests work), maven takes on the job. Just
drop zillions of plugins on it, and see your code/project gets better with any iteration.

The ongoing IDE integration is a bit of concern, but there are quite remarkable
advancements. Especially when you work on a very large project with 100s of jars
and artifacts (with RELEASE and SNAPSHOT-Versions), you would simply get insane
without maven (and a artifact manager, and an continuous build system). maven3
and e(clipse)4 will be a killer team .)

I'm not against other ways like Gradle, which I find fascinating. But I want to see
several dependent 150kb maven "pom.xml" descriptions with 30 plugins written
in Gradles' "descriptive" manner. Two pages of trivial usecases will always "look
better". But I guess, we have to wait and see heavy lifting examples of Gradle until
anyone can claim "its simpler and clearer" .)

John J. Franey replied on Thu, 2010/06/24 - 8:33am in response to: Yannick Menager

@Yannick @Roger

Ok, cool. That is what I expected.

I still am without an answer to the root of my question. Both Ivy and Maven require careful consideration regarding the source of the dependencies. This consideration is the burden of the build team, not the tool.

My take away is that poor decisions on the source of dependencies (which repo, for example) is not a quality metric of the dependency tool.

Regards,

John

Yannick Menager replied on Sun, 2010/07/11 - 7:05am in response to: Igor Laera

No need to do anything, The problem are the plugins (even the core ones) that change/break/disapear over time.

Unless you to go the hassle of making a clone of the maven repository and managing it yourself, you're exposed to plugin changes breaking your build over time, even if you're using a reasonably basic pom 

If the maven team was extremely careful about quality and release management, that wouldn't be such a big issue, but in my experience that has not being the case.

Michael Eric replied on Wed, 2012/09/26 - 3:38pm

I'd say one of the biggest problems with using Maven is if you don't follow Maven conventions to the letter. The second you start doing things your way you'll bog yourself down in XML hell and cute Maven workarounds (like the Maven Ant plugin) to get things done.

Spend some time to ensure that your projects follow the Maven conventions BEFORE you convert to Maven build scripts and you'll find it a lot easier.

linux archive 

Comment viewing options

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