... and I thought it would be a good idea to setup an integration test of some EJBs we are creating in a new project. Actually, it was not, since it nearly ruined my evening. But eventually I got it to work, and here is how.
To test the EJBs, I need to create an EAR file, deploy that to the application server (JBoss 5.1.0 in our case) and run JUnit test cases against this server. For Maven, I have setup a separate
integration-test module for executing the integration test for the following reasons:
- to better separate unit tests (with JUnit) from integration tests (also with JUnit), which simplifies Maven configuration a bit.
- to be able to run this module outside of the normal CI (continuous integration) build due to its lack of performance.
Cargo Maven Plugin
For automatically starting the container, deploying the EAR file and stopping the container when the tests are finished, I use the Cargo Maven plugin. I did this several times before (with Tomcat, though) – so I thought that'd be easy...
Well, when using JBoss, there are some tricks you have to know. Before going into the details, some more information on Cargo.
A Container is the base concept in Cargo. It represents an existing application server runtime, and Cargo hides all the details of the actual server implementation for you. There are two types of containers:
- Local Container: this is executing on the machine where Cargo runs. This can either be an Installed Container which is, well, installed on the local machine and is run in a separate VM, or an Embedded Container that is executing in the same JVM where Cargo is running (currently only supported for Jetty).
- Remote Container: a container that is already running anywhere (local or remote). It's not under Cargo's control and can't be started or stopped by Cargo.
You use a Configuration to specify how the container is configured (logging, data sources, location where to put the deployables, etc). The available configuration depends on the container type:
- Local Configuration: for local containers. There are two local configuration types: Standalone Local Configuration which configures the container from scratch in a directory of your choice, and Existing Local Configuration that re-uses an existing container installation already residing on your hard drive.
- Runtime Configuration: You use a runtime configuration when you want to access your container as a black box through a remote protocol (JMX, etc). This is perfect for remote containers.
In my case, I wanted to use a Local Installed Container with a Standalone Local Configuration, to eliminate dependencies from other deployments.
JBoss with Cargo
Well, and here are the pitfalls when using JBoss in this setting:
- Experimental: JBoss 5.x is still an experimental container for Cargo. This is a bit strange given the fact that this version is now out for a while, but fortunately not really an issue.
- Extensive Logging: When Cargo builds the JBoss configuration – remember, I use Standalone Local Configuration so Cargo creates one from scratch – it uses a logging setup (independantly from what is used with your JBoss installation!) that is way too chatty. The console scrolls forever, and things are slowing down in a way that you think everything is stuck in an infinite loop.
Thus, you have to tell Cargo to use another logging configuration file, which is a bit tricky and not documented very well (see this issue).
- Shutdown Port: Now the container starts up, the tests are run, but after that JBoss AS is not shutting down. It's telling me
javax.naming.CommunicationException: Could not obtain connection to any of these urls: localhost:1299, which means the wrong port is used for shutdown. Standard shutdown port is 1099, so we have to tell Cargo to use that port number.
All in all, the configuration now looks like this. Mentioned settings are highlighted. Perhaps this is useful for someone else...
<!-- *** Cargo plugin: start/stop JBoss application server and deploy the ear
file before/after integration tests *** -->
<!-- Container configuration -->
<!-- Configuration to use with the Container -->
<!-- Override logging created by Cargo (which is way to chatty) with default
file from JBoss (see http://jira.codehaus.org/browse/CARGO-585) -->
<!-- before integration tests are run: start server -->
<!-- after integration tests are run: stop server -->