tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Craig R. McClanahan" <cmcclana...@mytownnet.com>
Subject [Catalina] Discussion - Interceptor Architecture
Date Thu, 20 Jan 2000 07:14:12 GMT
The Interceptor architecture in the Catalina proposal is loosely based
on work I did earlier in Apache JServ, and also on the existing
"ServiceInterceptor" and "LifecycleInterceptor" interfaces in Tomcat
3.0.  Although the proposed architecture appears to meet the goals
outlined in the proposal, there are also (at least) a couple of problems
with it:

* Because interceptors are executed in a multithread
  environment just like servlets are, there is no
  convenient way to maintain per-request state
  between the preService() and postService() calls
  that occur for the same request.

* Exception handling is really fragile -- the current
  Javadocs say that if (say) a Container throws an
  exception, then the postService() method of all
  interceptors -- when you already called preService
  on them -- will be skipped.  This makes it much more
  difficult to release resources that were allocated
  in the preService methods.

In the Apache JServ component-based architecture, a different approach
called "Valves" was taken.  Instead of adding the interceptors into a
stack, they are added to a linked list instead.  A given Valve would
either process the request and return, or pass the request on to the
next Valve in the pipeline (after possibly modifying the request
parameters).  I have checked in the following files to illustrate the
Valve interface, and a convenience base class that implements the
appropriate linking.

    proposals/catalina/src/share/org/apache/tomcat/Valve.java

    proposals/catalina/src/share/org/apache/tomcat/core/ValveBase.java

This approach seems to meet all of the design objectives of
Interceptors, and adds some additional features:

* Per-request state is easy to keep, using local variables
  in the invoke() method.

* Exceptions thrown by subsequent Valves or Containers
  can be caught, so you can gracefully release anything
  you've allocated.

* You can even replace the request and/or response
  objects before calling the next valve in the pipeline,
  which would give you the ability to implement post-servlet
  filtering if you really wanted to (I don't like that approach,
  but it is enabled by this architecture).

If we like it better than Interceptors, I would propose that
Interceptors (in Catalina) be replaced by Valves (although I'm pretty
neutral about which name we keep).  What do we all think?

Craig McClanahan



Mime
View raw message