Spring Integration
  1. Spring Integration
  2. INT-928

Add support for nested splitter/aggregator flows

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Complete
    • Affects Version/s: 2.0 M1
    • Fix Version/s: 2.0 M7
    • Component/s: Core
    • Labels:
      None

      Description

      There are several ways to approach this, and beginning with some tests, we can experiment with each option:
      1) invoke the nested flow from a "gateway" which essentially "resets" any headers for the parent/calling flow
      2) add support for "Stack" typed header values, so that a component like Aggregator could pop() instead of simply get() or peek()
      3) work this into something like the "scatter-gather" component as a higher level "composite" handler (see INT-275).

      When considered in the broader sense, this issue is similar to that of sub-flows in Spring Web Flow.

        Activity

        Hide
        Dave Syer added a comment -

        I implemented this using a simple trick with two transformers: one upstream of the nested split, and one downstream. The upstream transformer stashes the correlationId, sequenceNumber and sequenceSize in temporary headers, and the downstream transformer restores them. This is really a special case of the stack-based approach above (with max depth 1). It suggests a backwards-compatible implementation of the stack-based approach: using a temporary header whose value is the stack instead of using the existing headers and changing their semantics.

        The only gotcha was that the MethodInvokingAggregator discards all headers, so we had to write a custom aggregator using the Message API to transfer the headers from the incoming messages (all are basically identical unless the flow since the split has inserted new headers).

        Show
        Dave Syer added a comment - I implemented this using a simple trick with two transformers: one upstream of the nested split, and one downstream. The upstream transformer stashes the correlationId, sequenceNumber and sequenceSize in temporary headers, and the downstream transformer restores them. This is really a special case of the stack-based approach above (with max depth 1). It suggests a backwards-compatible implementation of the stack-based approach: using a temporary header whose value is the stack instead of using the existing headers and changing their semantics. The only gotcha was that the MethodInvokingAggregator discards all headers , so we had to write a custom aggregator using the Message API to transfer the headers from the incoming messages (all are basically identical unless the flow since the split has inserted new headers).
        Hide
        Mark Fisher added a comment -

        Now that the aggregator maintains headers, this should be a bit simpler now? It seems like we could overcome the max-depth=1 limitation if the temporary headers were themselves Stacks perhaps?

        Show
        Mark Fisher added a comment - Now that the aggregator maintains headers, this should be a bit simpler now? It seems like we could overcome the max-depth=1 limitation if the temporary headers were themselves Stacks perhaps?
        Hide
        Dave Syer added a comment -

        Implemented using an array header containing popped state - seems like lowest common denominator. Works out of the box for splitter/aggregate pairs, but open to suggestion for better ways or more scenarios.

        Show
        Dave Syer added a comment - Implemented using an array header containing popped state - seems like lowest common denominator. Works out of the box for splitter/aggregate pairs, but open to suggestion for better ways or more scenarios.

          People

          • Assignee:
            Dave Syer
            Reporter:
            Mark Fisher
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Time Tracking

              Estimated:
              Original Estimate - 1d
              1d
              Remaining:
              Remaining Estimate - 1d
              1d
              Logged:
              Time Spent - Not Specified
              Not Specified