FilterChain and Filters

In the previous sections we mentioned the Processor, and its role - processing I/O events occurred on Grizzly Connections. The FilterChain is the most useful type of Processor used in Grizzly.

FilterChain, according to its name, is a chain of Filters. Each Filter represents a unit of processing work to be performed, whose purpose is to examine and/or modify the state of the transaction that is represented by a FilterChainContext.

To give an idea how FilterChain may look like, here is example of FilterChain, which implements HTTP server logic:

So, what if we want to implement HTTPS server? It's simple:

we add just one SSLFilter, responsible for encoding/decoding SSL secured data.

As we see, during the processing of any I/O Event, Filters in a FilterChain will be executed in the certain order. It's important to remember that the most of I/O Events are processed starting from first filter to last (from left to right on the schema above), except WRITE event, whose processing starts from last Filter in chain to first (from right to left a the schema above).

Let's define some terminology to make the following descriptions clearer:

Let's take a look which I/O events could be processed by a FilterChain, for that purpose we can just take a look at the Filter interface methods:

public NextAction handleRead(FilterChainContext ctx) throws IOException;

public NextAction handleWrite(FilterChainContext ctx) throws IOException;

public NextAction handleConnect(FilterChainContext ctx) throws IOException;

public NextAction handleAccept(FilterChainContext ctx) throws IOException;

public NextAction handleClose(FilterChainContext ctx) throws IOException;

so I/O events are

It's important to remember that the same I/O events on the specific Connection are processed serially. For example, if we process READ I/O event on Connection "A", Grizzly will never start processing another READ I/O event on the same Connection "A" until the processing of the previous READ I/O event has completed processing. If the user decides to take ownership of I/O event processing, then the "rule" of serial event processing should still be observed.

Additionally FilterChain Filters are able to initiate and handle custom event notifications. The event initiator may choose to emit the event upstream or downstream by FilterChain like:

public NextAction handleRead(FilterChainContext ctx) throws IOException {
        // Here we decide to notify downstream Filters
        ctx.notifyDownstream(new MyEvent(...));

        // Notify upstream Filters
        ctx.notifyUpstream(new AnotherEvent(...));
}

The Filters in FilterChain are able to intercept and process custom Events by implementing method:

public NextAction handleEvent(FilterChainContext ctx, FilterChainEvent event) throws IOException;

As we see each Filter "handle" method has FilterChainContext parameter and returns NextAction result.