Home > database >  Spring-Integration: Using a recipient-list-router from inside of a chain to achieve iteration but ge
Spring-Integration: Using a recipient-list-router from inside of a chain to achieve iteration but ge

Time:09-20

From a spring-integration chain A I'm calling a chain B that may "loop" on itself until all information recovery is satisfied (since the first call may retrieve information that itself needs to be resolved by subsequent calls).

chain A calls to chain B via a gateway call, hence expects a return message:

<int:chain input-channel="A_channel" />
    ...
    <int:gateway request-channel="B_channel" />
    ...
</int:chain>

In case that it's useful, I'll note that the chain A is itself called from a gateway call originating from an HTTP inbound-gateway.

Chain B then embeds a recipient-list-router:

<int:channel            id="B_channel" />
<int:chain   input-channel="B_channel" >
    <int:gateway request-channel="C_channel" />
    <int:transform ... set the payload to indicate if still more work to do ... />
    <int:recipient-list-router resolution-required="false">
        <int:recipient channel="B_channel" select-expression="payload.size() != 0" />
    </int:recipient-list-router>
</int:chain>

The is giving me an error. Either of

  • "No channel resolved by router" (when no resolution-required attribute is set)
  • "No channel resolved by router and no defaultOuputChannel defined" (with resolution-required set to false)

I'm wanting an iterative loop based upon a condition and I was thinking that recipient-list-router would give me that possibility, but I'm not finding the magic invocation. Also, if the recipient-list-router at the end of a chain resolves no output channel, I was thinking that it would continue to the output-channel that the chain itself would have configured, in this case, the replyChannel set up by the gateway call to chain B.

What will allow this kind of iterative execution from within a declarative environment?

CodePudding user response:

Solution using <int:filter ...> as proposed by @artem-bilan:

<int:channel            id="B_channel" />
<int:chain   input-channel="B_channel" >
    <int:gateway request-channel="C_channel" />
    <int:transform ... set the payload to indicate if still more work to do ... />
    <int:filter expression="payload.size() eq 0" discard-channel="B_channel" />  
    <... post-iteration operations here ...>
</int:chain>

Much more compact and easier to read. Thanks!

CodePudding user response:

What seems to "work" is simply taking the recipient-list-router (RLR) out of the chain and routing to a final chain.

The chain B from the initial example is split across two chains, an isolated RLR and two additional channels:

<int:channel            id="B_channel" />
<int:chain   input-channel="B_channel" output-channel="B2_channel" >
    <int:gateway request-channel="C_channel" />
    <int:transform ... set the payload to indicate if still more work to do ... />
</int:chain>

<int:channel                          id="B2_channel" />
<int:recipient-list-router input-channel="B2_channel" resolution-required="false">
    <int:recipient channel="B_channel"  select-expression="payload.size() gt 0" />
    <int:recipient channel="B3_channel" select-expression="payload.size() eq 0" />
</int:recipient-list-router>

<int:channel            id="B3_channel" />
<int:chain   input-channel="B3_channel" >
    ... do anything here ...
</int:chain>

However, I'm not quite sure that this returns the message to the replyChannel set by the original <int:gateway ...> call .. still testing it.

  • Related