Thursday, December 15, 2011

Maven2 → Maven3 migration - real life example

Couple of months after JDK 7 release I decided to update my projects to build on both new JDK and Maven3 (Maven2 previously). From JDK 7 I was expecting nothing new as the codebase of our projects should be migrated step by step as soon as the Ops start supporting new application servers that could run on Java 7. More important things were expected from Maven3, namely we wanted to shorten build time, that we already optimized by 20% using Maven2 by smart initialization of our unit tests (but that's another story). In this post I will explain what I had to change to make this happen.

Status quo ante

Our projects have pretty standard build options, no homemade plugins or execution paths, etc. Just couple of standard plugins with standard configuration.

During each build of multi-project Maven setup, Jenkins (currently 1.422) runs additionally CheckStyle, Cobertura and FindBugs plugins. CheckStyle and Cobertura are actually run twice, once during package to see if nobody wrote any crap, and second time during reports generation.

After the reports are generated everything travels to our projects website (run on Tomcat) via WebDAV protocol (oh, yeah! good old WebDAV).

Every time someone commits a change Jenkins runs mvn -e --batch-mode clean package site-deploy and we're all happy.

First run

Ok, let's change to Maven3 now. It should be easy. This is what I thought - "just change MAVEN_HOME and run the same stuff i.e. mvn ...". Well, ... it worked but besides couple of warnings it did not finish successfully.

Warnings, first (they are easy): Maven3 does not like if you don't provide version with plugin group and artifact ID, so this was my first change. I found all newest stable versions of plugins we use and added <version> tag everywhere.

Warnings disappeared but I still had errors. CheckStyle and Cobertura plugins were reporting style and coverage errors. It means that plugins were not configured correctly because they were executed but they did not load our settings.

Main problem was that in our pom.xml we defined that we want to use plugins within:

  
  ...
  

section but the configuration was set in <reporting> section.
This caused Maven3 not to read plugin setup during the build - and as I mentioned before we do check the style and code coverage during the build, not only during the report generation.

Fixing the build for Maven3

In Maven3 if you want to have some specific configuration to be take in to account during the build you have to put it in the <build> section. If you want the same config to be take into account during report generation you have to copy-paste it into <reporting> section, simple.

Cobertura plugin and Maven3
The biggest change had to be applied to Cobertura. In my Maven2 pom.xml we had:

  
    package
    
      clean
      check
    
  

and it had to be changed to: (not valid, see errata)

  
    clean
    clean
    
      clean
    
  
  
    package
    package
    
      instrument
      check
    
  

but... it did not solve all of the issues...

Cobertura plugin v2.5.1 bug in Maven3
(not valid, see errata
Cobertura plugin has some problems with Maven3 that were not present in Maven2 - check my bug report in Cobertura Maven Plugin JIRA site: MCOBERTURA-155
I provided a patch with workaround that works for me.

After all of these changes I was able to run mvn clean package Yeah!

Maven3 = site-deploy 3.0

Another warning I saw during the build was Maven3 asking to use maven-site-plugin version 3.x. Let's start with the fact that I had to add the following in the <build><plugins> section:

  org.apache.maven.plugins
  maven-site-plugin
  3.0

I had some problems generating the site but they seem to disappeared automagically so I will ignore them.

Maven3 = No WebDAV support

In each of our pom.xml we have the following:

  
    artifactory.internal
    Internal Release Repository
    dav:http://${artifactory}/libs-releases/
  
  
    website
    dav:${project.url}
  

Everything is ok but note the protocol i.e. dav:. It is not supported out-of-the-box in Maven3, so you have to add and extension in the <build> section:

    
      org.apache.maven.wagon
      wagon-webdav-jackrabbit
      2.1
    
  

Side-effect changes

As a side effect I updated Jenkins CI to the newest version 1.422, and also Artifactory to version 2.4.2.

Was it worth?

I spent one whole day on this migration but it was worth IMHO. For all the migrated projects we saw build time saving from 25% up to 45% (!!!) depending on the size of the project (of course, you may notice different figures).

Before the change our projects were built using JDK 1.6.0_23 and Maven 2.2.1, after the change we use JDK 1.7.0_1 and Maven 3.0.3.

I'm pretty happy with the change, and you?

2 comments:

gpcmol said...

I also changed from Maven 2 to 3. I also installed Java 7.
I faced one problem. The combination Windows 7, Java 7 and Maven 3.0.3 didn't work. Downloading artifacts from the Maven repository got stuck.
After a long search on Internet i discoverd that Java 7 and Maven 3 can result in this problem. I nnstalled Java 6 and it worked.

Przemysław Bielicki said...

hi,

it's neither Java 7 nor Maven 3 problem - it's Windows and it can be easily worked around: http://blog.bielu.com/2011/11/hotspot-64bit-server-hangs-on-socket.html

cheers