Announcement Announcement Module
Collapse
No announcement yet.
Problem implementing JMS synchonous communication with outbound gateway. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem implementing JMS synchonous communication with outbound gateway.

    Here it is: I'm implementing a service BUS that talks to a Message Driven Bean (MDB). It is a synchonous call.

    I'm using Spring Integration (SI) on both end (BUS + MDB).
    When the message leave the BUS though a JMS Outbound Gateway, it get pick up by the MDB through Websphere message listening and it tries to reply through a JMS Outbound Channel Adapter.

    Then it arrives... The BUS times out waiting for the message even though it's there on the Queue.

    I'm using:
    Spring 3.0.5.RELEASE
    Spring Integration 2.0.3.RELEASE
    IBM Websphere host the MDB.
    IBM MQ

    I know it's something with the corelation id/message id that is not recognized after it ran through the MDB, because I stubbed it with an JMS Inbound Gateway an it worked great.

    Any idea? Mark Fisher are you online ?

  • #2
    When you say "even though it's there on the Queue", are you referring to the Queue that you have configured as the reply-destination for the outbound gateway?

    Can you provide some relevant excerpts from your configuration?

    Thanks,
    -Mark

    Comment


    • #3
      Yes, Mark, I'm taking about the Reply Queue.

      Here is my Outbound Gateway config :

      <jms:outbound-gateway request-channel="mesChannel"
      connection-factory="connectionFactory"
      request-destination-name="${mes.mq.queue.request.name}"
      time-to-live="${mes.mq.time.to.live}"
      request-timeout="${mes.mq.queue.request.timeout}"
      receive-timeout="${mes.mq.queue.receive.timeout}"
      reply-destination-name="${mes.mq.queue.response.name}"
      reply-channel="bsbReplyChannel"
      />

      And here is my Inbound Gateway that stubs the MDB (and makes the loop work)...

      <jms:inbound-gateway id="mesInboundGateway" request-channel="mesReplyChannel"
      connection-factory="connectionFactory"
      request-destination-name="${mes.mq.queue.request.name}"
      default-reply-queue-name="${mes.mq.queue.response.name}"
      />

      I'm using 'predefined' queues for both request/reply.
      ----------------------------------------------------------------------------
      Here is the code on the MDB side when receiving the message:

      public void processMessage(javax.jms.Message message) {
      DefaultJmsHeaderMapper jmsHeaderMapper = new DefaultJmsHeaderMapper();
      Map<String, Object> headders = jmsHeaderMapper.toHeaders(message);
      MessageConverter messageConverter = new SimpleMessageConverter();
      String payload = (String) messageConverter.fromMessage(message);
      requestChannel.send(MessageBuilder.withPayload(pay load).copyHeaders(headers).build());
      }

      Here is the reply end config of the MDB.
      ---------------------------------------------------------------------------

      I'm using JTA as the transaction manager (and also had a few problems with the two phase commit so I disable it.. for now Container Transactions=Not Supported).

      Great response time !!
      Last edited by Olivier Quirion; Mar 4th, 2011, 02:07 PM. Reason: Addtionnal Info

      Comment


      • #4
        Can you verify that the outbound-channel-adapter you are using to send the "reply" on that MDB side is passing a Message that contains a value for the JMSCorrelationID?

        Comment


        • #5
          The JMSCorrelationID is set to X'000000000000000000000000000000000000000000000000 '
          or something like that. I haven't done anything to set it, so I assumes it's the default value.

          I tried setting it to something using :
          MessageBuilder.fromMessage(message).setHeader(JmsH eaders.CORRELATION_ID, 17).build();

          Before sending the message, but aborted because it breaked my test with the Inbound Gateway. I haven't test it with the MDB directly.

          Do I have to set it? And what value should I use (something unique of course: UUID, Timestamp or whatever)?
          Why would it break my test with the inbound gateway then?
          Thanks again

          Regards,
          Oliver
          Last edited by Olivier Quirion; Mar 4th, 2011, 02:28 PM. Reason: Typo

          Comment


          • #6
            By default, the Spring Integration JMS outbound-gateway will expect the reply to have a JMSCorrelationID value that matches the JMSMessageID of the request Message it had sent. Also, the Spring Integration JMS inbound-gateway provides the mirror-image of that same behavior by default. So, you should make sure that either the JMSMessageID ends up in the JMSCorrelationID on the other side when it's not Spring Integration based. Alternatively, you can tweak the configuration of how the outbound-gateway sets and expects the correlation ID. See the JavaDoc for the "setCorrelationKey(..)" method on JmsOutboundGateway for more information about that option.

            Hope that helps.
            -Mark

            Comment


            • #7
              Guess what:

              I've added the following piece of code:
              headers.put(JmsHeaders.CORRELATION_ID, headers.get(JmsHeaders.MESSAGE_ID));

              right after :

              DefaultJmsHeaderMapper jmsHeaderMapper = new DefaultJmsHeaderMapper();
              Map<String, Object> headers = jmsHeaderMapper.toHeaders(message);

              And voila!!! It all started working!!

              Thanks Mark, I'm a big fan of yours, keep up the good work @Spring.

              Comment


              • #8
                Okay, and just to be clear, you added that code within the handling method of your MDB, correct?

                Comment


                • #9
                  Yes, i've added the code in the MDB, when I'm in the process of converting the javax.jms.Message to a org.springframework.integration.Message.

                  Here it is:

                  public void processMessage(javax.jms.Message message) {
                  DefaultJmsHeaderMapper jmsHeaderMapper = new DefaultJmsHeaderMapper();
                  Map<String, Object> headers = jmsHeaderMapper.toHeaders(message);

                  headers.put(JmsHeaders.CORRELATION_ID, headers.get(JmsHeaders.MESSAGE_ID));

                  try {
                  MessageConverter messageConverter = new SimpleMessageConverter();
                  String payload = (String) messageConverter.fromMessage(message);
                  requestChannel.send(MessageBuilder.withPayload(pay load).copyHeaders(headers).build());
                  } catch (Throwable throwable) {
                  ...
                  }
                  }

                  Hopes this helps someone else one day!!!

                  Comment

                  Working...
                  X