DevOps Zone is brought to you in partnership with:

Kief is a software delivery consultant with ThoughtWorks in London, specializing in tools, practices, and processes for the continuous delivery of software. Kief is a DZone MVB and is not an employee of DZone and has posted 19 posts at DZone. You can read more from them at their website. View Full User Profile

Maven: great idea, poor implementation (Part 3)

01.09.2012
| 11398 views |
  • submit to reddit

In the first post in this series, I explained why I think Maven Maven is a good idea. Most projects need pretty much the same thing from a build system, but using Ant normally results in complex, non-standard build system which becomes a headache to maintain.

In theory, Maven should be a better way to run a build. By offering a standardised build out of the box, you would massively reduce the setup and learning curve for new joiners to the development team and take advantage of a healthy ecosystem of plugins that can be simply dropped into your build, and save loads of setup and maintenance hassle.

End of the Road sign

Although its goes pretty far towards the first two of these advantages, in my second post I described how Maven's configuration is too complex even for simple things.

I note that the Maven site doesn't currently mention "convention over configuration", although I'm sure it used to in the past, and there are plenty of references to it around the web. The Wikipedia entry for convention over configuration lists Maven as a poster-child, and Sonatype, the commercial company supporting Maven, names a chapter of their reference book named after the concept.

But it's a load of bollocks.

Anyway.

My final point (for this series, anyway) is on flexibility. The tradeoff between configuration complexity is normally flexibility. This is certainly the case with Ant; the complexity which makes every Ant-based build system a painfully unique snowflake buys you the capability to do damn near anything you want with it.

But Maven's complexity does not buy us flexibility.

My team wants to divide up its testing into multiple phases, following the "Agile testing pyramid" concept as mentioned by Mike Cohn.

So we'd like to have four layers to our pyramid, unit tests running first; database integration tests running next; web service tests third; and only if all of these pass do we run web UI tests. These test groups run in order of increasing heaviness, so we get feedback on the simple stuff quickly.

Maven supports two levels of testing, unit tests and integration tests. The failsafe plugin which provides integration testing support seems fairly new, and is actually pretty good if you only need one phase of integration testing. It lets you configure setup and teardown activities, so you can fire up an app server before running tests, and make sure it gets shut down afterwards.

If we could get failsafe to run three times during the build, each time carrying out different setup and teardown activities, and running different groups of tests, my team would be fairly happy with Maven.

It is possible to use build profiles to set up different integration tests in this way, but to get them to run, you need to run the build three times, and each time the preceding steps will be re-run - compiling, unit tests, packaging, etc. So it's kind of nasty, brutish, and too long.

The right way to achieve what we're after is probably to customise the build lifecycle, or create a new build lifecyle. Either way, it involves creating custom plugins, or extensions, or both. I've taken a stab at working out how, but after burning a couple of evenings without getting anywhere, I've shelved it.

I have no doubt it can be done, but it's just easier to do it in Ant and move on to other tasks. And that's pretty much the bottom line for me. I still like the idea of Maven, I have hopes it will continue to improve (it's a thousand times more usable than it was a few years ago), and maybe even go through a shift to embrace convention over configuration for real.

In the meantime, I'm likely to reach for Maven when I need something quickly for a project that seems likely to fit its paradigm, but for heavier projects (most of the ones I'm involved with for client projects), Ant is the pragmatic choice.

Part 1 and Part 2 are here.

Source:  http://kief.com/maven-inflexibility.html
Published at DZone with permission of Kief Morris, author and DZone MVB.

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

Tags:

Comments

Thomas Eichberger replied on Mon, 2012/01/09 - 3:00am

Well, I've been using Gradle for a while, because I dont like Maven, and it is really great. In an article it was called build tool of the future:-)

Jilles Van Gurp replied on Mon, 2012/01/09 - 3:27am

This mirrors my experience exactly. As a tech lead, I get to maintain builds of projects I inherited. Invariably these builds are flaky in multiple ways:

1) copy paste reuse. Rather than figuring out how stuff works, people copy snippets all over the place. This leads to incorrect behavior, redundancy, and sometimes it actually works. The root cause for this is that maven is too hard for most developers and copy paste reuse apparently gets the job done for most.

