4
votes

I've few basic questions regarding the splitter element in SI.

I understand that to form a customized splitter logic, we need to extend AbstractMessageSplitter and override the splitMessage method.

This collection of split messages are then presented on the output-channel of splitter (assuming no reply channel was configured on incoming message).

The output-channel of splitter can then become input-channel for another si component. Let's assume that component is a simple service-activator.

The manual says that "each" message of the collection will be processed by the downstream configuration to which this collection was presented. So in our example, service-activator will process "each" message.

1) My query is "who" exactly iterates the collection and presents "each" message from collection on the input-channel of service-activator ?

2) Let's assume that we have all direct channels involved here. Now if the output-channel of service-activator is configured as a nullChannel, will it still be presented the "next" message from collection once the first message has been processed successfully ?

3) Let's assume we have no aggregator involved here. Also let's assume all the methods involved have non-void return. What will be returned to the caller thread that present "collection" of messages to the splitter's output-channel ? Will it get back a collection of return types that the service-activator returns ? or will it get back just the return of last processed message from collection ?

I hope I made my queries elaborate enough to get them clarified.

Many thanks to respond.

Best Regards

1

1 Answers

0
votes

Yep. you are asking good questions!

1) AbstractMessageProducingHandler:

protected void sendOutputs(Object result, Message<?> requestMessage) {
    if (result instanceof Iterable<?> && shouldSplitOutput((Iterable<?>) result)) {
        for (Object o : (Iterable<?>) result) {
            this.produceOutput(o, requestMessage);
        }
    }
    else if (result != null) {
        this.produceOutput(result, requestMessage);
    }
}

Exactly from here each item is sent to the output-channel.

2) Yes, if everything is on the DirectChannel, the next message won't be sent until the finish for previous. Actually it works the same way like in raw java:

 for (Object o : collection) {

 }

Note: in this sync case, if the current message process fail, the next one won't be sent. Because of Exception. Exactly like with the raw Java :-).

3) Well. With raw Java it may look like:

split(Collection<?>, Future<?>);  
 --->>
 for (Object o : collection) {
     process(Object, Future<?>)
 }

Exactly this process is done in the splitter or even better in each EIP component. Actually all of them works only in push mode. Even if it is done something with the reply it is really only push to the replyChannel.

So, if you don't take care about the reply process only the first message will populate the reply to that Future<?> - in our case sends reply to the replyChannel. Right, all others can do the same, but the reply will be ignored already. See the TemporaryReplyChannel source code.

Note, if your downstream splitter process is async, e.g. ExecutorChannel as an output-channel on <splitter> there is no prediction which message will be guilty in the reply. Therefore to make you top sending Thread happy you should figure out some sufficient algorithm around those splitted messages. Maybe even with <aggregator>.

I think an answer for your last question depends on the target business logic requirements.