4

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

lbvirgo
  • 354
  • 1
  • 5
  • 22

1 Answers1

0

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.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • My business use case is that I've created a "util-kind-of" configuration of SI components that start with a service-activator. When a message is presented to this service-activator's input-channel, it processes the message through a downstream of components and then ultimately deposits the message payload on to a MQ. The end channel of this "util-kind-of" configuration is a nullChannel. My upstream configuration is producing a List of Messages. My requirement is to process each of these message through the "util-kind-of" configuration in an order. – lbvirgo Oct 21 '15 at 01:58
  • I'm planning to use a splitter between the upstream configuration and the "util-kind-of" configuration but I'm not sure 1) how to ensure processing order (so say a "natural" order; meaning in the same order in which messages were inserted in List; will that depend on what implementation of List I'm using ? 2) Since the end point of "util-kind-of" configuration is nullChannel, I'm not sure if the control will come back to caller thread to process next message in the List. – lbvirgo Oct 21 '15 at 02:01
  • For my use case I don't need an aggregator. I just need to split messages, process them in an order one by one. – lbvirgo Oct 21 '15 at 02:04
  • If your payload is a Collection already it is iterated as is without modification . The nullChannel just assumes the same like one-way outbound-channel-adapter. Just figure out the same process without SI! De ja vu , but that's is true that even SI is restricted with its language rules and even more: work the same way as similar components in the language – Artem Bilan Oct 21 '15 at 02:13
  • So if I remove output-channel="nullChannel" from the last element of my "util-kind-of" configuration and since I don't care for a response (if any) from this "util-kind-of" configuration, will that work out for my use case ? OR it cause any thread to be engaged (for sync case) ? – lbvirgo Oct 21 '15 at 02:46
  • You need `nullChannel` if you have `service-activator` for the non-`void` method to ignore its return. Otherwise everything works the same. No one thread won't be in stuck, unless your own logic. Sorry, I'm stopping to understand you... Maybe you'll come back to the reference manual. For example to understand how `nullChannel` works. BTW you even can read `NullChannel` source code. – Artem Bilan Oct 21 '15 at 18:57
  • Ok, I think I get it now. Manual says : "The nullChannel acts like /dev/null, simply logging any Message sent to it at DEBUG level and returning immediately." For my context, the key word here is "returning". I earlier assumed that caller thread "stops" its execution once it finds a nullChannel. But it appears that it means that caller thread will get handle back once it finds a nullChannel AND will not care about the response recvd (if any) from downstream. I hope this time I understood it correct ! – lbvirgo Oct 22 '15 at 01:28