2) dependency mismanagement. Both plugin versions and dependency versions tend to be copied all over the place as well. As maven evolves, your build becomes more and more obsolete. Maven is all about the illusion of dependency management without actually providing it. Yes, you do have the means to fix it but that is so hard that I've seen few people bother besides myself. In reality, there is little advantage over having a directory of stuff that needs to be on the classpath with a simple wild card. In both cases you end up with obsolete/unneeded/potentially harmful dependencies.

3) Repetitive to the point where it drives me nuts. It seems that unless I add shitload of crap to my command lines, maven does the wrong things by default: download the world (again), re-compile already compiled code, re-run tests that ran just fine on source code that hasn't changed, etc. Maven is a huge timewaster. Compare how fast your IDE does things (maven integration disabled) to how long you have to wait for stuff to compile manually.

4) A lot of plugins people depend on come with their own conventions for configuring and plenty of weirdness. All of this is magnified by documentation that is hard to read, poorly structured and doesn't cover the less trivial aspects. On top of that, there seem to be multiple plugins for the same job: it seems people can't agree on either conventions or how to do stuff. Choice is fine, but it adds a lot of complexity.

Andrew Spencer replied on Mon, 2012/01/09 - 6:58am in response to: Jilles Van Gurp

Jilles,

I sympathise with the problems of bad POM authorship, especially copy-paste and dodgy dependencies. This is partly laziness on the part of developers and I think it's unfair to blame it all on Maven (I mean, I've seen plenty of bad Java code, but that doesn't mean I shouldn't code in Java myself) . 

The dependency mess, though, is also caused by bad practices by library providers who often don't take care declaring their own dependencies.  The plugin configuration mess... well, it's mostly a lack of standardisation, but I'm not sure how it can be improved given that most of these plugins are not produced by the Maven project itself.  And the verbosity, that's entirely Maven's responsibility.

What I'm interested in learning is, what would a build tool look like that kept the good points of Maven, but improved on the bad ones?

Erwin Mueller replied on Mon, 2012/01/09 - 7:32am

I think you exaggerate things a lot. The "bloat" is not really confusing, it's XML, you can quickly skip over the not relevant tags. The locking of the plugin versions is a good thing, so that way your build will not break.

If you are using maven right, i.e. make use of parent poms and dependency management, it's very simple actually. I have a global parent pom where I manage all the versions of plugins and libraries, it's 512 lines long.Than I have more specialized global poms, for example for a Groovy build. All in one place and good tested, so the actual project pom file is very minimal.

For example, a project that will compile, test and build an application with an installer, deploy it to various servers, etc. contains only  a few lines of XML. Because with maven I can use parent pom, so I can put everything there and don't have to write it every time for each project.

For a cooperate environment Maven should be very good. Just declare all used libraries and plugins in a global parent pom and let each project inherit the configuration. That way, you have all the configuration in one place and all the developers can follow the cooperate policy.

John Dobie replied on Mon, 2012/01/09 - 7:34am

Hi Kief.
I totally agree about Maven needing support for multiple phases, especially when you have continuous builds.
You can work around it like this.
http://johndobie.blogspot.com/2011/06/seperating-maven-unit-integration-tests.html
But you shouldn't have to. Hopefully this will be fixed soon.
Nice articles.
John.

Mileta Cekovic replied on Mon, 2012/01/09 - 9:28am

That is exactly why we use Maven only for commit builds and ad-hoc analysis/reports:

- Pull the source from source control

- Generate sources, compile, compile unit tests, run unit tests

- Create artefacts, install in the remote repository

- THE END OF COMMIT BUILD

- Create docs, analysis, reports, etc with add-hoc goals still using Maven (this is actually better done by Maven then Ant)

- THE END OF MAVEN BUILD, PLEASE SWITCH TO ANT (with Maven Ant tasks :)) !

- Do component tests

- Deploy to integration environment, do integration tests

- Deploy to additional environment, do acceptane and/or performance tests

- Etc...

 

This seems to get the best of both tools, unless Maven build phases are made more scriptable and controlable.

 

Robert StJohn replied on Mon, 2012/01/09 - 10:24am

This is a nice post. I agree with a lot of what you wrote. The configuration can quickly become heavy and ugly, which is in part, I think, a symptom of being an XML syntax. One thing to consider about managing plugin versions, however, is that specifying a plugin version yields the desirable effect of repeatable builds. This can be especially relevant when using a complex build plugin such as Jetty. Suppose, for instance, your production deployment uses Jetty 7.0. You would not want Maven automatically pulling the latest 8.X Jetty to run your integration tests, would you? That being said, adding plugins to a POM, or configuring anything outside the box can be extremely painful.

