2014-04-09

Arquillian: Wait until message has been processed by MessageDriven Bean using JMX

I have the following scenario:


There is a queue called AllotmentQueue which is read by a (here not shown Message Driven Bean) which reads the message and calls the AllotmentUpdateService. The AllotmentUpdateService parses the XML message and calls the AllotmentService to update the Allotments in the database. I am using WildFly 8.0.0.Final as Application Server. I would like to test all this using Arquillian. I will write a message to the Queue and the call the AllotmentService and verify that all data has been inserted correctly:

This is the logic to write the message:
Now I would like to check the result:
Those tests do not work reliably. The reason is that the processing happens asynchronously, see the yellow arrows in this picture.


A work around would be to wait for a while (Thread.sleep), but this is not very elegant, since I never know how long the processing will be, because some files are huge and some not, additionally the performance of each machine varies. So sleeping for a long time will solve the problem, but my tests will run a very long time.

A much better solution is to check the content of the queue using JMX. First I need to know the ObjectName of the MBean, that controls the AllotmentQueue. I can find it using jvisualvm and connect to the running WildFly:


In my case the ObjectName is



There are some attributes in the MBean that can tell us details about the queue:


The attribute deliveringCount tells us, how many messages are currently in delivery. So after publishing the message, deliveringCount will be 1 and when the processing has finished it will be 0 again. So we will extend the test to check the MBean before and after publishing the message:


First we need to read the value of deliveringCount using JMX. Here is a private method for that:
This code is not optimized for performance, but this is ok, because it is in the testing code. Now as first step, we will check that deliveringCount is 0:

The @InSequence(1) will ensure that this method is called before all other methods with an @InSequence greater that 1. The publishing method will be @InSequence(2):
Now we need to wait until the message has been processed:

We will fail after 20 seconds, this value can be adjusted if it is not sufficient. But we will never wait longer the required. Theoretically there might be a racing condition, the we will check instantly that deliveringCount is 0 before it actually jumps to 1, but this has not happened to me before. In this case we could wait for maybe 1000ms at the beginning of the method (Yes, asynchronous is asynchronous).

Finally we will do the actual business logic tests. Note that @InSequence is 10, meaning that they will run after the 3, but in no particular order, which is ok for those tests:
As a final result, all tests run and the test does not need longer than the pure execution time:


This solution should work with all Application Servers and standalone JMS implementations as long as they provide this information via JMX.