I really like your approach, Dave. Some question though:
What would session.getFilterChain() return? It will be sessionChain, right?
Will IoFilterChain extend IoFilter and be just another IoFilter?
This is basically the same as nesting filter chains as I proposed
yesterday (remember the (((A, B), C), D) thingy?) but it's a flat list
of chains instead, right?
You still have the NextFilter problem. As I understand it these have to
be static since IoFilter.init() is called when the filter is added to a
chain. A NextFilter is passed to this method and the filter could
remember this for future use.
I can't see how the last filter in a wrapped chain will know where to go
next if the NextFilter given to it can't be created dynamically.
Remember, sessionManagerChain and portChain will be shared by many
connectionChains.
/Niklas
Irving, Dave wrote:
Explicitly asking users to add head/tail filter is a bad idea.
I agree. In fact - thats my point :o)
But I think it is a great idea. But we don't need to make a chain
be nested more than one level.
And head and tail filter must be hidden from user to prevent from
unexpected removal or reordering.
Exactly. The ** user ** doesn't write the code above: This is in the
acceptor (or whatever).
The idea is that the user can contribute a chain (Jose's approach) how
ever they like.
The special "head tail" behaviour is encapsulated to the client who
requires it: I.e, the acceptor / connector.
This is what I like about the idea. Currently, if you write a filter
chain, you need to care about that special head tail behaviour. Using
this approach you wouldn't - because a chain is nothing more than a
sequence of filters.
Its the /acceptor / connector /who cares about the head / tail
behaviour - so he can specify it directly.
Hopefully this example will clear up the creational logic:
Imagine this code is in SocketAcceptorDelegate.Worker#processSessions
- when we've just found out we've got a new session:
// Create the filter chain for the new connection / session
BasicFilterChain connectionChain = new BasicFilterChain();
// Add the session manager chain to the connection chain
connectionChain.addLast(sessionManagerChain);
// Add the per-port chain to the connection chain
connectionChain.addLast(portChain);
// Let the user contribute to a new per-session chain (Jose's approach)
BasicFilterChain sessionChain = new BasicFilterChain();
someChainBuilder.buildChain(sessionChain);
// Add the per-session filter to the connection chain
connectionChain.addLast(sessionChain);
// Now create the filter which does ** our ** work (i.e, real handler
writing)
IoFilter workerFilter = new EndOfTheLineFilter();
connectionChain.add( workerFilter );
Notice that the /user /isn't specifying the worker filter - the
SocketAcceptorDelegate is.
So I belive this gives us real benefits:
1) Makes the filter chain mechanism simpler (reduces complexity as
we're now using composition rather than inheritance)
2) Paves the way for user contribution to chains (Jose's approach)
3) Doesn't require filter cloning or per-traversal clones
4) Is OO: The acceptor / connector is the actor who wants to specify
"end of chain" behaviour: So he does so by means of adding a custom
filter to the end of the built chain
Does this clear it up at all?
What do you think about this approach?
Many thanks,
Dave (give me sleep) Irving
This e-mail and any attachment is for authorised use by the intended
recipient(s) only. It may contain proprietary material, confidential
information and/or be subject to legal privilege. It should not be
copied, disclosed to, retained or used by, any other party. If you are
not an intended recipient then please promptly delete this e-mail and
any attachment and all copies and inform the sender. Thank you.