Nathan Dolan replied on Mon, 2012/01/09 - 10:26am

Interesting post. Personally, I've seen plenty of successful projects that have adopted Maven, saved tons of time and reduced build complexity. It's by no means perfect but for me compared to hand-cranking bespoke build scripts its a no-brainer.

I'm confused about your assertion that Maven doesn't embrace convention over configuration (you put it a bit stronger than that!)

As you've pointed out, it dictates conventions on project folder structure, default behaviour in defined build phases, component management and versioning. I fail to see how this is not promoting convention over configuration. Obviously there will be some projects that fit the mould better than others: those not so well suited will require more configuration, those badly suited shouldn't use it. Its not "convention instead of configuration" - as with most things, if it ticks most your boxes you follow the convention then configure as required.

There are ways around your problem, but your answer appears to be to configure everything using Ant, which stipulates almost no conventions whatsoever. Maven is extensible - suggest writing a plugin/extension yourself for what you want to achieve, rather than hand-cranking. This will obviously require an investment in time to learn how to do it. And this of course is the price of CoC - its only really effective if the convention in question matches your requirements.

Jilles Van Gurp replied on Mon, 2012/01/09 - 1:57pm in response to: Andrew Spencer

Andrew,

 The reason I blame it on Maven, at least partially, is because it is a fairly consistent pattern of abuse. Even when it works properly, you still end up with tons of xml few people fully grasp. It's a problem inherent to the design and complexity of maven.

I don't buy the argument of "if everybody else would do the right thing than maven would be fine". The whole problem is that they won't and never will. This is not a perfect world. Technology that assumes it is (aka the closed world assumption) is inherently as broken as the assumption.

In my view an improvement would be to simplify the dependency management and restrict it to the actual software you are building. Managing build plugin dependencies is a bad idea. As for software dependencies, this needs to be centralized: especially for multi module projects (aka non trivial projects that actually require a build tool). Ant has a much more sane approach of stuff that comes with ant (which carries the same version and has been through the same QA process) and stuff that developers add to and by means of putting it on the classpath.

Then, configuration needs to be optional. That means in my book that a standard java program should just compile, build, test, jar, deploy, etc without a build file. Comply with the conventions: you don't need to do anything. Also, conventions need to be shareable between projects. A lack of a usable and understandable ability to share is what leads people to copy and paste. Using inheritance for this was always a bad idea.

Finally, almost no project ends up being a standard one. Scripting non standard parts needs to be easy. Sometimes a simple bash script just does the job. Build tools should get out of the way when needed and not put up barriers.

Jack Jackson replied on Mon, 2012/01/09 - 3:54pm

As a long-time Ant user (at least since 2003) working with Maven I usually try to get the best of both worlds by binding a lot of maven-antrun-plugin invocations to the various build phases, as soon as I cannot solve a task in a few minutes of googling. Being it packaging resources with build numbers, skinny jars that should be possible with maven-assembly-plugin but just do not work as they should, or multiple test stages. I know I lose flexibility (like cobertura cannot track my tests) but I can try to fix it when I start using it :D  

 Yes, it clutters up the buildfile, but still nothing against alone the dependency hackery (either get binaries or source for some of the dependencies) that used to be in my Ant build files :)

 

Fabrizio Giudici replied on Mon, 2012/01/09 - 4:25pm

 

Well, splitting a not really long post in three parts doesn't look a good idea... in any case I'm going to comment only here.

Honestly, I'm a bit tired of still reading posts about how Maven is bad and see the very same, old, list of problems that can be fixed by using a couple of good practices, mainly the superpom. Seems that people start using Maven for a few days, doesn't look around enough, and then blog the same things over and over.

Very quickly: "locking the version of a plugin" is not a problem, is instead a good practice, otherwise you can't have repeatable builds. Do you figure it out what happens if you try to rebuild your project from a tagged commit of 6 months ago if in the meantime a number of plugins have been updated? So, you have to explicitly declare the versions of every plugin that you use. Not by chance Maven warns that in future this practice will be mandatory and if we have to criticize it is because they didn't it from the beginning.

