After re-reading EIP description of the RoutingSlip pattern and the notes of Mark Fisher on Issue INT-267 I can more clearly see how to implement such a RoutingSlip pattern. After a few test, two things seem's mandatory for this :
* The RoutingSlip Object MUST be Cloneable in order to be able to provide a copy of the Queue to every "thread" resulting of the split operation. This can be done in AbstractMessageSplitter while setting the sequenceNumber for each fragment.
* The RoutingSlip MUST have an equals method which return true for every RoutingSlip instance created by the clone method so we are able to keep this object in the merge operation of the header during an aggregate operation.
What I can't really figure out is what the RoutingSlip object really is.
I attempt to make it a simple POJO returning a new channel name at each call, but then I need to add an IfElse condition after outputchannel/replychannel check when sending the reply (AbstractReplyProducingMessageHandler and CorrelatingMessageHandler). But if other routing patterns have to be implemented I agree this is not a good way to do that.
In another hand, Mark talk about granted the RoutingSlip concept has a MessageChannel himself. It seem's to be a good approach but I can't figure out at which time when committing the send operation this MessageChannel will substitute himself to the underlying next MessageChannel in the Queue ??
What seem's to miss here is a MessageChannelResolver interface with a single getChannel() method which was able to retrieve the next channel from the Queue or the ReplyChannel or anything else based on a custom policy.
Don't you thing that the following, may ease the support of such patterns ?
Code:
/**
* Send the message to the given channel. The channel must be a String or
* {@link MessageChannel} or {@link MessageChannelResolver} instance, never <code>null</code>.
*/
private void sendMessage(final Message<?> message, final Object channel) {
if (channel instanceof MessageChannel) {
this.messagingTemplate.send((MessageChannel) channel, message);
}
else if (channel instanceof MessageChannelResolver) {
this.messagingTemplate.send((MessageChannelResolver) channel.getChannel(), message);
}
else if (channel instanceof String) {
this.messagingTemplate.send((String) channel, message);
}
else {
throw new MessageDeliveryException(message,
"a non-null reply channel value of type MessageChannel or String is required");
}
}