JBoss Netty tutorial

User Rating: 4 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Inactive
 

The Netty project provides an asynchronous event-driven network application framework and tooling for the rapid development of maintainable high-performance high-scalability protocol servers and clients. In this tutorial we we will show how to use it to enhance the application server capabilities.

 

So, Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server development.

 'Quick and easy' does not mean that a resulting application will suffer from a maintainability or a performance issue. Netty has been designed carefully with the experiences earned from the implementation of a lot of protocols such as FTP, SMTP, HTTP, and various binary and text-based legacy protocols. As a result, Netty has succeeded to find a way to achieve ease of development, performance, stability, and flexibility without a compromise.

In the product documentation you can find some basic and advanced examples of Netty Servers: our aim is to show how to run a basic Server example at Server startup. JBoss AS by itself does not provide a custom Startup class, however this can be easily achieved by deploying an EJB 3.1 compatible marked with @Startup


import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;

import com.sample.NettyServer;

@Singleton(name="NettyEJB")
@Startup
public class NettyEJB {
@PostConstruct

        void init() {

         try {
                new NettyServer().startServer();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
}

And here's a minimal Netty Echo server which listen for requests on port 8888:

package com.sample;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.*;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

public class NettyServer {

    public void startServer() throws Exception {
        ChannelFactory factory =
            new NioServerSocketChannelFactory(
                    Executors.newCachedThreadPool(),
                    Executors.newCachedThreadPool());

        ServerBootstrap bootstrap = new ServerBootstrap(factory);

        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() {
                return Channels.pipeline(new EchoServerHandler());
            }
        });

        bootstrap.setOption("child.tcpNoDelay", true);
        bootstrap.setOption("child.keepAlive", true);

        bootstrap.bind(new InetSocketAddress(8888));
        System.out.println("Server Started!");
    }
}

ChannelFactory is a factory which creates and manages Socket Channels and its related resources. It processes all I/O requests and performs I/O to generate ChannelEvents. Netty provides various ChannelFactory implementations: in this example, we are using NioServerSocketChannelFactory.

Next, the ServerBootstrap is a helper class that sets up a server. The bootstrap class as it is does not provide any special functionalities. In particular we need to define what happens when a new connection is received.  Let's  create a new ChannelPipeline will be created by the specified ChannelPipelineFactory. The new pipeline contains the EchoServerHandler. In more complex applications, it is likely that you will add more handlers to the pipeline and extract this anonymous class into a top level class eventually.

EchoServerHandler extends SimpleChannelHandler, which is an implementation of ChannelHandler. SimpleChannelHandler provides various event handler methods that you can override. For now, it is just enough to extend SimpleChannelHandler rather than to implement the handler interfaces by yourself.
We override the messageReceived event handler method here. This method is called with a MessageEvent, which contains the received data, whenever new data is received from a client.


package com.sample;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;

public class EchoServerHandler extends SimpleChannelHandler { 

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { 
         ChannelBuffer  buf = (ChannelBuffer) e.getMessage();
            while(buf.readable()) {
                System.out.println((char) buf.readByte());
                System.out.flush();
            }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) { 
        e.getCause().printStackTrace();
        
        Channel ch = e.getChannel();
        ch.close();
    }
}

Follow us on Twitter