2

There is one request queue and the reply queues are created by the client server instances and pinned to each instance rather than using temporary queues.

The use case needs to get an inbound jms message and then send that message to an asynchronous process. Once the async reply messsage is received from the service I need to take those results and reply back to the original message's jmsReplyTo. The Jms gateway would not work in this instance AFAIK>

I am using a jms message driven channel adapter for the message in with a series of channels and service activators to handle the out of process calls and async replies. I am trying to use the DynamicDestinationResolver to no avail. Additionally I have tried to set the outbound destination address programatically but could not figure out a good way to do this.

This seems like a common pattern but I could not find a good example for a completely disconnected async request response. Disconnected meaning that the usual async jms request reply did not seem to fit the need.

Context Config:

<!-- Input from Amq -->

<amq:queue id="requestQueue" physicalName="${request.queue}" />

<int-jms:message-driven-channel-adapter id="jmsIn"
                                    connection-factory="jmsConnectionFactory"
                                    destination="requestQueue"
                                    channel="queueRequestChannel" concurrent-consumers="5" />

<int:channel id="queueRequestChannel" />

<int:service-activator input-channel="queueRequestChannel" ref="switchMessageHandler" method="processSwitchMessage"
        output-channel="cardNetworkOutChannel"/>

<!-- Output to Card Network-->
<int:channel id="cardNetworkOutChannel" />

<!--<int:service-activator input-channel="cardNetworkOutChannel" ref="cardNetworkHandler" method="send8583Message" />-->

<!-- Simply used to mock the card network by transforming a SwithMessage to a SwitchMessageResponse * Not needed for target solution -->
<int:transformer id="requestResponseTransformer" ref="nettyCardNetworkClientMock" input-channel="cardNetworkOutChannel"
                 method="process" output-channel="cardNetworkInChannel"/>

<!-- Input from Card Network -->
<int:channel id="cardNetworkInChannel" />

<int:service-activator input-channel="cardNetworkInChannel" ref="switchMessageHandler" method="sendSwitchMessage"
                       output-channel="queueReplyChannel"/>


<int:channel id="queueReplyChannel"/>

<int-jms:outbound-channel-adapter
        destination-resolver="simpleDestinationResolver" connection-factory="jmsConnectionFactory"
        channel="queueReplyChannel" destination-expression="headers.jms_replyTo" />
  • Sorry but your question is not clear at all. Please always try to be very specific... e.g. "..the gateway would not work...". Client side? or Server side? You should be able to use outbound and message-driven adapters on both sides and use `destination-expression` on the outbound adapters. – Gary Russell Jul 17 '15 at 20:24
  • Sorry Gary - This is a server side component from an ActiveMQ standpoint. The app consumes messages from a fixed queue. It then communicates via TCP via a specific protocol and receives replies over TCP. These replies will then need to be sent back to ActiveMQ referencing the original inbound ActiveMQ message's jmsReplyTo address. At design time this server component does not know what the reply to queues will be. The clients (ActiveMQ) to this app each create a reply queue unique to the client. – Cory E Adams Jul 17 '15 at 21:21
  • OK, but you need to explain exactly what your issue is. – Gary Russell Jul 17 '15 at 21:23
  • The ActiveMQ clients are not receiving the response as I am guessing that the server side jms outbound channel adapter is not setting the destination. – Cory E Adams Jul 17 '15 at 21:27

1 Answers1

-1

I just updated the jms sample app to make the server side use independent adapters instead of the inbound gateway and it works just fine...

<!--    <jms:inbound-gateway id="jmsin" -->
<!--                         request-destination="requestQueue" -->
<!--                         request-channel="demoChannel"/> -->

<channel id="demoChannel"/>

<jms:message-driven-channel-adapter destination="requestQueue" channel="demoChannel" />

<service-activator input-channel="demoChannel" ref="demoBean" output-channel="reply" />

<channel id="reply" />

<jms:outbound-channel-adapter channel="reply" destination-expression="headers['jms_replyTo']" />

Turn on DEBUG logging - we put out lots of useful stuff.

EDIT

I just made it async by...

<channel id="reply">
    <queue/>
</channel>

<jms:outbound-channel-adapter channel="reply" destination-expression="headers['jms_replyTo']">
    <poller fixed-delay="3000"/>
</jms:outbound-channel-adapter>

EDIT2

Depending on what you are using on the client side, many clients require the inbound message id to be used as the correlation id. (This is true for the outbound gateway by default, with named reply queue, unless you provide a correlation-key).

So, to set up the correlationId, you can use a header enricher; I just tested this...

<chain input-channel="reply">
    <header-enricher>
        <header name="jms_correlationId" expression="headers['jms_messageId']" />
    </header-enricher>
    <jms:outbound-channel-adapter destination-expression="headers['jms_replyTo']"/>
    <poller fixed-delay="1000" />
</chain>

This is not the issue if the client side is setting the correlation id header itself.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • That destination-expression was what I was looking for. The client is still not receiving the response. I have debugged and could not determine the outbound destination queue but I will turn the DEBUG logging on and see what I can find. I think your example would be more accurate if you had an async process that sent messages from your demoBean and another service activator that received messsages asynchronously prior to hitting the reply channel in your above example. In that case the chain is broken between the original inbound message on your demoChannel and the outbound reply channel. – Cory E Adams Jul 17 '15 at 21:46
  • See my edit - adding a queue channel makes it async. Still works fine for me. – Gary Russell Jul 17 '15 at 21:51
  • What are you using on the client side? – Gary Russell Jul 17 '15 at 22:50
  • accepting based on the destination-expression. The client no longer receives messages but the reply is clearly in the queue. – Cory E Adams Jul 20 '15 at 18:13
  • Best guess is the client has a message selector attempting to match something in the reply. If you don't control the client, your broker may provide a mechanism to determine what it is (e.g. ActiveMQ does via the web console). Spring Integration will echo any headers set on the client side (e.g. JMSCorrelationId). The inbound gateway inserts the messageId as the correlation id, when a correlation key is not provided. Hence my suggestion to try doing the same using a header enricher. – Gary Russell Jul 20 '15 at 19:15
  • Brilliant! Thanks Gary. The chain and header-enricher worked for AMQ. – Cory E Adams Jul 21 '15 at 14:38