Announcement Announcement Module
Collapse
No announcement yet.
How to send out 2 different messages to 2 different channels from a Service Activator Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to send out 2 different messages to 2 different channels from a Service Activator

    Hi,

    I am trying to implement the next flow:

    File-inbound-Adapter-->fileChannel-->ServiceActivatorWebService-->responseChannel-->ServiceActivatorProcessResponse

    I read a file from a folder, create a ws service request based on it and process the ws response. Additionally, I would like to archive the original file if the WebService was successful. My ServiceActivatorWebService returns a message with the XML response, so I am loosing the message with the original file in order for the File-outbound-Adapter to move the file to the archive folder.

    In other words, I would like to add the next flow (if the ws request was successful):
    ServiceActivatorWebService-->fileChannel2-->File-outbound-Adapter

    I cannot come up with a solution that does not involve changing the ServiceActivatorWebService business class to programatically send the original message to fileChannel2.

    Thanks !

  • #2
    This is a rather common scenario and has came up a few times on this forum.
    All you need to do is three things add a Bridge to the fileChannel and make fileChannel a pub-sub channel and most importantly make sure ServiceActivatorProcessResponse and Bridge send to the same output-channel. By doing so you'll accomplish a classic splitter-aggregator pattern.
    Make sure you set apply-sequence to 'true' on fileChannel, this way the default aggregator will know when to release the aggregated message (list).
    Code:
    fileChannel-->saws-->resChannel-->sapr -> aggregatingChannel
          |                                            /
           -> bridge ---------------------------------/
    When you implement custom aggregator you'll get an input as a list consisting of two messages. 1) the original one (coming from the bridge) and 2) the one coming from the WS response. I am sure you know what to do from there.

    Comment


    • #3
      @netname

      Another possible solution would be to loop through the file payload in a header property. So before the message is send to the ServiceActivatorWebService you use a header enricher to set a property like "loopThroughPayload" with the current payload. Than you can access the file payload (via message header property access) and the ws response via message payload after the ServiceActivatorWebService.
      The solution is not as a clean and pretty as the one of Oleg, but you do not need any aggregators (which are a little bit tricky in practice in my mind).

      Regards,
      Philipp

      Comment


      • #4
        Thanks for such a good and detailed answers. They make it so much easier for a newbie to pickup the new concepts and vocabulary.

        @Oleg

        With your instructions it was very easy to change the flow to get a list of messages with their corresponding payloads on my custom aggregator (one message with the file and the other with the ws response). The problem I am facing now is that my aggregator method can return a message with a file if there was no error on the ws, but what should I return if there was an error?

        In other words, how can I send a message to the discard channel instead of the normal output channel?

        @Philipp

        Your proposal seems very straightforward. I am way ahead with Oleg's solution but I can see how your method might be simpler. I guess a concern would be if the files were too large, in that case having 2 instances of them (on in the header and one in the payload) might be problematic.

        Thanks again for your help. Much appreciated !!

        Comment


        • #5
          . . .but what should I return if there was an error?
          This is probably one of those tricky part Philip was referring too.

          Also, both solutions discussed here are equally valid and clean so which one you choose depends on the use case. In fact I'd say if the only thing you care about is knowing the original file name and that's all, then I would go with the Philipps solution of enriching the original message with the file name.

          With the aggregator it does get tricky when not all (sequence size) messages come back to the aggregator due to the error or other reasons. In your case if an exception is raised before the message hits the aggregator, the aggregator will be sitting and waiting for a message that will never come. This means you would also need to implement the custom release strategy etc., and it might be an overkill of your use case.

          Comment


          • #6
            @netname

            For the more tricky error part with Olegs solution you can set the message header error channel property to a custom error channel, so that the ErrorMessage for the occurred exception in the serviceActivatorWebService is send to the "aggregatingChannel" or a custom "serviceActivatorWebServiceErrorChannel", in which some transformations can be done before the failed message gets routed to the "aggregatingChannel", and not the global errorChannel. You solved than the problem that the aggregator may wait forever for a message or that there are maybe some cases where the file message is released/expired to early if you work with timeouts (else you may get an OutOfMemoryError anytime or you need infinite persistence space).
            After the aggregator some handlers must be configured to handle the successful/unsuccessful message processing.
            By the way: The aggregator uses without custom configuration a heap based MessageStore (SimpleMessageStore).

            Regards,
            Philipp

            Comment

            Working...
            X