directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Apache Wiki <wikidi...@apache.org>
Subject [Directory Wiki] Update of "MinaTutorial" by CKoppelt
Date Thu, 15 Feb 2007 23:53:54 GMT
Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Directory Wiki" for change notification.

The following page has been changed by CKoppelt:
http://wiki.apache.org/directory/MinaTutorial

------------------------------------------------------------------------------
- = MINA Tutorial: A Date with MINA =
+ deleted
  
- Original author: TrustinLee
- 
- This tutorial is intended for active user participation.  Please feel free to improve this
crude tutorial.
- 
- == Table Of Contents ==
- 
- [[TableOfContents]]
- 
- == Overview ==
- 
- It’s the era of the World Wide Web.  Countless web application frameworks were born to
improve development productivity by orders of magnitude.  In spite of this dominance of the
WWW, we know that there are a lot of protocols that HTTP cannot replace, and even HTTP is
just one of them.  We still need to build clients and servers that implement appropriate protocols.
- 
- === What is MINA? ===
- 
- Have you ever implemented any protocol stack in Java, or in any other languages?  As you
must have experienced, programming network applications is not so easy even for professional
developers.  It is due to a few significant problems:
- 
-   * There is no appropriate network application framework designed for developer productivity.
-     * You lose any chance to create your application in limited time.
-   * Network I/O code, message encoder/decoder, and business logic is often coupled to each
other.
-     * You lose maintainability and reusability.
-   * Network applications are difficult to unit-test
-     * You lose agility.
- 
- MINA is a network application framework to resolve all the issues listed above without sacrificing
performance nor scalability.
- 
- == I/O Layer: Programming Echo Server ==
- 
- MINA consists of two layers; I/O layer and protocol layer.  We first implement an echo server
using only I/O layer because protocol layer is usually built on top of I/O layer.
- 
- attachment:Arch1.gif
- 
- The above diagram shows interaction between clients and the MINA I/O layer.  IoAcceptor
performs all low-level I/O, translates them into abstract I/O events, and forwards the translated
events with the associated IoSession to IoHandler.
- 
- === IoSession ===
- 
- attachment:IoSession.gif
- 
- An IoSession represents an I/O connection between a remote peer and your application.  With
IoSession, you can write messages to the remote peer, access session configurations, and store
custom attributes associated with the session.
- 
- === IoHandler ===
- 
- attachment:IoHandler.gif
- 
-   * sessionCreated: Invoked when a new I/O connection is established.  This method is invoked
before any I/O operation is executed so that any socket parameters or session attributes can
be set first.
-   * sessionOpened: Invoked after sessionCreated is invoked.
-   * sessionClosed: Invoked when the I/O connection is closed.
-   * sessionIdle: Invoked when there is no transmission of data between remote peer and user
application.
-   * exceptionCaught: Invoked when any exceptions are thrown from IoAcceptor or your IoHandler.
-   * messageReceived: Invoked when protocol message is received.  Implement your protocol
flow here.
-   * messageSent: Invoked when protocol message that user requested by IoSession#write(Object)
is sent out actually.
- 
- We’ll see how to implement IoHandler for echo protocol in the next section.
- 
- === Implementing IoHandler and Startup Code ===
- 
- You usually extend IoHandlerAdapter to implement handler methods you have interest in:
- 
- {{{
- package org.apache.mina.examples.echoserver;
- 
- import org.apache.mina.common.ByteBuffer;
- 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 EchoProtocolHandler extends IoHandlerAdapter
- {
-     public void sessionCreated( IoSession session )
-     {
-         if (session.getTransportType() == TransportType.SOCKET) {
-             ((SocketSessionConfig)session.getConfig()).setReceiveBufferSize(2048);
-         }
-     }
- 
-     public void exceptionCaught( IoSession session, Throwable cause )
-     {
-         session.close();
-     }
- 
-     public void messageReceived( IoSession session, Object message )
-     {
-         if (!(message instanceof ByteBuffer))
-             return;
-     	
-         ByteBuffer rb = (ByteBuffer)message;
-         // Write the received data back to remote peer
-         ByteBuffer wb = ByteBuffer.allocate( rb.remaining() );
-         wb.put( rb );
-         wb.flip();
-         session.write( wb );
-     }
- }
- }}}
- 
- You’ve just implemented echo protocol with MINA.  Now you need to bind your handler to
a server port:
- 
- {{{
- import java.net.InetSocketAddress;
- import org.apache.mina.transport.socket.nio.SocketAcceptor;
- import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
- 
- public class Main
- {
-     /** Choose your favorite port number. */
-     private static final int PORT = 8080;
-     
- 
-     public static void main( String[] args ) throws Exception
-     {
-         SocketAcceptor acceptor = new SocketAcceptor();
-         SocketAcceptorConfig defaultConfig = new SocketAcceptorConfig();
-         defaultConfig.setReuseAddress(true);
-      
-         // Bind
-         acceptor.bind(new InetSocketAddress(PORT), new EchoProtocolHandler(), defaultConfig);
- 
-         System.out.println( "Listening on port " + PORT );
-     }
- }
- }}}
- 
- === Adding IoFilters ===
- 
- IoFilter provides the most powerful way to extend MINA.  It intercepts all I/O events and
pre- or post-processes them.  You may think it is similar to Servlet filters.  IoFilters can
be used for many purposes such as:
- 
-   * Event logging
-   * Performance profiling
-   * Data transformation (e.g. SSL support)
-   * Firewall, ...
- 
- attachment:Arch2.gif
- 
- Our echo protocol handler doesn’t log any I/O events.  We could log them by adding a filter
that logs them.  MINA, fortunately, provides IoLoggingFilter that provides that functionality.
 Let’s add a logging filter to ServiceRegistry.
