Spring Message Channel Design

The Channel here we talked about is different from the Channel in Java NIO. NIO Channel is a wrapper around file descriptors. The Channel here is about message sending.

Spring Channel is the fundamental building block of Spring Messaging. Channel is a way to send messages. Here send means literally “send”. That’s why the very top interface of Spring Channel has only send method.

Since MessageChannel is a way to send messages, so who is invoking the send method?

The answer is some other consumer is using the channel to send messages.

But we care about how to connect channels together, pipe the messages down the stream. Since the send method of the channel is used to send a message. Then we could just call another channel’s send method inside the current channel to link the channels together. Dummy implementation looks like this

But this is too simple. Maybe different channels are responsible for different message formats. So in the first channel, we might want to process or transform the message before sending it to the second channel. We could create a MessageHandler and call this handler inside the channel send method. So let’s create another interface for MessageHandler

Different implementations of message handlers are dependent on business needs. It’s easy to see that MessageHandlers should exist inside the Channel.

In object-oriented programming, we want to decouple message handlers with the channel and give the user the ability to dynamically configure what handlers the channel could use. So we could actually create a register method on the handler side, take the channel as an input parameter.

Now we enabled to register message handlers with channels. We could loop through each handler to process the message inside the channel.

But how to send the transformed messages down the stream? The answer is We could call another channel’s send method inside the MessageHandler’s handleMessage method.

Now we have two problems to address

(1)What if the handler method of a certain MessageHandler is very computation heavy?

(2)We might have two different message handlers, HandlerB is not working on the result of HandlerA. They both work on the same message, but no relationship at all. They could be working in parallel.

The Solution

We need to use a separate thread to handle the message. How to design this? One way is to make each MessageHandler also extends Runnable.

Then we have to call the handleMessage inside the run() method. In order to start a separate thread, we could put one Executor inside the Channel implementation to start a separate thread for each handler.

Now let’s look at the original Spring implementation, how it corresponds to what we have described so far.

MessageHandlingRunnable.java

ExecutorSubscribableChannel.java

Now I want to make some corrections, so far all the above design corresponds to ExecutorSubscribableChannel. But it already gives us a general design of how Spring channels could be connected together by handlers. And also shows us how the channel could use different threading models to send the message. There are other types of channels like PollableChannel, QueueChannel. But the general design is the same, using handlers to process the message and pipe the messages down the stream.

If there is anything incorrect, please leave a comment. My next topic will be describing the threading models of Rabbitmq.

I am a software developer who is keen to know how things work