Interface ChannelPipeline
- All Known Implementing Classes:
AbstractCodecEmbedder.EmbeddedChannelPipeline,DefaultChannelPipeline
ChannelHandlers which handles or intercepts
ChannelEvents of a Channel. ChannelPipeline
implements an advanced form of the
Intercepting
Filter pattern to give a user full control over how an event is handled
and how the ChannelHandlers in the pipeline interact with each other.
Creation of a pipeline
For each new channel, a new pipeline must be created and attached to the channel. Once attached, the coupling between the channel and the pipeline is permanent; the channel cannot attach another pipeline to it nor detach the current pipeline from it.
The recommended way to create a new pipeline is to use the helper methods in
Channels rather than calling an individual implementation's
constructor:
import static org.jboss.netty.channel.Channels.*;ChannelPipelinepipeline = pipeline(); // same with Channels.pipeline()
How an event flows in a pipeline
The following diagram describes howChannelEvents are processed by
ChannelHandlers in a ChannelPipeline typically.
A ChannelEvent can be handled by either a ChannelUpstreamHandler
or a ChannelDownstreamHandler and be forwarded to the closest
handler by calling ChannelHandlerContext.sendUpstream(ChannelEvent)
or ChannelHandlerContext.sendDownstream(ChannelEvent). The meaning
of the event is interpreted somewhat differently depending on whether it is
going upstream or going downstream. Please refer to ChannelEvent for
more information.
I/O Request
via Channel or
ChannelHandlerContext
|
+----------------------------------------+---------------+
| ChannelPipeline | |
| \|/ |
| +----------------------+ +-----------+------------+ |
| | Upstream Handler N | | Downstream Handler 1 | |
| +----------+-----------+ +-----------+------------+ |
| /|\ | |
| | \|/ |
| +----------+-----------+ +-----------+------------+ |
| | Upstream Handler N-1 | | Downstream Handler 2 | |
| +----------+-----------+ +-----------+------------+ |
| /|\ . |
| . . |
| [ sendUpstream() ] [ sendDownstream() ] |
| [ + INBOUND data ] [ + OUTBOUND data ] |
| . . |
| . \|/ |
| +----------+-----------+ +-----------+------------+ |
| | Upstream Handler 2 | | Downstream Handler M-1 | |
| +----------+-----------+ +-----------+------------+ |
| /|\ | |
| | \|/ |
| +----------+-----------+ +-----------+------------+ |
| | Upstream Handler 1 | | Downstream Handler M | |
| +----------+-----------+ +-----------+------------+ |
| /|\ | |
+-------------+--------------------------+---------------+
| \|/
+-------------+--------------------------+---------------+
| | | |
| [ Socket.read() ] [ Socket.write() ] |
| |
| Netty Internal I/O Threads (Transport Implementation) |
+--------------------------------------------------------+
An upstream event is handled by the upstream handlers in the bottom-up
direction as shown on the left side of the diagram. An upstream handler
usually handles the inbound data generated by the I/O thread on the bottom
of the diagram. The inbound data is often read from a remote peer via the
actual input operation such as InputStream.read(byte[]).
If an upstream event goes beyond the top upstream handler, it is discarded
silently.
A downstream event is handled by the downstream handler in the top-down
direction as shown on the right side of the diagram. A downstream handler
usually generates or transforms the outbound traffic such as write requests.
If a downstream event goes beyond the bottom downstream handler, it is
handled by an I/O thread associated with the Channel. The I/O thread
often performs the actual output operation such as OutputStream.write(byte[]).
For example, let us assume that we created the following pipeline:
In the example above, the class whose name starts withChannelPipelinep =Channels.pipeline(); p.addLast("1", new UpstreamHandlerA()); p.addLast("2", new UpstreamHandlerB()); p.addLast("3", new DownstreamHandlerA()); p.addLast("4", new DownstreamHandlerB()); p.addLast("5", new UpstreamHandlerX());
Upstream means
it is an upstream handler. The class whose name starts with
Downstream means it is a downstream handler.
In the given example configuration, the handler evaluation order is 1, 2, 3,
4, 5 when an event goes upstream. When an event goes downstream, the order
is 5, 4, 3, 2, 1. On top of this principle, ChannelPipeline skips
the evaluation of certain handlers to shorten the stack depth:
- 3 and 4 don't implement
ChannelUpstreamHandler, and therefore the actual evaluation order of an upstream event will be: 1, 2, and 5. - 1, 2, and 5 don't implement
ChannelDownstreamHandler, and therefore the actual evaluation order of a downstream event will be: 4 and 3. - If 5 extended
SimpleChannelHandlerwhich implements bothChannelUpstreamHandlerandChannelDownstreamHandler, the evaluation order of an upstream and a downstream event could be 125 and 543 respectively.
Building a pipeline
A user is supposed to have one or more ChannelHandlers in a
pipeline to receive I/O events (e.g. read) and to request I/O operations
(e.g. write and close). For example, a typical server will have the following
handlers in each channel's pipeline, but your mileage may vary depending on
the complexity and characteristics of the protocol and business logic:
- Protocol Decoder - translates binary data (e.g.
ChannelBuffer) into a Java object. - Protocol Encoder - translates a Java object into binary data.
ExecutionHandler- applies a thread model.- Business Logic Handler - performs the actual business logic (e.g. database access).
ChannelPipelinepipeline =Channels.pipeline(); pipeline.addLast("decoder", new MyProtocolDecoder()); pipeline.addLast("encoder", new MyProtocolEncoder()); pipeline.addLast("executor", newExecutionHandler( newOrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576))); pipeline.addLast("handler", new MyBusinessLogicHandler());
Thread safety
A ChannelHandler can be added or removed at any time because a
ChannelPipeline is thread safe. For example, you can insert a
SslHandler when sensitive information is about to be exchanged,
and remove it after the exchange.
Pitfall
Due to the internal implementation detail of the current default
ChannelPipeline, the following code does not work as expected if
FirstHandler is the last handler in the pipeline:
public class FirstHandler extendsTo implement the expected behavior, you have to add SecondHandler before the removal or make sure there is at least one more handler between FirstHandler and SecondHandler.SimpleChannelUpstreamHandler{@Overridepublic void messageReceived(ChannelHandlerContextctx,MessageEvente) { // Remove this handler from the pipeline, ctx.getPipeline().remove(this); // And let SecondHandler handle the current event. ctx.getPipeline().addLast("2nd", new SecondHandler()); ctx.sendUpstream(e); } }
-
Method Summary
Modifier and TypeMethodDescriptionvoidaddAfter(String baseName, String name, ChannelHandler handler) Inserts aChannelHandlerafter an existing handler of this pipeline.voidaddBefore(String baseName, String name, ChannelHandler handler) Inserts aChannelHandlerbefore an existing handler of this pipeline.voidaddFirst(String name, ChannelHandler handler) Inserts aChannelHandlerat the first position of this pipeline.voidaddLast(String name, ChannelHandler handler) Appends aChannelHandlerat the last position of this pipeline.voidattach(Channel channel, ChannelSink sink) Attaches this pipeline to the specifiedChannelandChannelSink.Schedules the specified task to be executed in the I/O thread associated with this pipeline'sChannel.<T extends ChannelHandler>
TReturns theChannelHandlerof the specified type in this pipeline.Returns theChannelHandlerwith the specified name in this pipeline.Returns theChannelthat this pipeline is attached to.getContext(Class<? extends ChannelHandler> handlerType) Returns the context object of theChannelHandlerof the specified type in this pipeline.getContext(String name) Returns the context object of theChannelHandlerwith the specified name in this pipeline.getContext(ChannelHandler handler) Returns the context object of the specifiedChannelHandlerin this pipeline.getFirst()Returns the firstChannelHandlerin this pipeline.getLast()Returns the lastChannelHandlerin this pipeline.getNames()Returns theListof the handler names.getSink()Returns theChannelSinkthat this pipeline is attached to.booleanReturnstrueif and only if this pipeline is attached to aChannel.<T extends ChannelHandler>
TRemoves theChannelHandlerof the specified type from this pipelineRemoves theChannelHandlerwith the specified name from this pipeline.voidremove(ChannelHandler handler) Removes the specifiedChannelHandlerfrom this pipeline.Removes the firstChannelHandlerin this pipeline.Removes the lastChannelHandlerin this pipeline.<T extends ChannelHandler>
Treplace(Class<T> oldHandlerType, String newName, ChannelHandler newHandler) Replaces theChannelHandlerof the specified type with a new handler in this pipeline.replace(String oldName, String newName, ChannelHandler newHandler) Replaces theChannelHandlerof the specified name with a new handler in this pipeline.voidreplace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler) Replaces the specifiedChannelHandlerwith a new handler in this pipeline.voidSends the specifiedChannelEventto the lastChannelDownstreamHandlerin this pipeline.voidSends the specifiedChannelEventto the firstChannelUpstreamHandlerin this pipeline.toMap()Converts this pipeline into an orderedMapwhose keys are handler names and whose values are handlers.
-
Method Details
-
addFirst
Inserts aChannelHandlerat the first position of this pipeline.- Parameters:
name- the name of the handler to insert firsthandler- the handler to insert first- Throws:
IllegalArgumentException- if there's an entry with the same name already in the pipelineNullPointerException- if the specified name or handler isnull
-
addLast
Appends aChannelHandlerat the last position of this pipeline.- Parameters:
name- the name of the handler to appendhandler- the handler to append- Throws:
IllegalArgumentException- if there's an entry with the same name already in the pipelineNullPointerException- if the specified name or handler isnull
-
addBefore
Inserts aChannelHandlerbefore an existing handler of this pipeline.- Parameters:
baseName- the name of the existing handlername- the name of the handler to insert beforehandler- the handler to insert before- Throws:
NoSuchElementException- if there's no such entry with the specifiedbaseNameIllegalArgumentException- if there's an entry with the same name already in the pipelineNullPointerException- if the specified baseName, name, or handler isnull
-
addAfter
Inserts aChannelHandlerafter an existing handler of this pipeline.- Parameters:
baseName- the name of the existing handlername- the name of the handler to insert afterhandler- the handler to insert after- Throws:
NoSuchElementException- if there's no such entry with the specifiedbaseNameIllegalArgumentException- if there's an entry with the same name already in the pipelineNullPointerException- if the specified baseName, name, or handler isnull
-
remove
Removes the specifiedChannelHandlerfrom this pipeline.- Throws:
NoSuchElementException- if there's no such handler in this pipelineNullPointerException- if the specified handler isnull
-
remove
Removes theChannelHandlerwith the specified name from this pipeline.- Returns:
- the removed handler
- Throws:
NoSuchElementException- if there's no such handler with the specified name in this pipelineNullPointerException- if the specified name isnull
-
remove
Removes theChannelHandlerof the specified type from this pipeline- Type Parameters:
T- the type of the handler- Parameters:
handlerType- the type of the handler- Returns:
- the removed handler
- Throws:
NoSuchElementException- if there's no such handler of the specified type in this pipelineNullPointerException- if the specified handler type isnull
-
removeFirst
ChannelHandler removeFirst()Removes the firstChannelHandlerin this pipeline.- Returns:
- the removed handler
- Throws:
NoSuchElementException- if this pipeline is empty
-
removeLast
ChannelHandler removeLast()Removes the lastChannelHandlerin this pipeline.- Returns:
- the removed handler
- Throws:
NoSuchElementException- if this pipeline is empty
-
replace
Replaces the specifiedChannelHandlerwith a new handler in this pipeline.- Throws:
NoSuchElementException- if the specified old handler does not exist in this pipelineIllegalArgumentException- if a handler with the specified new name already exists in this pipeline, except for the handler to be replacedNullPointerException- if the specified old handler, new name, or new handler isnull
-
replace
Replaces theChannelHandlerof the specified name with a new handler in this pipeline.- Returns:
- the removed handler
- Throws:
NoSuchElementException- if the handler with the specified old name does not exist in this pipelineIllegalArgumentException- if a handler with the specified new name already exists in this pipeline, except for the handler to be replacedNullPointerException- if the specified old handler, new name, or new handler isnull
-
replace
<T extends ChannelHandler> T replace(Class<T> oldHandlerType, String newName, ChannelHandler newHandler) Replaces theChannelHandlerof the specified type with a new handler in this pipeline.- Returns:
- the removed handler
- Throws:
NoSuchElementException- if the handler of the specified old handler type does not exist in this pipelineIllegalArgumentException- if a handler with the specified new name already exists in this pipeline, except for the handler to be replacedNullPointerException- if the specified old handler, new name, or new handler isnull
-
getFirst
ChannelHandler getFirst()Returns the firstChannelHandlerin this pipeline.- Returns:
- the first handler.
nullif this pipeline is empty.
-
getLast
ChannelHandler getLast()Returns the lastChannelHandlerin this pipeline.- Returns:
- the last handler.
nullif this pipeline is empty.
-
get
Returns theChannelHandlerwith the specified name in this pipeline.- Returns:
- the handler with the specified name.
nullif there's no such handler in this pipeline.
-
get
Returns theChannelHandlerof the specified type in this pipeline.- Returns:
- the handler of the specified handler type.
nullif there's no such handler in this pipeline.
-
getContext
Returns the context object of the specifiedChannelHandlerin this pipeline.- Returns:
- the context object of the specified handler.
nullif there's no such handler in this pipeline.
-
getContext
Returns the context object of theChannelHandlerwith the specified name in this pipeline.- Returns:
- the context object of the handler with the specified name.
nullif there's no such handler in this pipeline.
-
getContext
Returns the context object of theChannelHandlerof the specified type in this pipeline.- Returns:
- the context object of the handler of the specified type.
nullif there's no such handler in this pipeline.
-
sendUpstream
Sends the specifiedChannelEventto the firstChannelUpstreamHandlerin this pipeline.- Throws:
NullPointerException- if the specified event isnull
-
sendDownstream
Sends the specifiedChannelEventto the lastChannelDownstreamHandlerin this pipeline.- Throws:
NullPointerException- if the specified event isnull
-
execute
Schedules the specified task to be executed in the I/O thread associated with this pipeline'sChannel. -
getChannel
Channel getChannel()Returns theChannelthat this pipeline is attached to.- Returns:
- the channel.
nullif this pipeline is not attached yet.
-
getSink
ChannelSink getSink()Returns theChannelSinkthat this pipeline is attached to.- Returns:
- the sink.
nullif this pipeline is not attached yet.
-
attach
Attaches this pipeline to the specifiedChannelandChannelSink. Once a pipeline is attached, it can't be detached nor attached again.- Throws:
IllegalStateException- if this pipeline is attached already
-
isAttached
boolean isAttached()Returnstrueif and only if this pipeline is attached to aChannel. -
getNames
Returns theListof the handler names. -
toMap
Map<String,ChannelHandler> toMap()Converts this pipeline into an orderedMapwhose keys are handler names and whose values are handlers.
-