- 
- {{{
- ....
- DefaultIoFilterChainBuilder chain = config.getFilterChain();
- addLogger(chain);
- ....
- 
- private static void addLogger( DefaultIoFilterChainBuilder chain ) throws Exception
- {
-     chain.addLast( "logger", new LoggingFilter() );
- 
-     System.out.println( "Logging ON" );
- }
- }}}
- 
- What about SSL?  MINA also provides an SSL filter that works in Java 5 or above.
- 
- {{{
- ....
- DefaultIoFilterChainBuilder chain = config.getFilterChain();
- addLogger(chain);
- ....
- 
- private static void addSSLSupport( DefaultIoFilterChainBuilder chain )
-     throws Exception
- {
-     SSLFilter sslFilter =
-         new SSLFilter( BogusSSLContextFactory.getInstance( true ) );
- 
-     chain.addLast( "sslFilter", sslFilter );
- 
-     System.out.println( "SSL ON" );
- }
- }}}
- 
- == Protocol Layer: Reversing the Echo ==
- 
- We learned how to use I/O layer via simplistic echo server example.  But have you ever imagined
how you would implement complex protocols like LDAP?  It must be a nightmare because the I/O
layer doesn’t help you separate message codec and actual business logic such as accessing
a directory database.  MINA provides a Protocol layer to resolve this issue.  The Protocol
layer transforms ByteBuffer events to POJO events which are at a higher-level:
- 
- attachment:Arch3.gif
- 
- You have to implement 5 interfaces: ProtocolHandler, ProtocolProvider, ProtocolCodecFactory,
ProtocolEncoder, and ProtocolDecoder:
- 
- attachment:ProtocolClasses.gif
- 
- Maybe it looks like overkill, but please note that ProtocolCodecFactory, ProtocolEncoder,
and ProtocolDecoder are fully reusable; Apache ASN1 project provides ASN.1 codec for MINA,
and more common codecs like XML, Java object serialization, and simple text will be provided
in the next release of MINA.  Once you implemente a flexible codec, you can reuse it in future
applications.  Even if you don’t plan to reuse your codec, of course, MINA provides a quite
easy way to implement complex protocols. (Please refer to Advanced Topics)
- 
- In this chapter, we create a ‘reverse’ server that reverses all text lines it receives
to demonstrate how to program in protocol layer.
- 
- === ProtocolSession ===
- 
- attachment:ProtocolSession.gif
- 
- ProtocolSession is a counterpart of the I/O layer IoSession.  As you must have noticed from
FIGURE X, you write messages as POJO's instead of ByteBuffer's.  ProtocolEncoder encodes message
objects to ByteBuffers so that the I/O layer can write them to underlying sockets.
- 
- === ProtocolHandler ===
- 
- attachment:ProtocolHandler.gif
- 
- ProtocolHandler is a counterpart of the I/O layer IoHandler.  dataRead and dataWritten methods
are replaced with messageReceived and messageSent.  This is because ProtocolDecoder decodes
ByteBuffers received from I/O layer into message objects.
- 
- === ProtocolEncoder and ProtocolDecoder ===
- 
- attachment:ProtocolCodec.gif
- 
- ProtocolEncoder and ProtocolDecoder have just one method each.  ProtocolEncoder encodes
message objects into a ByteBuffer, and ProtocolDecoder decodes ByteBuffers into message objects.
 We’ll learn how to implement these interfaces below.
