Announcement Announcement Module
Collapse
No announcement yet.
publishsubscribechannel when exception gets thrown in one of the subscribers Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • publishsubscribechannel when exception gets thrown in one of the subscribers

    What is the expected behavior of the publishsubscribechannel when a runtime exception gets thrown by one of the subscribers? Should all of the other subscribers still get the message?

    For instance, if there are 3 subscribers to a publishsubscribechannel and one of the subscribers throws a runtime exception, is the expected behavior that the other two subscribers will still receive the message and process normally or is the expected behavior that none of the subscribers will receive the message?

    The latter appears to be the case for me but I need to do some more testing to help me verify what is going on.

    Thanks

    Keith

  • #2
    Currently, it does fail fast as soon as an Exception occurs. That does not affect other handlers if the pubish-subscribe-channel has a TaskExecutor reference. But, in the default case where there is no TaskExecutor, that will prevent the remaining handlers from being invoked.

    I have thought about this recently, since the RecipientListRouter does have an "ignore" flag for failures. Perhaps we should provide the same thing for publish-subscribe-channel. It would be FALSE by default so that the current fail-fast behavior is the same, but at least that would enable switching it off. Does that make sense?

    Comment


    • #3
      Adding the "ignore" flag for failures sounds good.

      With that said ....
      I think I'm missing something.
      I'm a little confused about what the purpose of adding a task-executor to the publishsubscribechannel would be?

      A message comes into the publishsubscribechannel, the message gets "sent" to each subscriber of the publishsubscribechannel. What is a use case for adding a task-executor to this functionality?

      Comment


      • #4
        When a Message is sent to a publish-subscribe-channel, it uses a dispatcher to invoke the MessageHandlers that are subscribed to that channel (e.g. any service-activator, transformer, etc.). By default, that invocation will happen in the same Thread. By adding a TaskExecutor you get the advantage of letting those dispatches occur concurrently, but the tradeoff is that transactional context is not shared between the sender and the handler(s).

        Is that a clear enough description?

        Comment


        • #5
          So if I would add a org.springframework.scheduling.concurrent.ThreadPo olTaskExecutor I can make the publishsubscribechannel multi-threaded ... at the risk of complicating the "transaction?" Is that right? If so, would the "incoming transaction" essentially end at the publishsubscribechannel?

          Comment


          • #6
            Yes, that is the idea. In such a case, the only thing that can affect the sender's transaction is if a TaskExecutor throws an Exception to reject the task itself.

            Comment


            • #7
              I created this issue:
              http://jira.springframework.org/browse/INT-734

              I just resolved it also. The 'ignore-failures' attribute will be available in Spring Integration 1.0.3.

              Comment


              • #8
                Mark

                Do you have any suggestions for how to handle the durability issue related to the publisher-subscribe-channel?

                For example, my flow gets a message in, then goes through a number of common steps which end with the messages "published" to a publish-subscribe-channel. If at this point my "incoming transation" is over right? So if my incoming message was pulled off of an "incoming Queue" the acknowledge will get sent back to the JMS server and the message will come off of the queue. If my stand alone java process gets shut down before all the "listeners" of the publish-subscribe-channel" are done, I will lose messages.

                Any suggestions on how I handle this durability problem?

                Thanks

                Keith

                Comment


                • #9
                  Are the listeners on the publish-subscribe-channel executed in the same thread that receives the JMS message? i.e. are you using the "task-executor" attribute on the publish-subscribe-channel?

                  Comment


                  • #10
                    At the moment I am not using the task-executor but I am weighing the benefits/risks of doing that which is what drove my question.

                    It seems that I have 3 options:
                    1) Use publish-subsribe-channel with ignore-failures = false
                    In this case the issue is that if one of the "subscribers" throws an exception, the transaction will fail and the incoming message will stay on the queue. So if the 3rd of 5 subscribers throws the exception, the first two subscribers got the message but the 3,4,5th subscribers did not process the message.

                    2) I can use publish-subscribe-channel with ignore-failures=true
                    In this case all my subscribers will process the message and only the subscriber who throws the exception will not process the message. The issue here is that I have to come up with a way to deal with the "problem subscriber" and figure out how to "save" the message in order to fix the problem and retry it later. Since ignore-failures was true the transaction will complete even if there is an exception in one of the subscribers and the incoming message will come off of the incoming queue.

                    3) Add the "task-executor" capability
                    In this case the benefit seems to be that a "slow" subscriber will not hold things up for the other subscribers. The problem area is that the I believe the transaction will complete once the message gets put on the in-memory executor queue. Once the transaction completes, the message will come off of the incoming queue. The danger in this seems to be that if my stand alone spring integration process gets shut down for any reason I will lose the messages that were on the in memory executor queue.

                    Do I have all of that right? If so, I'm trying to way which one is the best case for my needs.

                    Comment


                    • #11
                      It sounds like you have a very good understanding of the behavior.

                      I don't know the details of your use-case, but typically it seems odd to have a JMS Queue followed by a "publish-subscribe-channel". Have you considered using a JMS Topic, or is there some reason for the Queue?

                      Comment


                      • #12
                        The high level picture of what we have going on:
                        Incoming messages go on the incoming queue.
                        The spring framework deployment pulls messages off the queue.
                        A set of "common" steps take place ... like schema validation, security validation, common normalization, etc
                        From there we need to send the message to several "subscribers" specific channels. Each subscriber path has a flow to transform and manipulate the message specific to that subscriber. The subscriber specific message then goes to a subscriber specific queue. Some subscribers write their own queue listeners and we write others. The ones we write we typically get the messages to the subscriber by file transfer or web service calls or something like that.

                        The thing I like about our current architecture/design is that I can scale by adding more "spring integration deployements." We also have redundancy because each deployment works off of the same incoming queue and publishes to the same subscriber queues. If one deployment would happen to go down, the message would stay on the incoming queue and another deployment would pick it up.

                        I thought about replacing the "publish-subscribe-channel" with a topic for the durability but then I lose the "add more deployments to scale" because I can only have one listener pulling messages off of the topic. I could create a topic per deployment, but then I lose the redundancy because each deployment has it's own topic.

                        I currently have things deployed with the publish-subscribe-channel set to ignore-failures=failse.
                        Things are working pretty well but I have two problems I'm worried about.
                        1) If a specific subscriber flow is really really slow, the other subscribers will have to wait for the slow one to get the message.
                        2) If one subscriber throws an exception it prevents the other subscribers from getting the message.

                        I was thinking of fixing problem 1 by adding the task-executors but then I run into the durability problem.

                        I was thinking of fixing problem 2 by adding the ignore-failres=true. I think this is my best path at the moment but I need to put something in place to make sure people get notified of a problem, the problem gets fixed, and the message gets resent.

                        In our world it is accpetable for our subscribers to get "duplicate messages" so the message that failed for one subsriber can be resent to all of them after the "failed subscriber problem" gets fixed.

                        I'm new to spring integration and relatively new to "ESBs" so I'm certainly open to other architecture/design ideas.

                        Thanks

                        Keith

                        Comment


                        • #13
                          Thanks for the detailed information!

                          Would it be manageable if you introduced another level of JMS Queues on the subscriber side of your "publish-subscribe-channel". That way you could achieve the following:
                          1) provide a new transaction boundary at the "handoff"
                          2) allow the subscribers to handle messages concurrently
                          3) avoid lost messages when one or more subscribers fail (assuming persistent Queues)

                          I guess it depends on how many such subscribers you have in the system.

                          Comment


                          • #14
                            The requirements people have promised my that the number of subscribers won't grow very much. Maybe 10 or so. Also some of the subscribers get what comes out of the "common steps" so I won't need to create another level of queues for those subscribers. I'll experiment and see how it goes.


                            Thanks for the suggestion.

                            Keith

                            Comment


                            • #15
                              Sounds good, and I was also thinking that this "second" level might be a good place to use JMS Topics after all (maybe even in place of publish-subscribe-channels).

                              Anyways, if possible, please report back as the project progresses. I'm also interested in any obstacles you encounter or ideas you have that we should consider for the 2.0 roadmap.

                              Thanks again,
                              Mark

                              Comment

                              Working...
                              X