Announcement Announcement Module
Collapse
No announcement yet.
chain proposals: explicit channels, injected output channel Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • chain proposals: explicit channels, injected output channel

    Hi,

    I very much like the <chain> element. I have a couple of proposals which I'd like your thoughts on which would extend the capabilities of <chain> whilst, I hope, staying true to the core purpose of <chain> (to more concisely represent a linear flow).

    Proposal 1: async dispatch via explicit PollableChannel and <poller>

    I want to be able to do async dispatches within my linear flow, not just DirectChannel-based dispatch, e.g.:

    Code:
     <chain input-channel="input" output-channel="output">
         <filter ref="someSelector" throw-exception-on-rejection="true"/>
         <header-enricher error-channel="customErrorChannel">
             <header name="foo" value="bar"/>
         </header-enricher>
         <channel>
           <queue capacity="100"/>
         </channel>
         <service-activator ref="someService" method="someMethod">
           <poller ...>...</poller>
         </service-activator>
     </chain>
    This involves being able to put explicit channels within the chain, as well the default (implicit DirectChannel).

    Proposal 2: injected output channels

    My second proposal is to allow an additional category of components to be included within a <chain>. Given some domain-specific class:

    Code:
    class MyClass {
      private MessageChannel outputChannel;
    
      @OutputChannel
      public void setOutputChannel(MessageChannel outputChannel) { this.outputChannel = outputChannel; }
    
      @ServiceActivator
      public void dispatch(Message<?> message) {
        doContextSpecificProcessing(message);
        try {
          outputChannel.send(message);
        } finally {
          doContextSpecificPostChannelSend(message);
        }
      }
    }
    I want to be able to include this in a chain as follows:

    Code:
     <spring:bean id="someService" class="MyClass"/>
    
     <chain input-channel="input" output-channel="output">
         <filter ref="someSelector" throw-exception-on-rejection="true"/>
         <header-enricher error-channel="customErrorChannel">
             <header name="foo" value="bar"/>
         </header-enricher>
         <service-activator ref="someService"/>
     </chain>
    The proposed @OutputChannel annotation is used to inject the next channel in the chain -- in this case, "output" channel -- into the "someService" bean so that it can particpate in the chain.

    This means that components requiring explicit control over the dispatch to the next channel can still participate in the chain.

    Regards,
    Mike

  • #2
    Second proposal makes more sense to me than the first. The benefit if chain is really arguable once you start creating channels yourself. And if we go that way why not just add a queue? You can see it get's a bit messy there.

    The second suggestion doesn't change the chain semantics, and actually a setter for the output channel is already required, so I don't see much harm in allowing the user to take explicit control of that.

    I think you should create separate issues for both of them.

    Comment


    • #3
      Thanks for the feedback. Have raised JIRA new feature requestsINT-732 and INT-733 to cover this.

      Comment


      • #4
        Mike,

        As far as the first proposal is concerned, I agree with Iwein. I think the main idea behind chain is that all channels are implicit. Perhaps even more importantly, the use of direct channels in a chain allows an entire chain to be handled within a single transactional context. I am reluctant to break that contract for something that is really not that difficult to configure as 2 chains with a queue-channel between them. Generally, asynchronous queue-based channels should be used sparingly. Do you need to use them frequently between the components within your chain? If so, can you explain the reason for that? (maybe we can consider a global channel strategy, etc. for a chain). By the way, when components are defined outside of a chain, a channel is automatically created if not already present for the name provided via the "input-channel" attribute. Therefore, it's actually not a big difference in the amount of configuration.

        For the second proposal, you should be able to just implement MessageHandler and provide that in a <bean/> within the chain. Have you tried that? Since you are already tying your code directly to the Message interface, there is not much harm in implementing the simple 'handleMessage(m)' method. Also, can you explain at a high-level what you are doing in the call within the finally block? Maybe there is another way to support that invocation either with existing functionality or the addition of a callback within the framework.

        Thanks for submitting the issues. The feedback is very important to us as we begin the shift to 2.0 development.

        Regards,
        Mark

        Comment


        • #5
          Mark,

          Thanks for pointing out the possibility of using MessageHandler. Yes, this essentially solves the second problem, although it might be nice for my class not to have to implement MessageHandler and instead have the message-handling method be determined via annotations -- in the spirit of the current fashion for annotation-driven functionality.

          Regards,
          Mike

          Comment

          Working...
          X