- 
- === Implementing ProtocolHandler ===
- 
- Let’s implement a ProtocolHandler first.  We extend ProtocolHandlerAdapter here too, just
like we did when we implemented IoHandler:
- 
- {{{
- package org.apache.mina.examples.reverser;
- 
- import org.apache.mina.common.IoHandler;
- import org.apache.mina.common.IoHandlerAdapter;
- import org.apache.mina.common.IoSession;
- 
- public class ReverseProtocolHandler extends IoHandlerAdapter
- {
-     public void exceptionCaught( IoSession session, Throwable cause )
-     {
-         // Close connection when unexpected exception is caught.
-         session.close();
-     }
- 
-     public void messageReceived( IoSession session, Object message )
-     {
-         // Reverse received string
-         String str = message.toString();
-         StringBuffer buf = new StringBuffer( str.length() );
-         for( int i = str.length() - 1; i >= 0; i-- )
-         {
-             buf.append( str.charAt( i ) );
-         }
- 
-         // and write it back.
-         session.write( buf.toString() );
-     }
- }
- }}}
- 
- === Implementing ProtocolProvider and Setup Code ===
- 
- The only one interface left to implement reverse protocol is ProtocolProvider.  It is very
simplistic:
- 
- {{{
- package org.apache.mina.examples.reverser;
- 
- import org.apache.mina.protocol.*;
- 
- /**
-  * {@link ProtocolProvider} implementation for reverser server protocol.
- */
- public class ReverseProtocolProvider implements ProtocolProvider
- {
-     // Protocol handler is usually a singleton.
-     private static ProtocolHandler HANDLER =
- new ReverseProtocolHandler();
- 
-     // Codec factory is also usually a singleton.
-     private static ProtocolCodecFactory CODEC_FACTORY =
- new ProtocolCodecFactory()
-     {
-         public ProtocolEncoder newEncoder()
-         {
-             // Create a new encoder.
-             return new TextLineEncoder();
-         }
- 
-         public ProtocolDecoder newDecoder()
-         {
-             // Create a new decoder.
-             return new TextLineDecoder();
-         }
-     };
- 
-     public ProtocolCodecFactory getCodecFactory()
-     {
-         return CODEC_FACTORY;
-     }
- 
-     public ProtocolHandler getHandler()
-     {
-         return HANDLER;
-     }
- }
- }}}
- 
- That's it, the Reverser protocol is fully implemented now.  Startup code is very similar
to that of echo server:
- 
- {{{
- package org.apache.mina.examples.reverser;
- 
- import org.apache.mina.common.*;
- import org.apache.mina.protocol.*;
- import org.apache.mina.registry.*;
- 
- /**
-  * (<b>Entry point</b>) Reverser server which reverses all text lines from
-  * clients.
-  * 
-  * @author Trustin Lee (trustin@apache.org)
-  * @version $Rev: 165594 $, $Date: 2005-05-02 16:21:22 +0900 $,
-  */
- public class Main
- {
-     private static final int PORT = 8080;
- 
-     public static void main( String[] args ) throws Exception
-     {
-         ServiceRegistry registry = new SimpleServiceRegistry();
- 
-         // Bind
-         Service service = new Service( "reverse", TransportType.SOCKET, PORT );
-         registry.bind( service, new ReverseProtocolProvider() );
- 
-         System.out.println( "Listening on port " + PORT );
-     }
- }
- }}}
- 
- === Adding ProtocolFilters ===
- 
- ProtocolFilter is the counterpart of IoFilter from I/O layer:
- 
- attachment:Arch4.gif
- 
- Adding IoLoggingFilter logs low-level I/O events which are appropriate for debugging purposes.
 We could use ProtocolLoggingFilter instead to log higher-level events:
