You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Krzysztof Mackowiak (JIRA)" <ji...@apache.org> on 2014/12/30 14:59:13 UTC

[jira] [Created] (CAMEL-8200) Race condition in JmsProducer for request/response messaging causing nondeterministic setting body to null.

Krzysztof Mackowiak created CAMEL-8200:
------------------------------------------

             Summary: Race condition in JmsProducer for request/response messaging causing nondeterministic setting body to null.
                 Key: CAMEL-8200
                 URL: https://issues.apache.org/jira/browse/CAMEL-8200
             Project: Camel
          Issue Type: Bug
          Components: camel-jms
    Affects Versions: 2.14.0
            Reporter: Krzysztof Mackowiak


In my team we have noticed that there is a race condition problem in JmsProducer class for request/response messaging. It causes that sometimes (nondeterministically) body of a response message is changed to null. It can happen when JMS response is received very fast (we use in-memory ActiveMQ with VM transport and no persistence) under heavy load.

It looks that there is a problem in JmsProducer class in processInOut(exchange, callback) method.

{code}
    protected boolean processInOut(final Exchange exchange, final AsyncCallback callback) {
        …
        doSend(true, destinationName, destination, messageCreator, messageSentCallback);
        // after sending then set the OUT message id to the JMSMessageID so its identical
        setMessageId(exchange);
        // continue routing asynchronously (reply will be processed async when its received)
        return false;
    }

...
    protected void setMessageId(Exchange exchange) {
        if (exchange.hasOut()) {
            JmsMessage out = exchange.getOut(JmsMessage.class);
            try {
                if (out != null && out.getJmsMessage() != null) {
                    out.setMessageId(out.getJmsMessage().getJMSMessageID());
                }
            } catch (JMSException e) {
                LOG.warn("Unable to retrieve JMSMessageID from outgoing JMS Message and set it into Camel's MessageId", e);
            }
        }
    }
{code}

The problem is caused by invoking setMessageId(...) method after doSend(...). Method doSend(...) is sending JMS request message and causes that another thread is used to handle JMS reply message. This leads to a situation that 2 different threads can operate on the same exchange (which is not synchronized at all) at the same time:
1) original thread in which processInOut(...) method was called,
2) separate thread from JMS component for handling JMS response.

In our case there it was happening sometimes that setMessageId(...) was invoked at the same time as PipelineHelper.createNextMessage(exchange) method:
{code}
    public static Exchange createNextExchange(Exchange previousExchange) {
        Exchange answer = previousExchange;
        // now lets set the input of the next exchange to the output of the
        // previous message if it is not null
        if (answer.hasOut()) {
            answer.setIn(answer.getOut());
            answer.setOut(null);
        }
        return answer;
    }
{code}
It caused that body of response message was lost (set to null).


It looks for me that calling setMessageId(...) at the end of processInOut(...) method is redundant and this logic should be executed when JMS reply message is handled.

I've attached a patch where invokation of setMessageId(...) is removed.
I've checked that it doesn't break any test for camel-jms component.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)