Second: every long configuration stuff must go in the superpom, using properties for configurability. To change the Java version in all of my projects I only have to set two properties. I also have complex configurations for Vaadin, Jetty, AspectJ, Android, the NetBeans Platform, whatever, in my superpom and hardly need to have another plugin configuration section in any of my JEE, JSE, Vaadin, Android, NetBeans Platform projects. My customers using my superpom share the same benefits and their POMs are very small as well.  All our projects thus share the same structures, conventions, release cycles and so on. 


Copypasting a POM? Sure, people not skilled with Maven tend to do that, but in general people not skilled with a technology tend to misuse it. It's the project leader responsibility to explain best practices and teaching them.

Sivaprasadreddy... replied on Tue, 2012/01/10 - 12:28am

Hi,
Its not the problem with Maven, its very common pattern in IT world.
Whenever a new technology/tool comes in, people starts using it and post their wow movements with that technology and use it to its full extent. After few years we will read "This XXX tool sucks" or "This ABCD tool is a nightmare" kind of posts about the same technology/tool.

You want examples?
Struts: The most successful framework in java and the most criticized framework too after few years.
Spring: Almost all (not everyone) people liked Spring for its simplicity, ease of use, DI, templates etc in the beginning. You can read lotttt of "I Love Spring" kind of articles from Spring fans(including me). Recently people started blaming Spring too. Nowadays you can read "Spring is bloated", "Spring XML sucks", "Moving from Spring to JEE", "Why do we need Spring when JEE6 is there" kind of articles.
Ant: This is the default build tool for java projects. Now people are saying Ant is verbose etc etc. If Ant is not good how come it became default build tool for all java projects.

"I strongly agree that everyone has a right to express their opinions and opinions might change over time".

So I feel that its not the problem with Maven or Ant...Its a trend :-), we will read same kind of articles on Gradle too in near future :-).

Actually its a good thing to happen. People will know about good as well as bad things about the popular tools/frameworks.

Mladen Girazovski replied on Tue, 2012/01/10 - 5:08am

*yawn*

same old same old...

A Developer who has been working with Framework A (Ant in this case) for 10 years has troubles with Framework B (Maven) and prefers Framework A... must be the fault of Framework B, right?

Don't get me wrong,  Maven has its quirks and complexity, but it is manageable, i find Maven to be a great tool for building projects, i prefer it always to having to script my builds.

Most of the problems mentioned in the series don't even come up if you stick to best pratices, the others are manageable, one "problem"sounds like the ancient "Attributes vs. Elements" XML debatte.

 

Andrew Spencer replied on Fri, 2012/01/13 - 9:00am in response to: Jilles Van Gurp

Jilles,

I can't really disagree with what you wrote (except one thing, see below).  I am tempted to say, as others have done, "Yes, but you don't get any of these problems if you use Maven properly."  But I can't, because it reminds me too much of what defenders of Clearcase say.  

The points about managing plugin dependencies, and about the need to make scripting easy, are well taken.

I do think Maven has done more good than harm compared with what there was before.  But I also have on my todo list to take a look at Gradle and at SBT.

The one thing I disagree with: a "standard" Java project will build under Maven, not quite without a POM, but at least with a POM containing only its identifiers and a list of dependencies - and I don't know where we can get those from, if not from a build file.

Jilles Van Gurp replied on Wed, 2012/01/18 - 4:56pm

Andrew, standard java for me includes web applications for which you probably want to fire up a app server, run tests against that, etc. I find that that generally requires a lot of copy pasting of e.g. surefire, jetty or cargo setup, and other cruft. Just doing standard stuff like this, you easily end up with a few hundred lines of very verbose but bog standard configuration.

Eclipse: right click, run as web application

Maven: write a few hundred lines of pom file, mvn clean install

Andrew Spencer replied on Mon, 2012/01/23 - 6:38am in response to: Jilles Van Gurp

Hi Jilles,

OK, I was thinking "compile and package" rather than "build".  Old habits die hard.

The appropriate way to do it in Maven is to define all that boilerplate in a super POM that can be inherited by every standard java webapp.  Then the Maven version is: inherit from super POM, mvn clean install.

So I think your criticism is partly unfair, and partly justified.  It's unfair insofar as Java webapps can be done simply with Maven (after all, using a super POM is hardly rocket science). 

On the other hand, it's a justified criticism insofar as Maven leaves the developer far too much latitude to do it badly. It's also justified in that Eclipse provides all that functionality off the shelf, whereas Maven doesn't provide a useful mechanism for providing/sharing shrinkwrapped POM configurations (the inheritance mechanism is too unwieldy).

Comment viewing options

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