This topic has not yet been written. The content below is from the topic description.
First, let us define a new type called UnixTime. package org.jboss.netty.example.time; import java.util.Date; public class UnixTime { private final int value; public UnixTime(int value) { this.value = value; } public int getValue() { return value; } @Override public String toString() { return new Date(value * 1000L).toString(); } } We can now revise the TimeDecoder to return a UnixTime instead of a ChannelBuffer. @Override protected Object decode( ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) { if (buffer.readableBytes() < 4) { return null; } return new UnixTime(buffer.readInt()); } FrameDecoder and ReplayingDecoder allow you to return an object of any type. If they were restricted to return only a ChannelBuffer, we would have to insert another ChannelHandler which transforms a ChannelBuffer into a UnixTime. With the updated decoder, the TimeClientHandler does not use ChannelBuffer anymore: @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { UnixTime m = (UnixTime) e.getMessage(); System.out.println(m); e.getChannel().close(); } Much simpler and elegant, right? The same technique can be applied on the server side. Let us update the TimeServerHandler first this time: @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) { UnixTime time = new UnixTime(System.currentTimeMillis() / 1000); ChannelFuture f = e.getChannel().write(time); f.addListener(ChannelFutureListener.CLOSE); } Now, the only missing piece is an encoder, which is an implementation of ChannelHandler that translates a UnixTime back into a ChannelBuffer. It's much simpler than writing a decoder because there's no need to deal with packet fragmentation and assembly when encoding a message. package org.jboss.netty.example.time; import static org.jboss.netty.buffer.ChannelBuffers.*; public class TimeEncoder extends SimpleChannelHandler { public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) { UnixTime time = (UnixTime) e.getMessage(); ChannelBuffer buf = buffer(4); buf.writeInt(time.getValue()); Channels.write(ctx, e.getFuture(), buf); } } An encoder overrides the writeRequested method to intercept a write request. Please note that the MessageEvent parameter here is the same type which was specified in messageReceived but they are interpreted differently. A ChannelEvent can be either an upstream or downstream event depending on the direction where the event flows. For instance, a MessageEvent can be an upstream event when called for messageReceived or a downstream event when called for writeRequested. Please refer to the API reference to learn more about the difference between a upstream event and a downstream event. Once done with transforming a POJO into a ChannelBuffer, you should forward the new buffer to the previous ChannelDownstreamHandler in the ChannelPipeline. Channels provides various helper methods which generates and sends a ChannelEvent. In this example, Channels.write(...) method creates a new MessageEvent and sends it to the previous ChannelDownstreamHandler in the ChannelPipeline. On the other hand, it is a good idea to use static imports for Channels: import static org.jboss.netty.channel.Channels.*; ... ChannelPipeline pipeline = pipeline(); write(ctx, e.getFuture(), buf); fireChannelDisconnected(ctx); The last task left is to insert a TimeEncoder into the ChannelPipeline on the server side, and it is left as a trivial exercise.