Skip to main content

Writing your pom files in Groovy - a sneek preview of Maven 3's polyglot features

Posted by johnsmart on October 21, 2009 at 11:04 AM PDT

Maven 3 is promising to be the most significant upgrade since the release of Maven 2. While maintaining backward compatibility with existing Maven 2 projects, it introduces a number of powerful and compelling new features, such as a complete rewrite of the internal architecture, OSGi support and multi-language pom files. In this article, I will be giving a preview of this last feature.

One exciting new feature in Maven 3 is it's ability to work with pom files written in non-XML notations. The Maven core now provides an underlying DSL to access the Maven internals, and write POM files in the language of your choice. This currently includes scripting languages like Groovy, Ruby, and others. In short, you will be able to write a DSL for virtually any scripting language you like that can hook into the Maven internals and pilot the Maven build process.

This article focuses on the Groovy support - writing your POM files in Groovy.

With Maven 3, you can use a Groovy DSL that maps directly to the XML pom format. So, instead of:

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

you could write:

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

 

Let's take a closer look. A handy way to start is to use the translator tool, which lets you translate an existing pom.xml file into:

$ translator pom.xml pom.groovy

 

This generates a Groovy transcription of your pom file, which looks and feels just like a traditional pom file, except in Groovy. Here is a simple one:

project {
modelVersion '4.0.0'
parent {
artifactId 'babble'
groupId 'com.sonatype.training'
version '1.0.6-SNAPSHOT'
}
artifactId 'babble-core'
version '1.0.6-SNAPSHOT'
name 'babble-core'
url 'http://maven.apache.org'
build {
testResources {
testResource {
filtering 'true'
directory 'src/test/resources'
}
}
}
dependencies {
dependency {
groupId 'junit'
artifactId 'junit'
version '4.7'
scope 'test'
}
}
profiles {
profile {
id 'development'
properties {
'log4j.level' 'DEBUG'
}
}
profile {
id 'production'
properties {
'log4j.level' 'WARN'
}
}
}
properties {
'log4j.level' 'info'
}
}

If you're familiar with the XML pom files, this will read pretty easily - it's essentially an XML pom file without the noise generated by the XML tags. Although it's an obvious improvement, some of the transcribed Groovy DSL code might still seem a bit wordy to some. For example, a set of project dependencies might look like this:

    dependencies {
dependency {
groupId 'junit'
artifactId 'junit'
version '4.7'
scope 'test'
}
dependency {
groupId 'org.hamcrest'
artifactId 'hamcrest-all'
version '1.1'
}
dependency {
groupId 'log4j'
artifactId 'log4j'
version '1.2.12'
}
}

However, you can make this more concise simply by using semi-colons to separate the dependency elements:

    dependencies {
dependency { groupId 'junit'; artifactId 'junit'; version '4.7'; scope 'test' }
dependency { groupId 'org.hamcrest'; artifactId 'hamcrest-all'; version '1.1' }
dependency { groupId 'log4j'; artifactId 'log4j'; version '1.2.12' }
}

This is certainly more concise and more readable, and goes with the general tendancy of moving away from XML as a build scripting language in favour of more lightweight notations. But the real power of this is that it is effectively an interface to the Maven 3 core, that gives you full access to all of the Maven features. The Maven 3 core is rock solid, and you can leverage all the existing features and plugins from the Maven 2 ecosphere.

Maven 3 is supposed to be fully backward-compatible with your existing Maven 2 projects, with the exception, I believe, of a few fairly rare corner cases. I tested Maven 3 against a few large real-world projects (including a couple of gnarly ones), and indeed everything seemed to work just fine. I've also converted the pom.xml files into Groovy equivalents and run the builds successfully. Performance is good - I didn't notice any real difference between using an XML pom file and a Groovy one.

I've just scratched the surface of Maven 3 Groovy support, but hopefully this will give you some idea of what it's all about. In the coming weeks, I'll write about some of the other new features in Maven 3.

