Home > Java > Maven doesn’t suck, your POM does

Maven doesn’t suck, your POM does

Maven bashing is an all-time favorite: there are plenty of articles telling how Maven downloads the whole Internet, or how POMs are bloated and so on.

While I agree that Maven could be perfected, I’m also aware that some (if not most) of its shortcomings are not intrinsic but are caused by (very) bad configuration. Worse, even if used correctly in your projects, problems sometimes come from third-party dependencies! You do not believe me? Well, two examples follow, from standard libraries.

Log4J

Coming from the classic logging framework, this may seem a surprise but log4j POM is a mess. Just look at its dependencies section:


  
    javax.mail
    mail
    1.4
  
  
    javax.jms
    jms
    1.1
  
  ...

Interestingly enough, Log4J depends on the Java Mail and JMS API! If you are using your application in an application server, you may be in for a rude surprise as conflicts may arise between your dependencies and the libraries available on the server.

Moreover, while some users may have the need of mail or JMS appenders, this is not the case for all of us. As such, there’s clearly a lack of appropriate modularization in the design of the library. Luckily, the above POM is an excerpt of version 1.2.15. Version 1.2.16 uses the optional tag for those libraries (which breaks transitivity): it addresses our application server use-case but is still a problem for those needing the dependencies as they have to add the dependency manually. See here for a thought or two on optional dependencies.

If we need version 1.2.15, there are basically two solutions.

  • Clean but cumbersome: we have to manually exclude JMS and Mail from each POM using Log4J. Who said software development was fun?
  • Gruesome but effective: if we have a Maven enterprise repository, we correct the POM (i.e. we add optional tags) on the repository.

Jasper reports

The Log4J example was straightforward: just the side-effects of bad modularization. Jasper’s POM has another twist, just look at a typical dependency:


  com.lowagie
  itext
  [1.02b,)
  compile

The version part means the dependency’s version should be between 1.02b included and the latest version. This obviously has two drawbacks:

  • From an architectural point of view, how can the POM provider guarantee there won’t be an API break with the latest version?
  • From a Maven POV, it means Maven will try to download the latest version. In order to do that, it will try to contact repo1… You’re beginning to see the problem? If you’re behing a corporate proxy that isolates you from the Internet, you’re toast.

The POM excerpt comes from version 2.0.4. Starting from version 2.0.5, Jasper’s designers used only single version dependencies.

If you’re stuck with older versions, the only solution here is to replace the POM with a manually crafted one that do not use unboundedversion dependencies on your enterprise repository.

Conclusion

Despite the constant noise on the Internet, Maven is a wonderful tool. Yet, even if I take the utmost care to design my POM, some external dependencies make my life harder. It would be better to stop losing time complaining about the tool and invest this time helping the developers of those dependencies to provide better POMs.

email
Send to Kindle
Categories: Java Tags:
  1. Christophe Vigouroux
    October 10th, 2011 at 08:25 | #1

    Hi Nicolas,

    For your problem involving Maven trying to contact repo1 to find the lastest artifact version and you being behind a proxy or using a custom repository, you can by example declare in settings.xml the following:

    nexus
    my corporate repository
    *
    http://my-corporate-repo/nexus/content/groups/public

    Maven now contacts you own repository instead of repo1 (tested and approved on our private network not connected at all to internet but using our own nexus repo)… There is of course the drawback that this needs that each developper adds those lines to their settings.xml. And I don’t know if this works well with a filesystem repository ?

  2. Christophe Vigouroux
    October 10th, 2011 at 08:30 | #2

    Ok… WordPress doesn’t htmlencode automatically it just erases xml tags… So here is the configuration snippet again:

    <mirrors>
    <mirror>
    <id>nexus</id>
    <name>my corporate repository</name>
    <mirrorOf>*</mirrorOf>
    <url>http://my-corporate-repo/nexus/content/groups/public</url&gt;
    </mirror>
    </mirrors>

  1. No trackbacks yet.