March 19, 2009

Maven Profiles: Activation... or not

I love Maven. Really, I do. I should say that since this is my first post in my own blog (I know, I'm probably the last man on the planet... ;o) Having said this, here is another annoyance. There are lots of them, inside and outside of Maven, and I'm going to share some of my experiences here.

This time, it's about Profiles. I'm not going to explain the basics (see Introduction to Build Profiles or the chapter on profiles in Maven: The Definitive Guide, for instance).

I wanted to use profiles to specify some re-usable configuration (for code generation out of oAW models, but that doesn't matter) in a parent POM, without having to repeat all the stuff in child POMs. The profile definition in parent POM consists of a plugin configuration along with required dependencies and looks like this:

<profile>
<id>adsl</id>
<build>
<plugins>
<plugin>
<groupId>org.fornax.toolsupport</groupId>
<artifactId>fornax-oaw-m2-plugin</artifactId>
... all the execution and configuration details ...
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.fja.ipl.adsl</groupId>
<artifactId>adsl</artifactId>
<version>${ipl.current.version}</version>
</dependency>
... and some more ...
</dependencies>
</profile>

Then I tried to activate the profile in those child POMs that should use it since they are based on an oAW model. Note that I wanted to activate the profile in the POM itself, not throug settingings or command line options. And this is where the pain begins...

First attempt was to just activate the profile in a child POM like this:

<profile>
<id>adsl</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>

However, instead of activating the inherited profile with the given id, Maven just overrides the profile from parent POM with a new (and empty) one. Okay, this might be the desired behaviour.

So, next attempt was to use the activation on a present file: whenever there is a workflow file src/main/resources/generateAll.oaw, the profile should be active. This is obvious, since oAW generation uses this workflow file anyways. Parent POM now looks like this:

<profile>
<id>adsl</id>
<activation>
<file>
<exists>src/main/resources/generateAll.oaw</exists>
</file>
</activation>

...
</profile>

This works great... almost. When dealing with multi-module projects, it depends on from where you start the Maven build. For instance, let's assume project P aggregates modules M1 and M2. When you step down to M1 and start Maven, the file can be found in context of M1 and the profile is activated, so everything is just fine. Same is true for M2. However, when the build is started for project P, the file is searched in P's context where it can be found and hence the build of M1 and M2 fails.

Sounds not that complicated... let's just use the ${basedir} property:

<exists>${basedir}/src/main/resources/generateAll.oaw</exists>

Well, it appears that this property is not expanded at all (see MNG-1775). Thus, this doesn't work either.

So, we're stuck. I don't have any other idea (do you?)...

This might not be the typical use case for profiles, which are meant to modify the POM at build time to support environment/platform specifics. Agreed. However, as long as there is no other way of defining complex configuration in parent POM that should be reused in some (not all) child POMs, this would have been a useful approach, IMHO.

Now, we end up in defining the plugin configuration in <pluginManagement> section and to enable it and add required dependencies in child POMs. That is, we have to repeat the following section in every single child project that want to harness oAW generation:

<build>
<plugins>
<plugin>
<groupId>org.fornax.toolsupport</groupId>
<artifactId>fornax-oaw-m2-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.fja.ipl.adsl</groupId>
<artifactId>adsl</artifactId>
<version>${ipl.current.version}</version>
</dependency>
... and more of them ...
</dependencies>

Cumbersome, redundant, hard to maintain. Maven should do better, really!

1 comment:

  1. While I'm a bit late, it's no less valuable of a find. I was trying use a parent pom to to standardize build configuration across several repositories by project type (pom vs library vs web app vs archetype ...).

    I had hoped to activate profiles from the parent by setting properties in the pom files of the children but property based profile activation is based on system properties and not effective Maven properties :( . Using hidden empty files is not a bad compromise and seems to to be working so far.

    ReplyDelete