In netty, MessageEvent (wrapper for messages) has a method Object getMessage() to get the real carried message from the network. Reading the source I noticed they heavily use the instanceof operator to switch among methods.
However, having a wide variety of message types I would like to avoid a method like this:
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
if (e.getMessage() instanceof MessageType1) {
...
} else if (e.getMessage() instanceof MessageType2) {
...
} ... {
...
} else if (e.getMessage() instanceof MessageTypeN) {
...
} else {
ctx.sendUpstream(e);
}
}
Writing different methods taking advantage of polymorphism would be much better, like:
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
// MessageType implements Message
if (e.getMessage() instanceof Message) {
handleMessage(ctx, (Message) e.getMessage());
} else {
ctx.sendUpstream(e);
}
}
void handleMessage(ChannelHandlerContext ctx, MessageType1 m) {
...
}
...
void handleMessage(ChannelHandlerContext ctx, MessageTypeN m) {
...
}
But i cannot due to downcasting limitations. Is there a clean way to do this or am I tied to instanceof cascade? I could bring the logic out the Handler using .doSomething() methods inside Message sub-types but I'd like to keep the business logic inside the netty pipeline.
Solved applying Visitor Pattern:
public interface Handler {
void handleMessage(ChannelHandlerContext ctx, MessageType1 m);
void handleMessage(ChannelHandlerContext ctx, MessageType2 m);
...
void handleMessage(ChannelHandlerContext ctx, MessageTypeN m);
}
then:
@Sharable
public class MessageHandler extends SimpleChannelHandler implements Handler {
...
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
if (e.getMessage() instanceof Message) {
Message m = (Message) e.getMessage();
m.handleTo(ctx, this);
} else {
ctx.sendUpstream(e);
}
}
@Override
public void handleMessage(ChannelHandlerContext ctx, MessageType1 m) {
...
}
and
public interface Message {
/*
* Will be {
* handler.handleMessage(ctx, this);
* }
* everywhere.
*/
void handleTo(ChannelHandlerContext ctx, Handler handler);
}