Automating Maven Releases

Automating maven releases should be pretty straightforward in non-interactive mode. A bug in the release plugin made it impossible in my situation. Every time I would provide the release version(s) as command line arguments, the release plugin would choke on me with the following error message:

Error parsing version, cannot determine next version: Unable to parse the version string

The following shellscript works around this problem, by redirecting input to the maven execution.

Note: I’m releasing a project with a parent and 2 child modules, which is why I have to specify three versions ( + 1 SCM tag). If you’re not using multiple modules, or are using more, you’ll have to adjust the script accordingly.

#!/bin/sh

releaseVersion=AmazingRelease1
nextVersion=AmazingRelease2

mvn \
    release:prepare -P production &>> /tmp/build.log << EOS
$releaseVersion
$releaseVersion
$releaseVersion
$releaseVersion
$nextVersion-SNAPSHOT
$nextVersion-SNAPSHOT
$nextVersion-SNAPSHOT
EOS

mvn release:perform -P production &>> /tmp/build.log

This is an abridged version of our full release script. The full version asks the user to enter the release version once, then releases several versions using different profiles and creates a distribution set with all versions and a bunch of documentation. This works in my situation, but if your release procedure is more complicated then you can just expand on the script :-).

OutOfMemoryError while running Maven Surefire tests

Imagine you have a project which works perfectly fine and well. All tests pass, each and every time. Then one day you commit a couple of new classes with related tests. Of course you ran all tests before committing, and everything worked just fine. Then, a minute or so later, you get a mail from Hudson (or whatever you’re using for CI) saying that there are test failures. “Maybe I forgot a file”, I thought. Checked the test results on Hudson. About a dozen tests were failing, unrelated to anything I touched. Odd. OutOfMemoryErrors all over the place. Most odd. Hudson’s tomcat has 1G, which should be plenty. Same with each build’s MAVEN_OPTS.

Apparently, someone who wrote the Maven Surefire Plugin thought that it would be a GREAT idea to ignore things like MAVEN_OPTS and other memory settings. The plugin seems to start a new JVM instance to run the tests. Without any of the arguments you so carefully selected. No. Apparently you have to explicitly tell the Surefire plugin that maybe, just maybe, it would be a good idea to use the memory settings you already provided elsewhere.

Anyhoo, this fixed it:

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <argLine>-Xmx512m</argLine>
        </configuration>
      </plugin>

DRY, you say? Not so much, eh.

Maven 3 resource filtering weirdness

Maven 3 is all nice and fast(er) and shiny, so I decided to upgrade a Maven 2 project to Maven 3. It (cl)aims to be backwards-compatible, so my consternation was pretty great when my build failed straight away. That’s to say, my tests failed. For some reason, my resources were no longer being filtered. Yup, ${property.keys} weren’t being replaced by values.

This struck me as being somewhat odd, because it worked fine with 2.2.1. A bit of debugging led me to the cause of the problem:

<!-- @Transactional can now be used as well -->

… apparently, the @ symbol is an escape character of sorts.

Considering that blurb on their website doesn’t even qualify as English, I’m not sure if this is a feature or a bug. But whatever. Removing that comment fixed the problem. Whoever came up with that bright idea (especially in an age where @annotations are as rampant as the black plague in the 14th century) probably deserves a spanking.

Howto: soapUI integration tests with Maven

Running soapUI tests with maven is surprisingly easy, all it requires is a few simple steps. This howto will walk you through deploying your web project in an embedded container and running the soapUI tests in the integration test phase.

Cargo configuration

With the cargo plugin you can deploy your project to just about any container. For the sake of simplicity I’ll be using an embedded Jetty 6 container.

