Announcement Announcement Module
Collapse
No announcement yet.
Spring Integration: publish-subscribe-channel and order of message delivery Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring Integration: publish-subscribe-channel and order of message delivery

    Hi,

    I am using a publish-subscribe-channel to send notifications to multiple subscribers. In one scenario, two messages were sent consecutively.
    However, it appeared that the second message was delivered first and then the first message was delivered.

    Is this the expected behavior? If so, is it possible to configure the channel to deliver messages in a FIFO order?

    Thank you very much in advance.

  • #2
    Moved thread to Spring Integration forum.

    Comment


    • #3
      Originally posted by userspring View Post
      In one scenario, two messages were sent consecutively.
      Can you explain and/or provide a code excerpt for this part?

      Is it simply two direct calls to channel.send(..), or is there another endpoint between where these messages are sent and the publish-subscribe-channel?

      Thanks.

      Comment


      • #4
        Thank you for your reply.

        My applicationContext:

        <integrationublish-subscribe-channel id="stateNotificationChannel" />
        <integration:service-activator input-channel="stateNotificationChannel"
        ref="suscriberA" method="stateNotificationHandler" />
        <integration:service-activator input-channel="stateNotificationChannel"
        ref="subscriberB" method="stateNotificationHandler" />
        <integration:service-activator input-channel="stateNotificationChannel"
        ref="subscriberC" method="stateNotificationHandler" />

        <bean id="publisher" class="com.myCom.service.impl.PublisherImpl">
        <property name="stateNotificationChannel" ref="stateNotificationChannel" />
        </bean>


        PublisherImpl Code:

        public class PublisherImpl implement Publisher {
        private MessageChannel stateNotificationChannel;
        public void setStateNotificationChannel(MessageChannel channel) {
        stateNotificationChannel = channel;
        }
        public void notifySubscribers() {
        .....
        sendCreateState();
        .....
        sendUpdateState();
        }
        public void sendCreateState() {
        Message<String> message = new GenericMessage<String>("CREATE");
        stateNotificationChannel.send(message);
        }
        public void sendUpdateState() {
        Message<String> message = new GenericMessage<String>("UPDATE");
        stateNotificationChannel.send(message);
        }
        }

        SubscriberAImpl Code:

        public class SubscriberAImpl implements SubscriberA {
        .....

        public void stateNotificationHandler(Message<String> message) {
        System.out.println("SubscriberAImpl.stateNotificat ionHandler: receiving state " + message.getPayload());
        }
        }

        (Ignoring SubscriberB and SubscriberC for now)

        Output:
        SubscriberAImpl.stateNotificationHandler: receiving state UPDATE
        SubscriberAImpl.stateNotificationHandler: receiving state CREATE

        Where I was expecting to see CREATE first and then UPDATE.


        I'd appreciate any advice/insight you can offer. Thank you.
        Last edited by userspring; Jan 29th, 2009, 08:34 AM.

        Comment


        • #5
          I just created a simple demo based on your code, and I am seeing the messages in the right order every time. Do you think something that you have left out could affect order?... or are you seeing Messages from multiple invocations?... or perhaps it's simply reordered in the console output but not the actual execution?

          If you could provide a very simple full code example that reproduces this, it would be extremely helpful in determining if there is in fact a bug.

          Thanks,
          Mark

          Comment


          • #6
            Yes, it is a simplified version of the real code, so the 2 actual calls do not happen that close together. There are calls to other beans and back in between the "send" calls, including steps that involve Hibernate data persistence. However, the two "send" calls do take place inside the same bean (same thread) and they do not go through other message endpoints.

            I am fairly certain the output is correct. Actually, I've also stepped through the code via the eclipse debugger and that seems to be the order.

            Unfortunately, the code base is quite large and has "privacy" restriction, so I am not sure I am allowed to send it out. I'll find out.

            Thank you again for your reply. Now that I know that this is not the expected behavior, I'll concentrate on the code logic to see maybe it's something else that is causing this problem.
            Last edited by userspring; Jan 29th, 2009, 11:19 AM.

            Comment


            • #7
              Thanks for the information.

              One simple trick that might help is to add the thread name to your output:
              Code:
               Thread.currentThread().getName() + ": SubscriberAImpl.stateNotificationHandler: receiving state " + message.getPayload()
              Please do post back if you discover what's happening.

              Comment


              • #8
                I definitely will. Thanks for the tip!

                Comment


                • #9
                  Mark,

                  Just want to let you know that we've found the problem and it's in the way our code behaves. The Message Channel delivers the messages in the correct order.

                  Using the above example,
                  - the "CREATE" message was send
                  - SubscriberA's service-activator method was the first to get invoked.
                  (SubscriberB's and SubscriberC's service-activator methods are still waiting to be invoked)
                  - SubscriberA's service-activator method performs some task that results in the publisher sending the "UPDATE".
                  - The send() call with "UPDATE" results in the service-activator method for all 3 subscribers to get invoked with the UPDATE message.
                  - All 3 subscribers finished processing the UPDATE message.
                  - SubscriberB's service-activtor method is invoked with the CREATE message
                  - SubscriberC's service-activtor method is invoked with the CREATE message

                  So the result is that while SubscriberA received the messages in the right order, SubscriberB and SubscriberC received the messages in the reversed order.

                  Note that I did not use thread-pool for the service activators since our beans are currently not thread-safe.

                  To resolve this for now, I just reversed the order of my service-activators in the applicationContext, i.e. putting subscriberA's service-activator last so that it is the last one to receive the message.

                  This seems to get me past the problem; however, I am not sure this is the ultimate solution or if I can always depend on this order being the same all the time (e.g. future implementation of Spring Integration may use a different ordering scheme)

                  This may sound a little strange, but is there any way I can guarantee the order in which the service-activator's get invoked?

                  Thank you!

                  Comment

                  Working...
                  X