Related Topics >>

Comments

is there tool support for Groovy?

last time I was forced to use groovy, we were in the textpad ear, a full year looking my own mistakes without any IDE support. How is it today ? is it better?

I prefer to write thousand lines of XML with fully support from an IDE and 5 lines of blind text.. but, if the IDEs are already supporting Groovy, I will give it a second try.. :)

* IMHO: less characters in this scenario is the most useless-marketing-speech ever.. :) The only argument I believe fair for adopting Grovvy is: "I like grovvy, that's why!" :)

Groovy & Maven

Yes, there is much better IDE support for Groovy (and Ruby) these days. Intellij Idea is excellent, and I think NetBeans and Eclipse have support too.

I think a benefit of using Groovy or JRuby over XML is that (I presume) you can use those languages to simplify the POM file in ways other than just replacing XML. That is, one could write methods for repeating patterns that simplify the code considerably, and then just call them for all the relevant elements.

If you had a library of these functions, then the verbosity and complexity could be encapsulated there, and the POM file itself could be made trivial. (At least that's my guess.)

- Keith

Wouldn't it be nice to make

Wouldn't it be nice to make it even more concise to define dependencies. I'm thinking of shorter/more convenient way to define the classifier. What about something like this: dependency { 'junit', 'junit', '4.7'; [scope 'test'] } or dependency { 'junit:junit:4.7'; scope 'test' } ?

What happened to POM attributes?

Last year there was a proposal by Don Brown to shorten POMs by using attributes. So to reuse your example, [dependency] [groupId]junit[/groupId] [artifactId]junit[/artifactId] [version]4.5[/version] [scope]test[/scope] [/dependency] would have become this: [dependency groupId="junit" artifactId="junit" version="4.5" scope="test" /] which is a great deal shorter and can still be validated through an XML schema. What happened to this proposal? I don't see how moving to Groovy would be better than this. Cheers, GB

I like attributes too

Not sure where this is at, but from what I understand of the new Maven 3 architecture, everything is normalized internally to the standard XML pom structure, but you can (or will be able to) write new POM notations very easily, that then map internally to the canonical form. So a version of the pom file that uses attributes doesn't sound too hard, compared to writing a DSL for Groovy, Ruby and YAML (all of which exist already in various forms of maturity).

can I execute any groovy scripts or is just a syntactic sugar ?

Hi John, does this new feature makes Maven really flexible (that is - can I execute any groovy scripts now ?) or is it just a syntactic sugar ? If it is only a DSL version of XML, than it won't make Maven any better. BTW. the code snippets you posted are rather hard to read - my Firefox 3.5.3 shows them as one looooooooooong line. -- best regards Tomek Kaczanowski http://kaczanowscy.pl/tomek

Syntactic sugar?

Thanks for the comments on the formatting - should be fixed now :-). So far I have been experimenting with using the Groovy notation essentially as a more concise transcription of the pom.xml file format - I'll do further posts on how it handles Groovy snippets. That said, even in Maven 2 it's pretty easy to integrate snipplets of Groovy code at various points in the Maven lifecycle, using the gmaven plugin, though it is arguably way too verbose for it's own good. I expect as the new DSLs evolve this will become easier and hopefully less wordy.

flexibility is the key - and it is Maven's weak point

Hi John, I agree with one thing - the formatting is fixed. :) As for the rest... no offense, but it is like I heard myself from few months ago :) Closed in the Maven-thinking-box and being able only what Maven allows me to see. That is were I was, for sure, and that is where I suspect you to be right now (sorry if it sounds harsh). Thinking in terms of Maven lifecycle and plugins - both extremely limiting (but you can't see it if you use it for few years like I did, and know many nice tricks that gives you illusion of control over the build process) and not flexible at all. Well, anyway, there are other build tools, much more powerful and flexible - see you there soon. :) -- best regards Tomek

Formatting

Appears to be some issues with the formatting of XML and Groovy code in this post.