Spring Message Channel Design

class FirstChannel implements MessageChannel {
send(Message message) {
SecondChannel downStream = new SecondChannel();
downStream.send(message)
}
}
class SecondChannel implements MessageChannel {
send(Message message) {
//dummy
}
}
interface MessageHandler {
handleMessage(Messsage message)
}
class FirstChannel implements MessageChannel {
List<MessageHandler> handlers;
...
}
class DummyHandler implements MessageHandler {
registerChannel(MessageChannel channel) {
channel.addHandlers(this) --> add handler to channel
}

handleMessage(Message message) {
...
}
}
class FirstChannel implements MessageChannel {
List<MessageHandler> handlers;

send(Message message) {
handlers.forEach(handler -> { --> foreach handler
handler.handleMessage(message)
})
}
}
class DummyHandler implements MessageHandler {
MessageChannel outputChannel;

DummyHandler(MessageChannel outputChannel) {this.outputChannel = outputChannel}
registerChannel(MessageChannel channel) {
channel.addHandlers(this)
}

handleMessage(Message message) {
/some message transformation might happen here*/ /*call output channel to pipe the changed message another channel */
outputChannel.send(message);
}
}

Now we have two problems to address

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

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.

interface MessageHandler extends Runnable { --> Runnable has run()
handleMessage(Message message);
}
class FirstChannel implements MessageChannel {
ExecutorService executor;
List<MessageHandler> handlers;

send(Message message) {
handlers.forEach(handler -> {
executor(handler.run()); --> here
})
}
}
MessageHandlingRunnable.java    --> Handler extends Runnablepublic interface MessageHandlingRunnable extends Runnable {
Message<?> getMessage();

MessageHandler getMessageHandler();
}
/*we have simplified the file, but the original file looks pretty much like this. The subscribers here are message handlers. It's just different names*/public boolean sendInternal(Message<?> message, long timeout) {
subscribers.foreach(subscriber -> {
ExecutorSubscribableChannel.SendTask sendTask = new ExecutorSubscribableChannel.SendTask(message, handler);
this.executor.execute(sendTask); --> Executor run SendTask
}
})
}
/*SendTask is one inner class which implements run method*/class SendTask implements MessageHandlingRunnable {
@Override
public void run() {
this.messageHandler.handleMessage(message);
}
}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ryan Zheng

Ryan Zheng

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