Spring Integration
  1. Spring Integration
  2. INT-1342

Allow to reuse a <chain> with different input and output channels

    Details

    • Type: New Feature New Feature
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None

      Description

      When one needs to factorize some chain of endpoints, it would be useful to define a common chain (with or without input and output channels) and be able to call it from anywhere by defining (or overriding) the input and output channels.

      For example, we might want to call frequently the following <chain>:

      <chain id="commonChain">
          <header-enricher> ... </header-enricher>
          <service-activator> ... </service-activator>
          <gateway> ... </gateway>
      </chain>

      but for different input and – especially! – output channels.


      As discussed on the forum,

      • The possibility to have a different output-channel is necessary, as, in the same context, we might want to have two flows invoking the same chain without interferring with each other.
      • The router is not an option for such a usecase :
        Indeed, the <chain> being configured in a separated file (and potentially saved in a different jar put at disposal of other applications), it is not aware of its "clients" and we don't want to modify the router (and thus the common jar) every time a new client wants to invoke the <chain>.
      • Setting the replyChannel header before calling the <chain> has also some drawbacks, such as:
        • The common <chain> might also want to set the replyChannel header for a similar reason, which would then override the value set by the "client".
        • The common <chain> could not be called within another <chain> as the output-channels are not explicitely defined.
        • Not easily readable for an external reader.

      Here's a suggestion which looks easy to understand for an external reader, quite straightforward to try for a Spring developper used to reusing beans, and which doesn't have all the previously mentionned drawbacks:

      common-config.xml
      <chain id="commonChain">
          <header-enricher> ... </header-enricher>
          <service-activator> ... </service-activator>
          <gateway> ... </gateway>
      </chain>
      client-config.xml
      <chain ref="commonChain" input-channel="channelIn" output-channel="channelOut" />
      

      Maybe "ref" is not the best attribute name as it is often used for POJOs in Spring Integration, but it is often used in this context in Spring and a POJO wouldn't probably make sense for a chain.

        Activity

        Hide
        Oleg Zhurakousky added a comment -

        Pierre

        I think what you are asking could be easily accomplished with <bridge> configured by each individual client that imports the configuration where the chain is. Right?

        Show
        Oleg Zhurakousky added a comment - Pierre I think what you are asking could be easily accomplished with <bridge> configured by each individual client that imports the configuration where the chain is. Right?
        Hide
        Pierre Lecesne added a comment -

        Indeed, it is. That's actually how we have implemented it in the end.

        In my opinion, it isn't so easy to read the context file (ie. the flow) as we can't see where the channels are defined (because defined in another file). I feel the flow is easier to read with the solution I suggested, but this may be only me

        Show
        Pierre Lecesne added a comment - Indeed, it is. That's actually how we have implemented it in the end. In my opinion, it isn't so easy to read the context file (ie. the flow) as we can't see where the channels are defined (because defined in another file). I feel the flow is easier to read with the solution I suggested, but this may be only me
        Hide
        Oleg Zhurakousky added a comment -

        Pierre

        In your solution I would still have to know the ID of the chain just like I would have to know the channel name right?
        Also, I am sure you understand the emphasis we put on the value of the Channel abstraction in SI. So "sending message to a chain" is somewhat couter-intuitive to the overall value of the Channel in SI and in fact might be misinterpreted. I think you'd agree that "sending message to a channel" at the end wins.

        In any event I propose to close it with NoFix at this time. What do you think?

        Show
        Oleg Zhurakousky added a comment - Pierre In your solution I would still have to know the ID of the chain just like I would have to know the channel name right? Also, I am sure you understand the emphasis we put on the value of the Channel abstraction in SI. So "sending message to a chain" is somewhat couter-intuitive to the overall value of the Channel in SI and in fact might be misinterpreted. I think you'd agree that "sending message to a channel" at the end wins. In any event I propose to close it with NoFix at this time. What do you think?
        Hide
        Pierre Lecesne added a comment -

        Dear Oleg,

        I'm not sure what you mean by "sending message to a chain" as, in my solution, the message is still sent to and consumed from channels. The chain, as it's been defined in my solution, could be compared (more or less) to the bean of a service-activator.
        If the channel was defined in the client context file (as opposed to in the common context file), the client could decide which implementation of channel he would like the chain to consume the message from. Else, the channel implementation must be unique among all clients and defined once and for all in the common context file.

        If you understand what I mean and still believe that this suggestion is not appropriate, then I'll trust your experience and approve the NoFix.

        Show
        Pierre Lecesne added a comment - Dear Oleg, I'm not sure what you mean by "sending message to a chain" as, in my solution, the message is still sent to and consumed from channels. The chain, as it's been defined in my solution, could be compared (more or less) to the bean of a service-activator. If the channel was defined in the client context file (as opposed to in the common context file), the client could decide which implementation of channel he would like the chain to consume the message from. Else, the channel implementation must be unique among all clients and defined once and for all in the common context file. If you understand what I mean and still believe that this suggestion is not appropriate, then I'll trust your experience and approve the NoFix.
        Hide
        Oleg Zhurakousky added a comment -

        Pierre, what I mean is that conceptually you can only send message to a channel. Chain (as you said) is like any other endpoint and as any other endpoint it 'subscribes' or 'polls' from the channel. So channel is still at the core of the solution.
        Anyway, I am resolving it
        Cheers

        Show
        Oleg Zhurakousky added a comment - Pierre, what I mean is that conceptually you can only send message to a channel. Chain (as you said) is like any other endpoint and as any other endpoint it 'subscribes' or 'polls' from the channel. So channel is still at the core of the solution. Anyway, I am resolving it Cheers
        Hide
        Oleg Zhurakousky added a comment -

        Also, you can try PropertyPaceholder when defining the chain and instead of use concrete name use $

        {someChannel}

        . Will that work?

        Show
        Oleg Zhurakousky added a comment - Also, you can try PropertyPaceholder when defining the chain and instead of use concrete name use $ {someChannel} . Will that work?

          People

          • Assignee:
            Mark Fisher
            Reporter:
            Pierre Lecesne
          • Votes:
            6 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: