Interface ChannelHandler

All Known Subinterfaces:
ChannelInboundHandler, ChannelOutboundHandler, WebSocketFrameDecoder, WebSocketFrameEncoder
All Known Implementing Classes:
AbstractBinaryMemcacheDecoder, AbstractBinaryMemcacheEncoder, AbstractMemcacheObjectAggregator, AbstractMemcacheObjectDecoder, AbstractMemcacheObjectEncoder, AbstractRemoteAddressFilter, AbstractSniHandler, AbstractTrafficShapingHandler, ApplicationProtocolNegotiationHandler, Base64Decoder, Base64Encoder, BinaryMemcacheClientCodec, BinaryMemcacheClientCodec.Decoder, BinaryMemcacheClientCodec.Encoder, BinaryMemcacheObjectAggregator, BinaryMemcacheRequestDecoder, BinaryMemcacheRequestEncoder, BinaryMemcacheResponseDecoder, BinaryMemcacheResponseEncoder, BinaryMemcacheServerCodec, ByteArrayDecoder, ByteArrayEncoder, ByteToMessageCodec, ByteToMessageCodec.Encoder, ByteToMessageDecoder, Bzip2Decoder, Bzip2Encoder, ChannelDuplexHandler, ChannelHandlerAdapter, ChannelInboundHandlerAdapter, ChannelInitializer, ChannelOutboundHandlerAdapter, ChannelTrafficShapingHandler, ChunkedWriteHandler, CleartextHttp2ServerUpgradeHandler, CombinedChannelDuplexHandler, CompatibleObjectEncoder, CorsHandler, DatagramDnsQueryDecoder, DatagramDnsQueryEncoder, DatagramDnsResponseDecoder, DatagramDnsResponseEncoder, DatagramPacketDecoder, DatagramPacketEncoder, DefaultChannelPipeline.HeadContext, DefaultChannelPipeline.TailContext, DeflateDecoder, DeflateEncoder, DelimiterBasedFrameDecoder, DnsNameResolver.DnsResponseHandler, DynamicAddressConnectHandler, FastLzFrameDecoder, FastLzFrameEncoder, FixedLengthFrameDecoder, FlowControlHandler, FlushConsolidationHandler, GlobalChannelTrafficShapingHandler, GlobalTrafficShapingHandler, HAProxyMessageDecoder, HAProxyMessageEncoder, Http2ChannelDuplexHandler, Http2ConnectionHandler, Http2FrameCodec, Http2FrameLogger, Http2MultiplexCodec, Http2MultiplexHandler, Http2StreamFrameToHttpObjectCodec, HttpClientCodec, HttpClientCodec.Decoder, HttpClientCodec.Encoder, HttpClientUpgradeHandler, HttpContentCompressor, HttpContentDecoder, HttpContentDecompressor, HttpContentEncoder, HttpObjectAggregator, HttpObjectDecoder, HttpObjectEncoder, HttpProxyHandler, HttpProxyHandler.HttpClientCodecWrapper, HttpRequestDecoder, HttpRequestEncoder, HttpResponseDecoder, HttpResponseEncoder, HttpServerCodec, HttpServerCodec.HttpServerRequestDecoder, HttpServerCodec.HttpServerResponseEncoder, HttpServerExpectContinueHandler, HttpServerKeepAliveHandler, HttpServerUpgradeHandler, HttpToHttp2ConnectionHandler, IdleStateHandler, InboundHttpToHttp2Adapter, IpSubnetFilter, JdkZlibDecoder, JdkZlibEncoder, JsonObjectDecoder, JZlibDecoder, JZlibEncoder, LengthFieldBasedFrameDecoder, LengthFieldPrepender, LineBasedFrameDecoder, LineEncoder, LoggingHandler, MessageAggregator, MessageToByteEncoder, MessageToMessageCodec, MessageToMessageDecoder, MessageToMessageEncoder, MqttDecoder, MqttEncoder, ObjectDecoder, ObjectEncoder, OcspClient.Initializer, OcspClientHandler, OcspHttpHandler, OcspServerCertificateValidator, OptionalSslHandler, PcapWriteHandler, PerFrameDeflateDecoder, PerFrameDeflateEncoder, PerMessageDeflateDecoder, PerMessageDeflateEncoder, ProxyHandler, ReadTimeoutHandler, RedisArrayAggregator, RedisBulkStringAggregator, RedisDecoder, RedisEncoder, ReplayingDecoder, ResolveAddressHandler, RtspDecoder, RtspEncoder, RtspObjectDecoder, RtspObjectEncoder, RtspRequestDecoder, RtspRequestEncoder, RtspResponseDecoder, RtspResponseEncoder, RuleBasedIpFilter, SctpInboundByteStreamHandler, SctpMessageCompletionHandler, SctpMessageToMessageDecoder, SctpOutboundByteStreamHandler, ServerBootstrap.ServerBootstrapAcceptor, SimpleChannelInboundHandler, SimpleUserEventChannelHandler, SmtpRequestEncoder, SmtpResponseDecoder, SnappyFramedDecoder, SnappyFrameDecoder, SnappyFramedEncoder, SnappyFrameEncoder, SniHandler, Socks4ClientDecoder, Socks4ClientEncoder, Socks4ProxyHandler, Socks4ServerDecoder, Socks4ServerEncoder, Socks5ClientEncoder, Socks5CommandRequestDecoder, Socks5CommandResponseDecoder, Socks5InitialRequestDecoder, Socks5InitialResponseDecoder, Socks5PasswordAuthRequestDecoder, Socks5PasswordAuthResponseDecoder, Socks5ProxyHandler, Socks5ServerEncoder, SocksAuthRequestDecoder, SocksAuthResponseDecoder, SocksCmdRequestDecoder, SocksCmdResponseDecoder, SocksInitRequestDecoder, SocksInitResponseDecoder, SocksMessageEncoder, SocksPortUnificationServerHandler, SpdyFrameCodec, SpdyHttpCodec, SpdyHttpDecoder, SpdyHttpEncoder, SpdyHttpResponseStreamIdHandler, SpdySessionHandler, SslClientHelloHandler, SslHandler, SslMasterKeyHandler, SslMasterKeyHandler.WiresharkSslMasterKeyHandler, StompSubframeAggregator, StompSubframeDecoder, StompSubframeEncoder, StringDecoder, StringEncoder, TcpDnsQueryDecoder, TcpDnsQueryEncoder, TcpDnsResponseDecoder, TcpDnsResponseEncoder, UniqueIpFilter, Utf8FrameValidator, WebSocket00FrameDecoder, WebSocket00FrameEncoder, WebSocket07FrameDecoder, WebSocket07FrameEncoder, WebSocket08FrameDecoder, WebSocket08FrameEncoder, WebSocket13FrameDecoder, WebSocket13FrameEncoder, WebSocketClientCompressionHandler, WebSocketClientExtensionHandler, WebSocketClientProtocolHandler, WebSocketClientProtocolHandshakeHandler, WebSocketExtensionDecoder, WebSocketExtensionEncoder, WebSocketFrameAggregator, WebSocketProtocolHandler, WebSocketServerCompressionHandler, WebSocketServerExtensionHandler, WebSocketServerProtocolHandler, WebSocketServerProtocolHandshakeHandler, WriteTimeoutHandler, XmlDecoder, XmlFrameDecoder, ZlibDecoder, ZlibEncoder

