Any multi-channel router should support channel name patterns [INT-1189]
Mark Fisher opened INT-1189 and commented
Currently, the multi-channel routers are required to return 0 or more channel instances or channel names. This is typically done by returning an array or Collection (or having an equivalent type of evaluation result from a SpEL expression).
We should also add support for basic wildcard matching (e.g. "bank.prime.*" would match any channel whose name begins with "bank.prime.").
The most elegant solution is probably to change the ChannelResolver strategy interface so that it supports a multi-return value option. The only method currently defined on the interface is:
MessageChannel resolveChannelName(String channelName);
We could add:
Collection<MessageChannel> resolveChannelPattern(String channelPattern);
The question is of course if we need to worry about backwards compatibility. It would be much nicer to have a single interface rather than having to extend ChannelResolver (which inevitably leads to instanceof checks). My initial feeling is that implementing ChannelResolver is a rather advanced extension. In fact, I'd be surprised if more than a handful of SI users have ever done it. Those users would probably be the least concerned if we add a method to the interface.
Affects: 2.0 M4
Issue Links:
- #5375 Refactor router hierarchy to provide consistent approach for managing router mappings dynamically (e.g., ControlBus)
Oleg Zhurakousky commented
Yet another option would be to provide an implementation of MessageChannel that encapsulates a Collection of channels gathered based on the pattern matching. This way non of the interfaces has to change, therefore no need to worry about breaking backward compatibility. This way you would have something like:
class PatternBasedChannel implements MessageChannel{
private Collection<MessageChannel> channels;
. . . .
}
So now it would be similar to the RecipientListRouter. You call a single send(..) on it and it will be propagated to all channels in yje internal Collection.
Mark Fisher commented
I don't think it would be a good idea to make a bunch of channels appear to be one channel. That is blurring the distinction between the responsibilities of a channel vs. router. We don't necessarily need to change the ChannelResolver interface, we could just as easily do this in the router via the direct reference to beanFactory (e.g. a method in the AbstractChannelNameResolvingRouter class).
Oleg Zhurakousky commented
For multi-channel router I agree, its already a multi-channel router, so we just need to make sure it recognizes patterns. The way I interpreted the requirement was more along these lines:
<service-activator output-channel="*input" .../>
Send to all channels that end with 'input'.
I would look at it slightly different and AMQP-ish-like way where I would have a class PatternBasedChannelExchange implements MessageChannel. And yes this particular implementation would inherit basic capabilities of the RecipientListRouter where recipient list would be assembled based on the pattern/expression and "bound to a pattern". It could actually even be more dynamic where new channels would be bound to it as they are created. So every time you provide anything but a single channel name, the endpoint would be bootstrapped with the Exchange rather then Channel, however to the internals of SI it would make no difference since Exchange would implement MessageChannel
Mark Fisher commented
I think using the name pattern in the output-channel is something we want to avoid. That really starts to blur the line between a router and channel. If we are making analogies with AMQP "Exchange", I definitely think we would be talking about a Router in Spring Integration and not a channel.
Oleg Zhurakousky commented
I agree and I think i misinterpreted the requirement and was trying to find justification for output-channel="
Mark Fisher commented
On second thought, I think we might want to be careful with this one.
Perhaps we can provide this feature in "recipient-list-router" or some other focused component. However, if we were to actually make this work for any router, I think it would be too easy to abuse.
Oleg Zhurakousky commented
Although it sounds simple there are many ways to approach it and finding the most appropriate is what makes it tricky, so we'll revisit this in 2.2