blob: aa6f87179b9a2ef1d0b4b1b2a80e2b4ffe398ff0 [file] [log] [blame]
Title: Quick Start Guide
Notice: Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.
http://www.apache.org/licenses/LICENSE-2.0
.
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
# Quick Start Guide
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:
* MINA 2.0.7 Core
* JDK 1.5 or greater
* [SLF4J|http://www.slf4j.org/] 1.3.0 or greater
* **Log4J 1.2** users: _slf4j-api.jar_, _slf4j-log4j12.jar_, and [Log4J](http://logging.apache.org/log4j/1.2/) 1.2.x
* **Log4J 1.3** users: _slf4j-api.jar_, _slf4j-log4j13.jar_, and [Log4J](http://logging.apache.org/log4j/1.2/) 1.3.x
* **java.util.logging** users: _slf4j-api.jar_ and _slf4j-jdk14.jar_
* **IMPORTANT** : Please make sure you are using the right _slf4j-*.jar_ that matches to your logging framework.
For instance, _slf4j-log4j12.jar_ and _log4j-1.3.x.jar_ can not be used together, and will malfunction.
I have tested this program on both Windows© 2000 professional and linux. If you have any problems getting this program to work, please do not hesitate to [contact us|Contact] in order to talk to the MINA developers. Also, this tutorial has tried to remain independent of development environments (IDE, editors..etc). This tutorial will work with any environment that you are comfortable with. Compilation commands and steps to execute the program have been removed for brevity. If you need help learning how to either compile of execute java programs, please consult the [Java tutorial](http://java.sun.com/docs/books/tutorial/).
## Writing the MINA time server
We will begin by creating a file called MinaTimeServer.java. The initial code can be found below:
:::Java
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.
:::Java
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class MinaTimeServer
{
public static void main( String[] args )
{
IoAcceptor acceptor = new NioSocketAcceptor();
}
}
With the _NioSocketAcceptor_ class in place, we can go ahead and define the handler class and bind the NioSocketAcceptor to a port.
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. We use an existing TextLine factory because it will handle text base message for you (you don't have to write the codec part)
:::Java
import java.nio.charset.Charset;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class MinaTimeServer
{
public static void main( String[] args )
{
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
}
}
At this point, we will define the handler that will be used to service client connections and the requests for the current time. The handler class 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 pattern which 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.
:::Java
import java.io.IOException;
import java.nio.charset.Charset;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class MinaTimeServer
{
public static void main( String[] args ) throws IOException
{
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
acceptor.setHandler( new TimeServerHandler() );
}
}
We will now add in the NioSocketAcceptor configuration. This will allow us to make socket-specific settings for the socket that will be used to accept connections from clients.
:::Java
import java.io.IOException;
import java.nio.charset.Charset;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class MinaTimeServer
{
public static void main( String[] args ) throws IOException
{
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
acceptor.setHandler( new TimeServerHandler() );
acceptor.getSessionConfig().setReadBufferSize( 2048 );
acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
}
}
There are 2 new lines in the MinaTimeServer class. These methods set the set the IoHandler, input buffer size and the idle property for the sessions. The buffer size will be specified in order to tell the underlying operating system how much room to allocate for incoming data. The second line will specify when to check for idle sessions. In the call to setIdleTime, the first parameter defines what actions to check for when determining if a session is idle, the second parameter defines the length of time in seconds that must occur before a session is deemed to be idle.
The code for the handler is shown below:
:::Java
import java.util.Date;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
public class TimeServerHandler extends IoHandlerAdapter
{
@Override
public void exceptionCaught( IoSession session, Throwable cause ) throws Exception
{
cause.printStackTrace();
}
@Override
public void messageReceived( IoSession session, Object message ) throws Exception
{
String str = message.toString();
if( str.trim().equalsIgnoreCase("quit") ) {
session.close();
return;
}
Date date = new Date();
session.write( date.toString() );
System.out.println("Message written...");
}
@Override
public void sessionIdle( IoSession session, IdleStatus status ) throws Exception
{
System.out.println( "IDLE " + session.getIdleCount( status ));
}
}
The methods used in this class are _exceptionCaught_, _messageReceived_ and _sessionIdle_. _exceptionCaught_ should always be defined in a handler to process and exceptions that are raised in the normal course of handling remote connections. If this method is not defined, exceptions may not get properly reported.
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 IoBuffer object, and be required to write out a IoBuffer object.
The _sessionIdle_ method will be called once a session has remained idle for the amount of time specified in the call _acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );_.
All that is left to do is define the socket address that the server will listen on, and actually make the call that will start the server. That code is shown below:
:::Java
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class MinaTimeServer
{
private static final int PORT = 9123;
public static void main( String[] args ) throws IOException
{
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
acceptor.setHandler( new TimeServerHandler() );
acceptor.getSessionConfig().setReadBufferSize( 2048 );
acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
acceptor.bind( new InetSocketAddress(PORT) );
}
}
## Try out the Time server
At this point, we 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@myhost:~> telnet 127.0.0.1 9123<br/>Trying 127.0.0.1...<br/>Connected to 127.0.0.1.<br/>Escape character is '^\]'.<br/>hello<br/>Mon Apr 09 23:42:55 EDT 2007<br/>quit<br/>Connection closed by foreign host.<br/>user@myhost:~> | MINA Time server started.<br/>Session created...<br/>Message written... |
## What's Next?
Please visit our [User Guide](userguide/user-guide-toc.html) page to find out more resources.