Two Spring/Hibernate gotchas that got me

Earlier this week I got caught out by two Spring/Hibernate features. One of my service layer methods threw a checked exception after a bit of relatively complex validation, just like I intended. What happened next, however, was not expected. My test failed. Well, it didn’t fail, it died with an error and a horrible stack trace of doom. Hibernate was kind enough to tell me that a batch update failed. This struck me as slightly odd, considering the fact that an exception was thrown long before any saving was meant to occur.

I had, apparently, forgotten about the rather unintuitive automagic dirty checking and subsequent saving. In my rather humble opinion, it’s a feature that should be disabled by default, but that’s not the point here. I had been made aware of the feature in the past, but had somehow completely forgotten about it. Fine, no worries, I can live with it, I’ll just roll back my transaction.

However! My test still shouldn’t have failed, or so I thought. After all, I had Spring transaction support set up for all my service calls, and surely an exception will cause the transaction to roll back? Wrong. By default, transactions are only rolled back for Unchecked exceptions, not for checked exceptions. I can’t for the life of me fathom what the reasoning behind this decision might be, but there you have it. It’s well document in the Spring transaction documentation, but again I had completely forgotten about it.

A simple bit of config fixed the problem:

<tx:method name="*" rollback-for="java.lang.Throwable"/>

So please, don’t be like me. Don’t get caught out by these features! Unless you’re looking for a couple of hours of entertainment, that is :-).

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.

Howto: PostgreSQL data source in JDeveloper/OC4J

Today I had to create a postgres connection pool in JDeveloper’s embedded oc4j container. JDeveloper being the horrible piece of software that it is, and its documentation being rather lacking, this took a lot longer than it should have. The pretty GUI wizards aren’t able to pull it off either — these measly conjurers really aren’t worthy of the name.

The biggest hurdly was postgres’ connection pool not being happy with just a jdbc URL. Instead it expects a hostname, port number and database name. These things are all in the jdbc url, but never mind, that would’ve been too simple. After reading through the XSD for data-sources.xml, I realised that there’s an option to provide custom properties to the factory. Quite simple really. A connection pool definition looks something like this:

<connection-pool name="myPool" disable-server-connection-pooling="false">
	<connection-factory
		factory-class="org.postgresql.jdbc3.Jdbc3PoolingDataSource"
		user="postgres" password="1234"
		url="jdbc:postgresql://localhost:5432/db">
		<property name="serverName" value="localhost" />
		<property name="portNumber" value="5432" />
		<property name="databaseName" value="db" />
	</connection-factory>
</connection-pool>
<managed-data-source name="dataSource" jndi-name="jdbc/postgresDS" connection-pool-name="myPool" />

Once this is done, all that’s left to do is place the postgres driver JAR in the j2ee/home/applib folder in your JDeveloper folder. If you don’t place it there, you’ll get very nice class not found errors.

That’s it. Not very hard at all!