A blog mainly about Java

Your tests assume that JBoss is up and running

As a Java EE developer I tend to mix unit tests with integrations tests, usually using Arquillian. But sometimes, for obscure reasons, Arquillian cannot do the job (let’s say the packaging of the application to test is too obscur). So I want to deploy my application, and then, execute some tests. But what I really want is my tests to be executed if and only if the web application is deployed, if not, the tests are skipped. In other words, I want my Jenkins to automatically fail if there is no JBoss. For that I can use the JBoss HTTP management API and the JUnit assumptions.

Use Case

Let’s say I have a Java EE application with a simple HTML page (index.html), a servlet (MyServlet.java) and a REST endpoint (MyRESTEndpoint.java). Once packaged in a WAR (sampleJavaEEJBossUtil.war) and deployed on JBoss, I want to check all the different URLs and HTTP response code (i.e. is the servlet deployed and running, is the REST endpoint up and running…).

I execute the test while the application is deployed and JBoss is up and running, and the test is green. As you can imagine, if I shutdown JBoss or undeploy the application, the test fail. In this case, what I really want, is to ignore the test.

JBoss Admin CLI

So let’s say the web application is deployed, JBoss is up and running, everything is fine… let’s check all that with the JBoss CLI. You will find this command line interface under $JBOSS_HOME/bin/jboss-cli.sh. When you execute it, you connect to JBoss and enter a few commands to get the status of the server and other components (i.e. datasource, JMS factories…). The following commands check that JBoss is up and running and also that our sampleJavaEEJBossUtil.war is deployed:

JBoss Admin REST API

On top of the command line interface, JBoss also has a REST interface for administration. So all the commands you type on CLI have an HTTP equivalent. So to know if JBoss is up and running and if the sampleJavaEEJBossUtil.war is deployed we can just go to a browser and type the following URLs:

Notice that the JBoss administration APIs are under http://localhost:9990/management. Then, it’s just a matter of passing certain paths (e.g. deployment) or query parameters (e.g. operation=attribute)). If you type these URLs in a browser, you will also notice that you need to login as an administrator (first you need to create a user/password with the $JBOSS_HOME/bin/add-user.sh utility).

JBoss Administration APIs need DIGEST Authentication

So what if you don’t want to use a browser but instead use the JAX-RS 2.0 client API to connect to it? Let’s first use curl to see what it tells us.

As you can see, when using DIGEST authentication, the output is much more verbose and the outcome is a return code 200 (instead of just 401). So now we have the two important ingredients to access the API with REST : we know how the URLs look like, and we know we need to use DIGEST authentication. So let’s see how to do it.

But unfortunately, this won’t work because it will return a 401 (Unauthorized). We need to authenticate using the DIGEST scheme. How do we do that in JAX-RS 2.0? Well, we can’t :o( The only trick I found (thanks to Bill Burke and Arun Gupta) is using the Apache HTTP Client and an extension of RESTEasy. So in the code below, the getClient method returns an authenticated HttpClient which is then used to access the JBoss administration REST APIs.

Here, I’ve simplified the code (no exception handling) and I’m only showing the method isJBossUpAndRunning. But you can check the full JBossUtil class on GitHub, I’ve created other methods.

The Test Class

Coming back to our use case, we now have all the pieces of the puzzle. We know how to check that JBoss is up and running (we could even check that the web application is actually deployed) and we can use the JUnit Assumptions. The following test will only be executed if and only if JBoss is up and running. If not, the test will automatically be ignored, thanks to the Assume API.

Conclusion

Unit testing is important, but when you execute your code within a container, integration tests are also very useful. Arquillian solves most of the problems and simplifies integration testing, but other technics can also be used. The main ambition of our build system is to pass all the tests… or ignore some. With JUnit assumptions and some REST APIs, our tests can be knowledgeable and executed only if the container is up and running, if the web application is deployed, or if the datasource is actually enabled. Download the code, give it a try, and let me know what you think.