Home > Apache Mina, Java > How to use the MINA IoFilter

How to use the MINA IoFilter

While rewriting a personal project using Apache Mina I found out that there was very limited documentation about how to chain up IoFilters and ProtocolCodecs properly. I’m using a text based protocol that uses line delimiters to indicate message boundaries. Mina comes with a TextLineCodec that does the splitting for you, resulting in your handler receiving String objects, instead of IoBuffers.

Great of course, but my idea was to line up the TextLineCodec filter with my own custom codec that creates nice command objects for my handler, and does some exception handling in case an invalid message is received. That way my handler code stays clean of any low-level protocol concerns and only works with high level objects. After several hours of fiddling around trying to create my own ProtocolCodec implementation I was unable to get it done. The interfaces didn’t allow me to pass on something else than an IoBuffer, not what i call a high-level object. After a mail conversation with Trustin Lee i decided to directly implement the IoFilter interface. But let’s start with the IoHandler.

My handler extends IoHandlerAdapter and contains the following method:

@Override
public void messageReceived(IoSession session, Object message) throws Exception {
/*
* If the received object is not a GLS Command object, then throw an exception
*/
if (! (message instanceof GlsCommand)) {
throw new Exception(“Illegal object type received: “+message.getClass().getSimpleName());
}

GlsCommand command = (GlsCommand) message;

/*
* Now that we know its a GLS Command object, pass it to the processing method
*/
processCommand(command);

/*
* Let the client know the processing was completed succesfully (no exception was thrown)
*/
session.write(ServerCommand.OK);

/*
* If the client told the server it was gonna quit, close the session
*/
if (“Q”.equals(command.getCommand())) {
session.close();
}
}

As you can see this code receives GlsCommand objects and replies using an Enum ServerCommand. The actual processing of the command happens in a private method not included here.

Now, of course the high-level object don’t magically travel between the client and the server. They are coded and decoded by an IoFilter which i will show in a moment. First you need to know that i’m combining 2 filters. The first one is the TextLineCodec which comes standard with MINA, and the second is my own filter. The TextLineCodec transforms the incoming stream of bytes from the client into String messages by tokening the stream on end-of-line characters. The decode method of the TextLineCodec receives bytebuffers, and passes String objects to the next filter. The encode method takes String objects and sends them to the client followed by an end-of-line character.
The String objects from the TextLineCodec are passed on to the next filter, which is my custom protocol filter:

Public class GlsProtocolFilter extends IoFilterAdapter {

@Override
public void messageReceived(NextFilter nextFilter, IoSession session, Object obj) throws Exception {
/*
* If the received object is not a String, then throw an exception
*/
if (! (obj instanceof String)) {
throw new Exception(“Illegal object type received: “+obj.getClass().getSimpleName());
}

/*
* Cast the received object to a String object
*/
String message = (String) obj;

/*
* Create a GlsCommand object and pass it on to the next filter in the chain
* (Which probabely doesn’t exist, so it goes directly to the Handler object)
*/
GlsCommand command = new GlsCommand(message);
nextFilter.messageReceived(session, command);
}

@Override
public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
/*
* If the object being sent is not a ServerCommand object, then throw an exception
*/
if (! (writeRequest.getMessage() instanceof ServerCommand)) {
throw new Exception(“Illegal object type being sent: “+writeRequest.getMessage().getClass().getSimpleName());
}

ServerCommand command = (ServerCommand) writeRequest.getMessage();
GlsCommandReply reply;

reply = new GlsCommandReply(writeRequest, command.getShortCommand().toString());

nextFilter.messageSent(session, reply);
}
}

Here you can see that the messageReceived method accepts noting else than String objects, and the messageSent command only accepts ServerCommand objects.

Now, putting it all together, my main code looks like this:

public static void main(String[] args) throws IOException {

NioSocketAcceptor acceptor = new NioSocketAcceptor();

acceptor.getFilterChain().addLast(“TextLineCodec”, new ProtocolCodecFilter(new TextLineCodecFactory()));
acceptor.getFilterChain().addLast(“GlsProtocolServerFilter”, new GlsProtocolFilter());

acceptor.setHandler(new GlsHandler());
acceptor.setReuseAddress(true);

acceptor.bind(new InetSocketAddress(47757));
}

I set the reuseAddress setting to true so my application doesn’t give me addresAlreadyInUse crap when i stop and start it.

If you have comments or questions, please don’t hesitate to contact me!

Geert Schuring.

Advertisements
Categories: Apache Mina, Java
  1. Lim Tou Ee
    November 13, 2008 at 4:50 pm

    Bookmarked!

    Thanks for putting this up.
    I never heard of apache mina until my boss told me implement a program using apache mina.

  2. Josh
    June 30, 2010 at 9:53 pm

    Geert Schuring, I love you more than you’ll ever know. You just solved a problem I’ve been having for days. I’ve gone through so many ideas that ended in failure. The main problem is if you want to scale your protocol handling to say, down the road you want to add additional protocols for other “command” families, casting in the handler can be a pain. Of course, using “instanceof” shouldn’t be a hard solution to come up with, however, it is so simple I didn’t include it in with all the “design patterny” complex solutions I was thinking of that didn’t work at all. I even tried applying generics which I do not know how to properly use. So, thank so much for this post.

  3. divya
    July 5, 2012 at 6:14 am

    Hi Geert Schuring, I am trying to implement server and client using Apache MINA, i am sending POJO from client to server and from server to client, but i am facing problem while receiving the Serialized object in Server messageReceived(IoSession session, Object message). in this method object is coming null. In your example what is GlsCommand ? is that a pojo? if yes please let me know how you are serializing and de – serializing it. Thank you in advance.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: