Click here to Skip to main content
Click here to Skip to main content

Tagged as

Network Application Framework with Java

, 7 Apr 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
Apache MINA is a network application framework which helps users develop high performance and high scalability network applications easily. It provides an abstract · event-driven · asynchronous API over various transports such as TCP/IP and UDP/IP via Java NIO.

Introduction

Apache MINA is a network application framework which helps users develop high performance and high scalability network applications easily. It provides an abstract · event-driven · asynchronous API over various transports such as TCP/IP and UDP/IP via Java NIO.

Apache MINA is often called:

  • NIO framework · library,
  • client · server framework · library, or
  • a networking · socket library.

Background

To write programs in this framework you must know Core Java, some fundas about Socket programming, TCP/IP and UDP. If you are strong in it, then you can make an 8th wonder of world with this framework. Wink | ;)

Using the Code

This tutorial will walk you through the process of building a MINA based program. This tutorial will walk through building a time server. The following prerequisites are required for this tutorial: All the required libraries are available in “lib” folder of the source code that I have.

  • MINA 1.1 Core
  • JDK 1.5 or greater
  • SLF4J 1.3.0 or greater
    • Log4J 1.2 users: slf4j-api.jar, slf4j-log4j12.jar, and Log4J1.2.x
    • Log4J 1.3 users: slf4j-api.jar, slf4j-log4j13.jar, and Log4J1.3.x
    • java.util.logging users: slf4j-api.jar and slf4j-jdk14.jar

Writing the MINA Time Server

We will begin by creating a file called MinaTimeServer.java. The initial code can be found below:

public class MinaTimeServer{
     public static void main(String args[]){
        // code will go here next.
    }
}

This code should be straightforward to all. We are simply defining a main method that will be used to kick off the program. At this point, we will begin to add the code that will make up our server. First off, we need an object that will be used to listen for incoming connections. Since this program will be TCP/IP based, we will add a SocketAcceptor to our program.

import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
public class MinaTimeServer {
    public static void main(String[] args) {
        // The following two lines change the default buffer type to 'heap',
        // which yields better performance.c
        ByteBuffer.setUseDirectBuffers(false);
        ByteBuffer.setAllocator(new SimpleByteBufferAllocator());
        IoAcceptor acceptor = new SocketAcceptor();
    }
}

With the SocketAcceptor class in place, we can go ahead and define the handler class and bind the SocketAcceptor to a port. If you are interested in adding a thread model to the SocketAcceptor, please read the Configuring Thread Model tutorial.
We will now add in the SocketAcceptor configuration. This will allow us to make socket-specific settings for the socket that will be used to accept connections from clients.

