The codec framework
This chapter covers
- An overview of decoders, encoders and codecs
- Netty’s codec classes
What is a codec?
This conversion logic is handled by a codec, which consists of an encoder and a decoder, each of which transforms a stream of bytes from one format to another.
Decoders
These classes cover two distinct use cases:
- Decoding bytes to messages —
ByteToMessageDecoder
andReplayingDecoder
- Decoding one message type to another —
MessageToMessageDecoder
Abstract class ByteToMessageDecoder
The following table shows two most important methods in ByteToMessageDecoder
API.
To decode the byte stream, you’ll extend ByteToMessageDecoder
. The design is illustrated in figure 10.1.
This listing shows the code for ToIntegerDecoder
.
Reference counting in codecs
once a message has been encoded or decoded, it will automatically be released by a call toReferenceCountUtil.release(message)
. If you need to keep a reference for later use you can callReferenceCountUtil.retain(message)
. This increments the reference count, preventing the message from being released.
Abstract class ReplayingDecoder
The full declaration of this class is1
public abstract class ReplayingDecoder<S> extends ByteToMessageDecoder
The parameter S
specifies the type to be used for state management, where Void
indicates that none is to be performed. The following listing shows a reimplementation of ToIntegerDecoder
based on ReplayingDecoder
.
Please take note of these aspects of ReplayingDecoderBuffer
:
- Not all
ByteBuf
operations are supported. If an unsupported method is called, anUnsupportedOperationException
will be thrown. ReplayingDecoder
is slightly slower thanByteToMessageDecoder
Here’s a simple guideline: use ByteToMessageDecoder
if it doesn’t introduce excessive complexity; otherwise, use ReplayingDecoder
.
More decoders
The following classes handle more complex use cases:
io.netty.handler.codec.LineBasedFrameDecoder
— This class, used internally by Netty, uses end-of-line control characters (\n
or\r\n
) to parse the message data.io.netty.handler.codec.http.HttpObjectDecoder
— A decoder for HTTP data.
Abstract class MessageToMessageDecoder
In this section we’ll explain how to convert between message formats using the abstract base class1
2public abstract class MessageToMessageDecoder<I>
extends ChannelInboundHandlerAdapter
The parameter I
specifies the type of the input msg argument to decode()
, which is the only method you have to implement. The following table shows the details of this method.
The design of IntegerToStringDecoder
is illustrated in figure 10.2.
The following listing is the implementation of IntegerToStringDecoder
.
HttpObjectAggregator
For a more complex example, please examine the classio.netty.handler.codec.http.HttpObjectAggregator
, which extendsMessageToMessageDecoder<HttpObject>
.
Class TooLongFrameException
Netty provides a TooLongFrameException
, which is intended to be thrown by decoders if a frame exceeds a specified size limit.
Listing 10.4 shows how a ByteToMessageDecoder
can make use of TooLongFrameException
to notify other ChannelHandlers
in the ChannelPipeline
about the occurrence of a frame-size overrun.
Encoders
Abstract class MessageToByteEncoder
The following table shows the MessageToByteEncoder
API.
You may have noticed that this class has only one method, while decoders have two. The reason is that decoders often need to produce a last message after the Channel
has closed (hence the decodeLast()
method).
Figure 10.3 shows a ShortToByteEncoder
.
The implementation of ShortToByteEncoder
is shown in the following listing.
Netty provides several specializations of MessageToByteEncoder
upon which you can base your own implementations. The class WebSocket08FrameEncoder
provides a good practical example. You’ll find it in the package io.netty.handler.codec.http.websocketx
.
Abstract class MessageToMessageEncoder
The following table shows the MessageToMessageEncoder
API.
Figure 10.4 shows a IntegerToStringEncoder
.
As shown in the next listing, the encoder adds a String
representation of each outbound Integer
to the List
.
For an interesting specialized use of MessageToMessageEncoder
, look at the class io.netty.handler.codec.protobuf.ProtobufEncoder
, which handles data formats defined by Google’s Protocol Buffers specification.
Abstract codec classes
Abstract class ByteToMessageCodec
The following table shows the ByteToMessageCodec
API.
Any request/response protocol could be a good candidate for using the ByteToMessageCodec
.
Abstract class MessageToMessageCodec
MessageToMessageCodec
is a parameterized class, defined as follows:1
public abstract class MessageToMessageCodec<INBOUND_IN,OUTBOUND_IN>
The important methods are listed in the following table.
WebSocket protocol
WebSocket
is a recent protocol that enables full bidirectional communications between web browsers and servers.
Class CombinedChannelDuplexHandler
CombinedChannelDuplexHandler
declared as1
2public class CombinedChannelDuplexHandler
<I extends ChannelInboundHandler, O extends ChannelOutboundHandler>
First, examine ByteToCharDecoder
in the following listing.
The following list shows CharToByteEncoder
, which converts Characters
back to bytes.
Now that we have a decoder and encoder, we’ll combine them to build up a codec. This listing shows how this is done.