Should you move to Maven 2?
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)
(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
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
Jonathan Fisher replied on Wed, 2010/06/23 - 9:01am
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
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.
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
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