Search code examples
requestactivemq-classicresponsemule

Mule Jms Request-Response in Topics


For a project I have to use a request-response pattern on an ActiveMQ Topic, I know it is not a good practice to answer to a topic but unfortunately I have to. My problem is that if I use the exchange-pattern="request-response" attribute at the jms:output-endpoint (to publish the request message) the message is published twice! So the subscriber get the message twice and also send his response twice.

With the request-response Router it works (this means the message is only send once). But I would like to use a automatically generated temporary topic, so I would rather like to use the exchange-pattern="request-response" than the request-response Router.

Is there a reason why the output-endpoint sends the message twice? If there is no other possibility as to use the request-response Router, is it possible to generate a temporary topic there?

I made a short program with a publisher (mule.componentA) and the subscriber (mule.componentB) where the message is send twice:

<jms:activemq-connector brokerURL="tcp://localhost:61616" name="JMS_Connector" doc:name="Active MQ" specification="1.1" validateConnections="true" />

<flow doc:name="mule.componentA" name="mule.componentA">
    <http:inbound-endpoint host="localhost" port="8081" doc:name="HTTP" exchange-pattern="one-way" path="componentA" />
    <set-payload value="hello" doc:name="Set Payload"/>
    <logger message="componentA send: parameter: #[message.payload]" level="INFO" doc:name="Logger"/>
    <jms:outbound-endpoint connector-ref="JMS_Connector" doc:name="JMS"  exchange-pattern="request-response" topic="topic.test"/>
    <logger message="componentA received. message: #[message.payload]" level="INFO" doc:name="Logger" />
</flow>

<flow doc:name="mule.componentB" name="mule.componentB">
<jms:inbound-endpoint connector-ref="JMS_Connector" doc:name="JMS" exchange-pattern="one-way" topic="topic.test"/>
    <logger message="componentB received. message: #[message.payload]" level="INFO" doc:name="Logger" />
    <set-payload value="world" doc:name="Set Payload"/>
    <logger message="componentB send: message: #[message.payload]" level="INFO" doc:name="Logger"/>
</flow>

The http:inbound-endpoint is the trigger to start the flow. I tried it with firefox and curl, but there were no different.

The output is:

INFO 2014-01-21 16:12:29,760 [[request_response].mule.componentA.stage1.02] org.mule.api.processor.LoggerMessageProcessor: componentA send: parameter: hello 
INFO 2014-01-21 16:12:29,761 [[request_response].mule.componentA.stage1.02] org.mule.transport.service.DefaultTransportServiceDescriptor: Loading default outbound transformer: org.mule.transport.jms.transformers.ObjectToJMSMessage 
INFO 2014-01-21 16:12:29,762 [[request_response].mule.componentA.stage1.02] org.mule.transport.service.DefaultTransportServiceDescriptor: Loading default response transformer: org.mule.transport.jms.transformers.ObjectToJMSMessage 
WARN 2014-01-21 16:12:29,762 [[request_response].mule.componentA.stage1.02] com.mulesoft.mule.transport.jms.EeJmsMessageDispatcher: Starting patched JmsMessageReceiver 
INFO 2014-01-21 16:12:29,762 [[request_response].mule.componentA.stage1.02] org.mule.lifecycle.AbstractLifecycleManager: Initialising: 'JMS_Connector.dispatcher.191522199'. Object is: EeJmsMessageDispatcher 
INFO 2014-01-21 16:12:29,762 [[request_response].mule.componentA.stage1.02] org.mule.lifecycle.AbstractLifecycleManager: Starting: 'JMS_Connector.dispatcher.191522199'. Object is: EeJmsMessageDispatcher 
INFO 2014-01-21 16:12:29,822 [[request_response].mule.componentB.stage1.02] org.mule.api.processor.LoggerMessageProcessor: componentB received. message: hello 
INFO 2014-01-21 16:12:29,823 [[request_response].mule.componentB.stage1.02] org.mule.api.processor.LoggerMessageProcessor: componentB send: message: world 
INFO 2014-01-21 16:12:29,826 [[request_response].mule.componentB.stage1.02] org.mule.transport.service.DefaultTransportServiceDescriptor: Loading default outbound transformer: org.mule.transport.jms.transformers.ObjectToJMSMessage 
INFO 2014-01-21 16:12:29,828 [[request_response].mule.componentB.stage1.03] org.mule.api.processor.LoggerMessageProcessor: componentB received. message: hello 
INFO 2014-01-21 16:12:29,829 [[request_response].mule.componentB.stage1.03] org.mule.api.processor.LoggerMessageProcessor: componentB send: message: world 
INFO 2014-01-21 16:12:29,830 [[request_response].mule.componentB.stage1.03] org.mule.transport.service.DefaultTransportServiceDescriptor: Loading default outbound transformer: org.mule.transport.jms.transformers.ObjectToJMSMessage 
INFO 2014-01-21 16:12:29,832 [[request_response].mule.componentB.stage1.02] org.mule.transport.jms.JmsReplyToHandler: Reply Message sent to: temp-topic://ID:philipps-mbp-62486-1390317145516-1:1:1 with correlationID:ID:philipps-mbp-62486-1390317145516-1:1:3:1:1 
INFO 2014-01-21 16:12:29,833 [[request_response].mule.componentB.stage1.03] org.mule.transport.jms.JmsReplyToHandler: Reply Message sent to: temp-topic://ID:philipps-mbp-62486-1390317145516-1:1:1 with correlationID:ID:philipps-mbp-62486-1390317145516-1:1:3:1:2 
INFO 2014-01-21 16:12:29,837 [[request_response].mule.componentA.stage1.02] org.mule.api.processor.LoggerMessageProcessor: componentA received. message: world

Solution

  • I would say it's probably ActiveMQ trying to ensure the message is received by subscribers. I don't quite get what you are trying to achieve here. If you are publishing something to a JMS topic, you are usually broadcasting a message to several receivers, and here you trying to do point-to-point messaging. If you can not use a JMS queue with request-response exchange-pattern instead, I would suggest you to use a topic with one-way exchange-pattern, and then add a third flow/topic to receive messages from componentB and put your response handling logic there.