import java.io.IOException;
import java.nio.charset.Charset;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.filter.LoggingFilter;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
public class MinaTimeServer {
private static final int PORT = 9123;
public static void main(String[] args) throws IOException {
 ByteBuffer.setUseDirectBuffers(false);
 ByteBuffer.setAllocator(new SimpleByteBufferAllocator());

 IoAcceptor acceptor = new SocketAcceptor();

 SocketAcceptorConfig cfg = new SocketAcceptorConfig();
 cfg.getFilterChain().addLast( "logger", new LoggingFilter() );
 cfg.getFilterChain().addLast( "codec", new ProtocolCodecFilter
		( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
 }
}

Here we have created a new instance of the SocketAcceptorConfig class that will be used to pass in to the acceptor once we are ready to start up the acceptor. First, we have set the reuse address flag. See more information about this in the JDK Documentation. Next we add a filter to the configuration. This filter will log all information such as newly created sessions, messages received, messages sent, session closed. The next filter is a ProtocolCodecFilter. This filter will translate binary or protocol specific data into message object and vice versa.

This last addition will bind the acceptor to the port. This method will signal the startup of the server process. Without this method call, the server will not service client connections.

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.filter.LoggingFilter;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;

public class MinaTimeServer {

private static final int PORT = 9123;

public static void main(String[] args)
throws IOException { ByteBuffer.setUseDirectBuffers(false); ByteBuffer.setAllocator(
new SimpleByteBufferAllocator());

IoAcceptor acceptor = new SocketAcceptor();

SocketAcceptorConfig cfg = new SocketAcceptorConfig(); 
	cfg.getFilterChain().addLast( logger",
new LoggingFilter() ); cfg.getFilterChain().addLast( codec",
new ProtocolCodecFilter(
new TextLineCodecFactory( Charset.forName(  ))));

acceptor.bind(new InetSocketAddress(PORT),
new TimeServerHandler(), cfg); System.out.println(MINA Time server started."); }}

What you see here is that we have defined a variable port of type integer and made a call to SocketAcceptor.bind(SocketAddress,IoHandler). The first parameter is the SocketAddress that describes the network address that will be listening on, in this case port 9123, and the local address. 

The second parameter passed to the bind method is a class that must implement the interface IoHandler. For almost all programs that use MINA, this becomes the workhorse of the program, as it services all incoming requests from the clients. For this tutorial, we will extend the class IoHandlerAdapter. This is a class that follows the adapter design patternwhich simplifies the amount of code that needs to be written in order to satisfy the requirement of passing in a class that implements the IoHandler interface. 

The third parameter is the configuration object, cfg, which has been configured with a logger filter and a codec filter. MINA is set up such that each message that is received will be passed through any and all filters in the filter chain defined for the IoAcceptor. In this case, we will pass all messages through a logging filter and then a codec filter. The logging filter will simply log the message using the SL4J library, and the codec filter will decode each message received and encode each message sent using the supplied TextLineCodecFactory class.   

Below is the class TimeServerHandler:

import java.util.Date;
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.apache.mina.common.TransportType;
import org.apache.mina.transport.socket.nio.SocketSessionConfig;

public class TimeServerHandler extends IoHandlerAdapter {
 public void exceptionCaught(IoSession session, Throwable t) throws Exception {
 t.printStackTrace();
 session.close();
 }

 public void messageReceived(IoSession session, Object msg) throws Exception {
 String str = msg.toString();
 if( str.trim().equalsIgnoreCase("quit") ) {
 session.close();
 return;
 }

 Date date = new Date();
 session.write( date.toString() );
 System.out.println("Message written...");
 }

 public void sessionCreated(IoSession session) throws Exception {
 System.out.println("Session created...");

 if( session.getTransportType() == TransportType.SOCKET )
 ((SocketSessionConfig) session.getConfig() ).setReceiveBufferSize( 2048 );

 session.setIdleTime( IdleStatus.BOTH_IDLE, 10 );
 }
}

Here we have the code for the handler portion of the tutorial program. We have overridden the methods exceptionCaught, messageReceived and sessionCreated. As stated previously, this class extends the IoHandlerAdapter, which is a class that follows the Adapter design pattern. 

The exceptionCaught method will simply print the stack trace of the error and close the session. For most programs, this will be standard practice unless the handler can recover from the exception condition.

The messageReceived method will receive the data from the client and write back to the client the current time. If the message received from the client is the word "quit", then the session will be closed. This method will also print out the current time to the client. Depending on the protocol codec that you use, the object (second parameter) that gets passed in to this method will be different, as well as the object that you pass in to the session.write(Object) method.  If you do not specify a protocol codec, you will most likely receive a ByteBuffer object, and be required to write out a ByteBuffer object.

The sessionCreated method is typically where your session initialization occurs. In this case, we print out that the method has been entered, and then test if the transport type of the session is socket based (versus UDP), and then set the receive buffer size. In the case above, the incoming buffer size is set to 2048 bytes. The idle time is also set to 10 seconds. If we were to override the sessionIdle method, the sessionIdle method would get called every 10 seconds.

Try Out the Time Server

At this point, you can go ahead and compile the program. Once you have compiled the program, you can run the program in order to test out what happens. The easiest way to test the program is to start the program, and then telnet in to the program:

Client Output Server Output

user@myhostUnsure | :~ > telnet 127.0.0.1 9123 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. hello Mon Apr 09 23:42:55 EDT 2007 quit Connection closed by foreign host. user@myhostUnsure | :~ >

MINA Time server started. Session created... Message written...

NOTE: This is the simplest way to create a server in Java, I have also added the source code (Project) which consists of only 2 Java files. Just import the project in your IDE workspace and execute MinaTimeServer.java file, this will start the server. For telnet, you use Command Prompt and follow the above steps. You can do a variety of things with Apache MINA, for the time being, to make it easy I’m outputting the server time and the client text that he enters to the Client.

Points of Interest

I liked this framework, you can support many protocols like Telnet, IRC, STOMP, XMPP, DarkStar, Yahoo Messenger Protocol, etc. with this framework.

History

  • 7th April, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

jaigharge

India India
No Biography provided

Comments and Discussions

 
Questionimport error in netbeans PinmemberMember 859039427-Jan-12 6:24 
AnswerRe: import error in netbeans Pinmemberjaigharge31-Jan-12 4:39 
GeneralVery good content. Pinmemberraam78-Apr-09 23:32 
GeneralI liked the content and the Code did work fine for me. Pinmemberkaazi7-Apr-09 21:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141220.1 | Last Updated 7 Apr 2009
Article Copyright 2009 by jaigharge
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid