org.jboss.netty.channel
Interface ChannelPipeline

All Known Implementing Classes:
DefaultChannelPipeline, StaticChannelPipeline

public interface ChannelPipeline

A list of 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.*;
 ChannelPipeline pipeline = pipeline(); // same with Channels.pipeline()
 

How an event flows in a pipeline

The following diagram describes how ChannelEvents 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:

 ChannelPipeline p = 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());
 
In the example above, the class whose name starts with 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:

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:

  1. Protocol Decoder - translates binary data (e.g. ChannelBuffer) into a Java object.
  2. Protocol Encoder - translates a Java object into binary data.
  3. ExecutionHandler - applies a thread model.
  4. Business Logic Handler - performs the actual business logic (e.g. database access).
and it could be represented as shown in the following example:
 ChannelPipeline pipeline = Channels.pipeline();
 pipeline.addLast("decoder", new MyProtocolDecoder());
 pipeline.addLast("encoder", new MyProtocolEncoder());
 pipeline.addLast("executor", new ExecutionHandler(new OrderedMemoryAwareThreadPoolExecutor(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 extends SimpleChannelUpstreamHandler {

     @Override
     public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
         // 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);
     }
 }
 
To 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.

Version:
$Rev: 2153 $, $Date: 2010-02-17 17:24:25 +0900 (Wed, 17 Feb 2010) $
Author:
The Netty Project, Trustin Lee

Method Summary
 void addAfter(String baseName, String name, ChannelHandler handler)
          Inserts a ChannelHandler after an existing handler of this pipeline.
 void addBefore(String baseName, String name, ChannelHandler handler)
          Inserts a ChannelHandler before an existing handler of this pipeline.
 void addFirst(String name, ChannelHandler handler)
          Inserts a ChannelHandler at the first position of this pipeline.
 void addLast(String name, ChannelHandler handler)
          Appends a ChannelHandler at the last position of this pipeline.
 void attach(Channel channel, ChannelSink sink)
          Attaches this pipeline to the specified Channel and ChannelSink.
<T extends ChannelHandler>
T
get(Class<T> handlerType)
          Returns the ChannelHandler of the specified type in this pipeline.
 ChannelHandler get(String name)
          Returns the ChannelHandler with the specified name in this pipeline.
 Channel getChannel()
          Returns the Channel that this pipeline is attached to.
 ChannelHandlerContext getContext(ChannelHandler handler)
          Returns the context object of the specified ChannelHandler in this pipeline.
 ChannelHandlerContext getContext(Class<? extends ChannelHandler> handlerType)
          Returns the context object of the ChannelHandler of the specified type in this pipeline.
 ChannelHandlerContext getContext(String name)
          Returns the context object of the ChannelHandler with the specified name in this pipeline.
 ChannelHandler getFirst()
          Returns the first ChannelHandler in this pipeline.
 ChannelHandler getLast()
          Returns the last ChannelHandler in this pipeline.
 List<String> getNames()
          Returns the List of the handler names.
 ChannelSink getSink()
          Returns the ChannelSink that this pipeline is attached to.
 boolean isAttached()
          Returns true if and only if this pipeline is attached to a Channel.
 void remove(ChannelHandler handler)
          Removes the specified ChannelHandler from this pipeline.
<T extends ChannelHandler>
T
remove(Class<T> handlerType)
          Removes the ChannelHandler of the specified type from this pipeline
 ChannelHandler remove(String name)
          Removes the ChannelHandler with the specified name from this pipeline.
 ChannelHandler removeFirst()
          Removes the first ChannelHandler in this pipeline.
 ChannelHandler removeLast()
          Removes the last ChannelHandler in this pipeline.
 void replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler)
          Replaces the specified ChannelHandler with a new handler in this pipeline.
<T extends ChannelHandler>
T
replace(Class<T> oldHandlerType, String newName, ChannelHandler newHandler)
          Replaces the ChannelHandler of the specified type with a new handler in this pipeline.
 ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler)
          Replaces the ChannelHandler of the specified name with a new handler in this pipeline.
 void sendDownstream(ChannelEvent e)
          Sends the specified ChannelEvent to the last ChannelDownstreamHandler in this pipeline.
 void sendUpstream(ChannelEvent e)
          Sends the specified ChannelEvent to the first ChannelUpstreamHandler in this pipeline.
 Map<String,ChannelHandler> toMap()
          Converts this pipeline into an ordered Map whose keys are handler names and whose values are handlers.
 

Method Detail

addFirst

void addFirst(String name,
              ChannelHandler handler)
Inserts a ChannelHandler at the first position of this pipeline.

Parameters:
name - the name of the handler to insert first
handler - the handler to insert first
Throws:
IllegalArgumentException - if there's an entry with the same name already in the pipeline
NullPointerException - if the specified name or handler is null

addLast

void addLast(String name,
             ChannelHandler handler)
Appends a ChannelHandler at the last position of this pipeline.

Parameters:
name - the name of the handler to append
handler - the handler to append
Throws:
IllegalArgumentException - if there's an entry with the same name already in the pipeline
NullPointerException - if the specified name or handler is null

addBefore

void addBefore(String baseName,
               String name,
               ChannelHandler handler)
Inserts a ChannelHandler before an existing handler of this pipeline.

Parameters:
baseName - the name of the existing handler
name - the name of the handler to insert before
handler - the handler to insert before
Throws:
NoSuchElementException - if there's no such entry with the specified baseName
IllegalArgumentException - if there's an entry with the same name already in the pipeline
NullPointerException - if the specified baseName, name, or handler is null

addAfter

void addAfter(String baseName,
              String name,
              ChannelHandler handler)
Inserts a ChannelHandler after an existing handler of this pipeline.

Parameters:
baseName - the name of the existing handler
name - the name of the handler to insert after
handler - the handler to insert after
Throws:
NoSuchElementException - if there's no such entry with the specified baseName
IllegalArgumentException - if there's an entry with the same name already in the pipeline
NullPointerException - if the specified baseName, name, or handler is null

remove

void remove(ChannelHandler handler)
Removes the specified ChannelHandler from this pipeline.

Throws:
NoSuchElementException - if there's no such handler in this pipeline
NullPointerException - if the specified handler is null

remove

ChannelHandler remove(String name)
Removes the ChannelHandler with the specified name from this pipeline.

Returns:
the removed handler
Throws:
NoSuchElementException - if there's no such handler with the specified name in this pipeline
NullPointerException - if the specified name is null

remove

<T extends ChannelHandler> T remove(Class<T> handlerType)
Removes the ChannelHandler of 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 pipeline
NullPointerException - if the specified handler type is null

removeFirst

ChannelHandler removeFirst()
Removes the first ChannelHandler in this pipeline.

Returns:
the removed handler
Throws:
NoSuchElementException - if this pipeline is empty

removeLast

ChannelHandler removeLast()
Removes the last ChannelHandler in this pipeline.

Returns:
the removed handler
Throws:
NoSuchElementException - if this pipeline is empty

replace

void replace(ChannelHandler oldHandler,
             String newName,
             ChannelHandler newHandler)
Replaces the specified ChannelHandler with a new handler in this pipeline.

Throws:
NoSuchElementException - if the specified old handler does not exist in this pipeline
IllegalArgumentException - if a handler with the specified new name already exists in this pipeline, except for the handler to be replaced
NullPointerException - if the specified old handler, new name, or new handler is null

replace

ChannelHandler replace(String oldName,
                       String newName,
                       ChannelHandler newHandler)
Replaces the ChannelHandler of 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 pipeline
IllegalArgumentException - if a handler with the specified new name already exists in this pipeline, except for the handler to be replaced
NullPointerException - if the specified old handler, new name, or new handler is null

replace

<T extends ChannelHandler> T replace(Class<T> oldHandlerType,
                                     String newName,
                                     ChannelHandler newHandler)
Replaces the ChannelHandler of 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 pipeline
IllegalArgumentException - if a handler with the specified new name already exists in this pipeline, except for the handler to be replaced
NullPointerException - if the specified old handler, new name, or new handler is null

getFirst

ChannelHandler getFirst()
Returns the first ChannelHandler in this pipeline.

Returns:
the first handler. null if this pipeline is empty.

getLast

ChannelHandler getLast()
Returns the last ChannelHandler in this pipeline.

Returns:
the last handler. null if this pipeline is empty.

get

ChannelHandler get(String name)
Returns the ChannelHandler with the specified name in this pipeline.

Returns:
the handler with the specified name. null if there's no such handler in this pipeline.

get

<T extends ChannelHandler> T get(Class<T> handlerType)
Returns the ChannelHandler of the specified type in this pipeline.

Returns:
the handler of the specified handler type. null if there's no such handler in this pipeline.

getContext

ChannelHandlerContext getContext(ChannelHandler handler)
Returns the context object of the specified ChannelHandler in this pipeline.

Returns:
the context object of the specified handler. null if there's no such handler in this pipeline.

getContext

ChannelHandlerContext getContext(String name)
Returns the context object of the ChannelHandler with the specified name in this pipeline.

Returns:
the context object of the handler with the specified name. null if there's no such handler in this pipeline.

getContext

ChannelHandlerContext getContext(Class<? extends ChannelHandler> handlerType)
Returns the context object of the ChannelHandler of the specified type in this pipeline.

Returns:
the context object of the handler of the specified type. null if there's no such handler in this pipeline.

sendUpstream

void sendUpstream(ChannelEvent e)
Sends the specified ChannelEvent to the first ChannelUpstreamHandler in this pipeline.

Throws:
NullPointerException - if the specified event is null

sendDownstream

void sendDownstream(ChannelEvent e)
Sends the specified ChannelEvent to the last ChannelDownstreamHandler in this pipeline.

Throws:
NullPointerException - if the specified event is null

getChannel

Channel getChannel()
Returns the Channel that this pipeline is attached to.

Returns:
the channel. null if this pipeline is not attached yet.

getSink

ChannelSink getSink()
Returns the ChannelSink that this pipeline is attached to.

Returns:
the sink. null if this pipeline is not attached yet.

attach

void attach(Channel channel,
            ChannelSink sink)
Attaches this pipeline to the specified Channel and ChannelSink. Once a pipeline is attached, it can't be detached nor attached again.

Throws:
IllegalStateException - if this pipeline is attached already

isAttached

boolean isAttached()
Returns true if and only if this pipeline is attached to a Channel.


getNames

List<String> getNames()
Returns the List of the handler names.


toMap

Map<String,ChannelHandler> toMap()
Converts this pipeline into an ordered Map whose keys are handler names and whose values are handlers.



Copyright © 2008-2011 JBoss, a division of Red Hat, Inc.. All Rights Reserved.