<!-- Deploy the project WAR to a built-in container during the integration test phase -->
<build>
[...]
<plugin>
	<groupId>org.codehaus.cargo</groupId>
	<artifactId>cargo-maven2-plugin</artifactId>
	<executions>
		<!--Start the container in the pre-integration-test phase -->
		<execution>
			<id>start-container</id>
			<phase>pre-integration-test</phase>
			<goals>
				<goal>start</goal>
			</goals>
		</execution>
		<!-- Stop the container after integration tests are done -->
		<execution>
			<id>stop-container</id>
			<phase>post-integration-test</phase>
			<goals>
				<goal>stop</goal>
			</goals>
		</execution>
	</executions>
	<configuration>
		<wait>false</wait> <!-- We want to deploy, run tests and exit, not wait -->
		<container>
			<containerId>jetty6x</containerId>
			<type>embedded</type>
		</container>
		<configuration>
			<properties>
				<cargo.servlet.port>${my.project.port}</cargo.servlet.port>
			</properties>
		</configuration>
	</configuration>
</plugin>
[...]
</build>

soapUI project configuration

If you haven’t already created a SOAP UI test suite, now’s the time to do so. Once this is done, copy the test suite to your test resources folder (src/test/resources). Set up your project to filter resources.

<build>
[...]
	<testResources>
		<testResource>
			<filtering>true</filtering>
			<directory>src/test/resources</directory>
		</testResource>
	</testResources>
[...]
</build>

With that out of the way, you can now edit the soapUI project file with your favourite XML editor. What you want to do is replace all endpoint references (and possibly WSDL locations) by property keys. So <con:endpoint>http://localhost:8080/MyProject/endpoint</con:endpoint> becomes <con:endpoint>${my.project.endpoint}</con:endpoint>.
Your webapp will be deployed to http://localhost:${my.project.port}/${project.artifactId}-${project.version}, so I suggest using that as a property value.

<project | profile>
[...]
<properties> 
	<my.project.port>8888</my.project.port>
	<my.project.endpoint>http://localhost:${my.project.port}/MyProject/endpoint</my.project.endpoint>
</properties>
[...]
</project | profile>

soapUI plugin configuration

First, add the eviware soapUI maven repository to your list of repositories.

<pluginRepositories>
	<pluginRepository>
		<id>eviwarePluginRepository</id>
		<url>http://www.eviware.com/repository/maven2/</url>
	</pluginRepository>
</pluginRepositories>

Then, add the plugin to your build and let maven know when you want to execute it. Considering the container is starting up before the integration test phase, and is shutting down afterwards, running the tests as integration tests seems like the best option ;-).

<!-- Run SOAP UI tests during the integration phase. -->
<plugin>
	<groupId>eviware</groupId>
	<artifactId>maven-soapui-plugin</artifactId>
	<version>2.5.1</version>
	<configuration>
		<junitReport>yes</junitReport>
		<exportAll>yes</exportAll>
		<projectFile>target/test-classes/soapui-project.xml</projectFile>
		<outputFolder>target/soapui-reports</outputFolder>
	</configuration>
	<executions>
		<execution>
			<id>wsn-server-test</id>
			<phase>integration-test</phase>
			<goals>
				<goal>test</goal>
			</goals>
		</execution>
	</executions>
</plugin>

All done!

Now when you run maven verify (or install, or ..) your SOAP UI tests will automagically be executed and you’ll be informed of any failures.

Maven sucks?

Kent Spillner certainly seems to think so. I disagree with the conclusion, but I find myself agreeing with a lot of the points he makes. It’s true that maven builds aren’t always consistent across different platforms or even maven versions. It’s also true that your pom.xml file can grow rather large and complicated if you want to get maven to do interesting things. And it’s definitely very true that maven dependency management can be hair-pullingly-complicated and is essentially broken. Sure.

But saying that writing your own build manager is better? Advocating ant and rake? Seriously? Maven does a lot more than just build your project. It does reporting, site generation, eclipse project generation and pretty much anything else you can think of. The convenience of the thing is worth a lot. It’s definitely worth having to struggle with the POM every once in a while. And to be honest, the POM syntax isn’t much more horrible than ant’s or rake’s.

As for platform/version inconsistencies: if you can’t force the people on your team to use the same software, then your problems probably run a lot deeper than just build management. Software has bugs, this includes maven as well. If you’ve hit a particular bug that causes your build to go kaboom, then fixing it sounds like the way to go.

If you have the time to write a build manager for every project you work on, be my guest. I for one don’t, and maven has actually served me pretty well so far.