- 
- {{{
-     private static void addLogger( ServiceRegistry registry )
-     {
-         ProtocolAcceptor acceptor = registry.getProtocolAcceptor( TransportType.SOCKET );
-         acceptor.getFilterChain().addLast( "logger", new ProtocolLoggingFilter() );
-         System.out.println( "Logging ON" );
-     }
- }}}
- 
- == Advanced Topics ==
- 
- We cover more advanced topics for serious MINA users here.
- 
- === ByteBuffers ===
- 
- MINA doesn’t use the Java NIO ByteBuffer class directly.  It uses custom a ByteBuffer
class that extends the functionality of the Java NIO ByteBuffer.  Here are some differences:
- 
-   * MINA ByteBuffer is an abstract class that users can extend freely.
-   * MINA manages and pools MINA ByteBuffers.  Users can control the point the buffers are
released by providing acquire() and release() methods.
-   * MINA ByteBuffer provides convenient methods like unsigned value getter and String getter
and putter.
- 
- If you use MINA, you’ll never need to use NIO buffers directly because you can do most
buffer manipulation tasks using MINA buffers only.
- 
- ==== ByteBuffer pooling ====
- 
- MINA has a global ByteBuffer pool that is shared by all MINA applications in the same Virtual
Machine.  Any allocated buffers are released after the I/O operation or event handler method
is performed or invoked.  So you can simply call ByteBuffer.allocate() to get a clean buffer
from the pool and forget about returning it to the pool.  Please refer to the ByteBuffer JavaDocs
for more details.
- 
- === Thread Model ===
- 
- MINA provides support for various threading models using its versatile filter mechanism.
 It runs in a single thread mode when no thread pool filters are added.  If you add one IoThreadPoolFilter
to IoAcceptor, you get one leader-follower thread pool.  If you add one more ProtocolThreadPoolFilter,
Your server will have two thread pools; one (IoThreadPoolFilter) for decoding message objects
and the other (ProtocolThreadPoolFilter) for processing business logic.
- 
- The SimpleServiceRegistry adds IoThreadPoolFilter and ProtocolThreadPoolFilter which is
adequate for applications that require high-scalability by default.  If you want to use your
own threading model, please refer to the SimpleServiceRegistry source code and initialize
Acceptors by yourself.  It is, of course, a trivial task.
- 
- {{{
- IoThreadPoolFilter threadPool = new IoThreadPoolFilter();
- threadPool.start();
- 
- IoAcceptor acceptor = new SocketAcceptor();
- acceptor.getFilterChain().addLast( "threadPool", threadPool );
- 
- ProtocolThreadPoolFilter threadPool2 = new ProtocolThreadPoolFilter();
- threadPool2.start();
- 
- ProtocolAcceptor acceptor2 = new IoProtocolAcceptor( acceptor );
- acceptor2.getFilterChain().addLast( "threadPool", threadPool2 );
- 
- ...
- 
- threadPool2.stop();
- threadPool.stop();
- }}}
- 
- 
- === More Complex Protocols ===
- 
- ‘Reverser’ example is still too simple compared to other complex protocols.  There should
be dozens of message types, and their codec is required to make the server work.  MINA provides
the following utility classes to help you:
- 
-   * DemuxingProtocolHandler
-   * DemuxingProtocolCodecFactory
- 
- Please refer to the JavaDocs for more details.
- 
- === In-VM Pipe Communication ===
- 
- You must have learned that protocol layer is built on top of I/O layer, but it is not really
true.  Though we usually use protocol layer that wraps I/O layer, there is a special implementation
of protocol layer called as ‘in-VM pipe communication’.
- 
- Let’s assume that you implement a SMTP server and a Spam Filter server in MINA.  The SMTP
server will possibly communicate with the Spam Filter server to detect spam messages or any
clients which are listed in the RBL.  If these two servers are in the same Java VM, an I/O
layer is unnecessary; you can simply bypass encoding and decoding of message objects.  In-VM
pipe communication enables you to use the same code regardless of whether spam filter server
resides in the same VM or not.
- 
- Please refer to the ‘Tennis’ example in the source distribution.
- 
- == How to Contribute ==
- 
- We want MINA to evolve actively, reacting to user requests, and therefore we need as much
feedback from you as possible.  The Apache Directory team will strive to satisfy all possible
use cases of MINA.  Please feel free to contact us.
- 
- === How to Contact Us ===
- 
-   * Mailing list: dev@directory.apache.org (Please use ‘[mina]’ prefix)
-   * Issue tracker: http://issues.apache.org/jira/browse/DIRMINA
- 
- === How to Report Bugs ===
- 
- You can report any bugs found from MINA to our issue tracker page.  Please attach any test
cases that can reproduce your issue if possible.
- 
- === How Issues ===
- 
- Any patches and comments are welcome!  You can browse the list of unresolved issues in JIRA:
- 
-   * http://issues.apache.org/jira/browse/DIRMINA
- 
- Or, you could do some performance benchmarks on MINA and tune it.
- 
- == Acknowledgements ==
- 
- MINA couldn’t exist without strong support of many contributors:
- 
-   * The Apache Directory team for letting me join the team
-   * All users of Netty2 forum and dev@directory.apache.org for great feedbacks
-   * Jan Andersson and his team for SSLFilter
-   * Vel Pandian for enabling client mode for SSLFilter
-   * Vinod Panicker for performance benchmark and active feedbacks
- 

Mime
View raw message