public interface ChannelHandler
Handles an I/O event or intercepts an I/O operation, and forwards it to its next handler in its ChannelPipeline.

Sub-types

ChannelHandler itself does not provide many methods, but you usually have to implement one of its subtypes:

Alternatively, the following adapter classes are provided for your convenience:

For more information, please refer to the documentation of each subtype.

The context object

A ChannelHandler is provided with a ChannelHandlerContext object. A ChannelHandler is supposed to interact with the ChannelPipeline it belongs to via a context object. Using the context object, the ChannelHandler can pass events upstream or downstream, modify the pipeline dynamically, or store the information (using AttributeKeys) which is specific to the handler.

State management

A ChannelHandler often needs to store some stateful information. The simplest and recommended approach is to use member variables:
 public interface Message {
     // your methods here
 }

 public class DataServerHandler extends SimpleChannelInboundHandler<Message> {

     private boolean loggedIn;

     @Override
     public void channelRead0(ChannelHandlerContext ctx, Message message) {
         if (message instanceof LoginMessage) {
             authenticate((LoginMessage) message);
             loggedIn = true;
         } else (message instanceof GetDataMessage) {
             if (loggedIn) {
                 ctx.writeAndFlush(fetchSecret((GetDataMessage) message));
             } else {
                 fail();
             }
         }
     }
     ...
 }
 
Because the handler instance has a state variable which is dedicated to one connection, you have to create a new handler instance for each new channel to avoid a race condition where an unauthenticated client can get the confidential information:
 // Create a new handler instance per channel.
 // See ChannelInitializer.initChannel(Channel).
 public class DataServerInitializer extends ChannelInitializer<Channel> {
     @Override
     public void initChannel(Channel channel) {
         channel.pipeline().addLast("handler", new DataServerHandler());
     }
 }

 

Using AttributeKeys

Although it's recommended to use member variables to store the state of a handler, for some reason you might not want to create many handler instances. In such a case, you can use AttributeKeys which is provided by ChannelHandlerContext:
 public interface Message {
     // your methods here
 }

 @Sharable
 public class DataServerHandler extends SimpleChannelInboundHandler<Message> {
     private final AttributeKey<Boolean> auth =
           AttributeKey.valueOf("auth");

     @Override
     public void channelRead(ChannelHandlerContext ctx, Message message) {
         Attribute<Boolean> attr = ctx.attr(auth);
         if (message instanceof LoginMessage) {
             authenticate((LoginMessage) o);
             attr.set(true);
         } else (message instanceof GetDataMessage) {
             if (Boolean.TRUE.equals(attr.get())) {
                 ctx.writeAndFlush(fetchSecret((GetDataMessage) o));
             } else {
                 fail();
             }
         }
     }
     ...
 }
 
Now that the state of the handler is attached to the ChannelHandlerContext, you can add the same handler instance to different pipelines:
 public class DataServerInitializer extends ChannelInitializer<Channel> {

     private static final DataServerHandler SHARED = new DataServerHandler();

     @Override
     public void initChannel(Channel channel) {
         channel.pipeline().addLast("handler", SHARED);
     }
 }
 

The @Sharable annotation

In the example above which used an AttributeKey, you might have noticed the @Sharable annotation.

If a ChannelHandler is annotated with the @Sharable annotation, it means you can create an instance of the handler just once and add it to one or more ChannelPipelines multiple times without a race condition.

If this annotation is not specified, you have to create a new handler instance every time you add it to a pipeline because it has unshared state such as member variables.

This annotation is provided for documentation purpose, just like the JCIP annotations.

Additional resources worth reading

Please refer to the ChannelHandler, and ChannelPipeline to find out more about inbound and outbound operations, what fundamental differences they have, how they flow in a pipeline, and how to handle the operation in your application.