John is an experienced consultant specialising in Enterprise Java, Web Development, and Open Source technologies, currently based in Sydney, Australia. Well known in the Java community for his many published articles, and as author of Java Power Tools and Jenkins: The Definitive Guide, and founder of the open source Thucydides Automated Acceptance Test Library project, John helps organisations to optimize their Java development processes and infrastructures and provides training and mentoring in agile development, automated testing practices, continuous integration and delivery, and open source technologies in general. John is the CEO of Wakaleo Consulting, and runs several Training Courses on open source Java development tools and best practices. John is a DZone MVB and is not an employee of DZone and has posted 125 posts at DZone. You can read more from them at their website. View Full User Profile

More Groovy Magic with Maven pom Files

11.02.2009
| 10106 views |
  • submit to reddit

Last time, I introduced some of the new Groovy support available in Maven 3, and looked at how you will be able to write your pom files in Groovy, or in other non-XML notations. In this article, we'll take a further look at what you can do with a Maven pom file written in Groovy.

Jason Dillon, the guy who brought us GMaven, has been working hard on extending the Groovy pom scripting features, and is coming up with some great new capabilities. In the last article, we saw how the Groovy DSL makes dependencies more concise, with dependency declarations along the following lines:

    dependencies {
dependency { groupId 'junit'; artifactId 'junit'; version '4.7'; scope 'test' }
}

In fact, you can do even better than this. A short-hand notation for dependencies lets you define dependencies in a single line. So

<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.5</version>
      <scope>test</scope>
    </dependency

becomes:

    dependency('junit:junit:4.5:test')

This also works for the project parent, plugins, modules and many other elements. For example, you could write the following:

project {
parent('tweeter:co.nz.codingdojo.tweeter:1.0.0-SNAPSHOT')
...
}

This shorthand notation also works with dependency exclusions. Here is a real-world example from the graven project itself:

dependencies {
dependency('org.codehaus.groovy:groovy:1.7-beta-2') {
exclusions('junit:junit', 'org.apache.ant:ant', 'org.apache.ant:ant-launcher')
}
}

Here is a more complete example, showing this notation in action in the parent element, as well as in dependencies and plugins:

project(modelVersion: '4.0.0') {
parent('tweeter:co.nz.codingdojo.tweeter:1.0.0-SNAPSHOT')
artifactId 'tweeter-web'
packaging 'war'
name 'Tweeter Web Application'

dependencies {
dependency('javax.servlet:jstl:1.2')
dependency('junit:junit:4.7:test')
}

build {
plugins {
plugin('org.mortbay.jetty:maven-jetty-plugin:6.1.21') {
configuration {
port '9090'
scanIntervalSeconds '5'
stopPort '9966'
stopKey 'foo'
}
executions {
execution(id: 'start-jetty', phase: 'pre-integration-test') {
goals('run')
configuration {
scanIntervalSeconds '0'
daemon 'true'
}
}
}
}
}
}
}

You can also bind Groovy scriptlets to different phases in the lifecycle with a minimum of fuss. For example, you will be able to integrate Groovy code directly at different points in the lifecycle. At this stage, the syntax uses the $execute macro, and looks something like this:
project {
build {
$execute(id: 'test1', phase: 'validate') {
println "foo"
}

$execute(id: 'test2', phase: 'compile') {
println "bar"
}
...
}
Within the Groovy closure, you will be able to access the usual pom variable such as $project and $settings, as you can with GMaven.

You can also use Groovy in the pom file itself, to make the pom file itself more dynamic and concise. For example, in this example (taken from the graven pom file), the project modules are defined in a central list, and used both in the dependency management section (to avoid duplicating the version number for each module) and in the modules element:

project {
...
def mods = ['pmaven-common','pmaven-cli','pmaven-maven-plugin',
'pmaven-groovy','pmaven-yaml','pmaven-jruby']
...
dependencyManagement {
dependencies {
mods.each { artifact ->
dependency {
groupId 'org.sonatype.pmaven'
artifactId "$artifact"
version '1.0-SNAPSHOT'
}
}
}
...
modules(*mods)
}

This really is the best of both worlds. If you need flexibility, you can add Groovy scripting to do most anything you want. However it remains within the structure of the Maven build lifecycle. We are not going back to Ant-like anarchy of build scripts built up of arbitrary targets and task dependencies: 'mvn verify', for example, will still do what you expect it to do.

Some readers seemed concerned that this would just add another notation to learn, and rightly so! Keeping your code maintainable is an essential part of good development practices! However, this is not a totally new formalism - this is more a transcription of the XML pom format with a few fairly intuitive short-cuts. For anyone familiar with Groovy and Maven, a pom file written in Groovy is very easy to read and understand indeed.

 

Indeed, under the hood, the pom files are converted to the canonical XML pom format that we all know and love. When an artifact is deployed to a Maven repository (be it a local one, or the official central repository), the Pom file will be in the standard, canonical XML format. The support for multi-language pom files is clearly intended to make your live easier within your organization writing and maintaining pom files in a format that suits you - not to turn the central repository into a Tower of Babel.

Regarding tool support, the standard m2eclipse integration will work fine with any POM file format, as m2eclipse uses the canonical XML format under the hood. However, Groovy support in Eclipse being what it is, the pom editor will probably take a while before you get all of the nice auto-completion features you currently get with the XML format. Nevertheless, for a groovy-savvy developer, this new pom format is a great step forward.

 

From http://weblogs.java.net/blog/johnsmart

Published at DZone with permission of John Ferguson Smart, 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.)