Unconstant Conjunction A personal blog

Logic in Maven Archetypes

Time for a real first post. Recently, I’ve been working on creating a Maven archetype for a certain open-source project, and discovered to my delight that archetypes actually support a limited kind of logic. If it’s not immediately obvious why that would be useful, consider that you can make use of this logic to, for example, optionally add a dependency based on a custom parameter.

Making use of the fact that Maven builds its archetypes using Apache’s Velocity template engine, you can embed statements reminiscent of C-style preprocessor directives in any file in the archetype. To add an optional dependency, try embedding the logic below in the pom.xml file

<dependencies>
	...
#if (${includeNetty} == 'true' || ${includeNetty} == 'yes' || ${includeNetty} == 'y')
	<dependency>
		<groupId>io.netty</groupId>
		<artifactId>netty</artifactId>
		<version>3.4.6.Final</version>
		<scope>compile</scope>
	</dependency>
#end
</dependencies>

This will work provided, of course, that you’ve defined includeNetty like so in your archetype-metadata.xml file.

<requiredProperties>
    <requiredProperty key="includeNetty"> 
     	<defaultValue>false</defaultValue>
    </requiredProperty> 
</requiredProperties>

The above snippet becomes

<dependencies>
	...
	<dependency>
		<groupId>io.netty</groupId>
		<artifactId>netty</artifactId>
		<version>3.4.6.Final</version>
		<scope>compile</scope>
	</dependency>
</dependencies>

when -DincludeNetty is set to true (or yes, or y, in keeping with Maven-style commands), and

<dependencies>
	...
</dependencies>

when it is false (or, really, anything but true, yes, or y). Unfortunately, this trick doesn’t work to optionally include whole files – there isn’t currently a way to do that at all in Maven, although the feature has been suggested.

Avoid leading whitespace

Just a tip: when embedding these preprocessing commands, don’t put any whitespace before the # character, otherwise it will be included in the output. This snippet

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<currentYear>2013</currentYear>
	#if (${includeNetty} == "true")
	<nettyVersion>3.4.6.Final</nettyVersion>
	#end	
<properties>

harmless though it looks, will actually output

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<currentYear>2013</currentYear>
		<nettyVersion>3.4.6.Final</nettyVersion>
	<properties>

due to the leading whitespace, which can be extremely annoying if you actually care about nicely formatted pom.xml files.

comments powered by Disqus