I am writing a test that uses some client side logic and some server side logic. In the client side, I make a REST call to some webservice which manipulates the data and stores it in a JMS queue. I later make a JMS call to see what was written to the JMS topic, and am getting some surprising results.
Here is the interesting portion of the test code that defines this issue:
@Test
@OperateOnDeployment("my-deployable")
public void testMessageInTopic() throws Exception {
// make a rest call with the minimal request
makeRequest(getMyXmlAsString());
// compare the message with the one sent to the topic
connection = factory.createConnection();
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
final MessageConsumer consumer = session.createConsumer(topic);
connection.start();
System.out.println("### listening for a response");
final TextMessage receivedMessage = (TextMessage) consumer.receive();
final String expectedString = "sampleFromTest"
final String receivedText = receivedMessage.getText();
System.out.println("### got this message " + receivedText);
assertEquals("the message in the received topic is the same", expectedString, receivedText);
System.out.println("#### the message was as expected");
}
The makeRequest(final String data) method does the following:
public makeRequest(final String data) {
final String url = getAppEndpoint("http://localhost:8080/doit");
final ClientRequest req= new ClientRequest(url);
req.header(HttpHeaderNames.CONTENT_TYPE, MediaType.TEXT_PLAIN);
req.body(MediaType.TEXT_PLAIN, data);
response = req.post(MyResponse.class);
}
When observing the logs, here are the messages I get in order:
09:38:59,448 INFO [stdout] (pool-2-thread-1) ### got this message sampleFromTest
09:38:59,448 INFO [stdout] (pool-2-thread-1) #### the message was as expected
09:38:59,488 INFO [stdout] (pool-2-thread-2) ### listening for a response
It's obvious that embedded tests and client side tests combined do not play nice, as threading becomes an issue. I can potentially circumvent this issue by making the rest call in my @Before test method, or by injecting the webservice and programmatically hitting it with a request. However, as my interest lies in testing the full integration path, mixing client and server requests seems like a good idea. My question is then, is it possible to run a scenario where we make a client side request and parse data received by the container?
Turns out that I was getting this discrepancy because I was calling the jms receive() method without adding an explicit wait. Hence, the above output was correct:
09:38:59,448 INFO [stdout] (pool-2-thread-1) ### got this message sampleFromTest
09:38:59,448 INFO [stdout] (pool-2-thread-1) #### the message was as expected
09:38:59,488 INFO [stdout] (pool-2-thread-2) ### listening for a response
To solve my issue, I did something like this to add an explicit, synchronous wait before executing more code:
final TextMessage message = (TextMessage) consumer.receive(15000);
This way, after a message is written, I wait for up to 15 sec for it to trickle back down. While I could never prove that
### listening for a response
never occurred before
09:38:59,448
in the original issue, applying this approach indeed solves the problem.