tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Costin Manolache <>
Subject Re: authorization providers (was More on JAAS)
Date Wed, 19 Apr 2000 18:53:50 GMT
> * They can both be used to implement "filter" (the request passes
>   on through) or "handler" (the request is handled, and no further
>   processing happens).  This latter capability of RequestInterceptors
>   was not obvious in the code (lack of comments) to me earlier --
>   I apologize for mis-stating this in an earlier email.

With a big difference...

> * State Management -- Both RequestInterceptors and Valves are
>   used in a multithreaded environment (thread per concurrent
>   request).  As a result, any state about this request that a
>   RequestInterceptor wants to save must be stored in the request
>   itself.  In a Valve, you can do that (important if some other
>   component needs access to this information) but you can also
>   use local variables inside the invoke() method for state information
>   that is purely local to this request.

Are we going back to "recursive versus iterative alghoritms"  ?
Yes, you get the ability to store local variables on the invocation stack -
but  that's not allways an advantage.

> * Complexity -- RequestInterceptor provides you circa 10 entry points,
>   and you must understand the request processing lifecycle in pretty
>   good detail to know where your logic should go.  Valves are called
>   once per request, so this is quite obvious.  See more on this topic
>   below; there are other subtleties.

Well, you must understand the request processing in both cases...

> * Performance Overhead -- A RequestInterceptor that passes requests
>   on (the usual case) receives circa 10 method calls per request, versus
>   one for a Valve.  In addition, the requirement to store state information
>   in the request, as opposed to on the stack, can cause additional
>   overhead to implement the same functionality.

First "overhead" - it's an implementation problem, nothing wrong with the
The second - I just a result of the alghortim choice, and interceptors are
supposed to be very simple, we tried very hard to keep even the
configuration as part of the "core objects" - i.e. you configure the
context, not the interceptor. If the state is associated with the request -
it's better to keep it in the request, instead of doing tricks with
the execution stack.

But if you want to discuss "performance overhead" - the request interceptor
have full control over the parsing alghoritm. It can use a BTree or any
other data structure - and that _does_ matter in execution time.
With Valve  -  you impose a certain method ( division of problem space)
and prevent any optimizations that can result from using efficient data

The reason Valve looks nice on paper is that it doesn't have to deal with
all the details of the request processing - subRequests, etc. Looking forward
to see how Catalina will perform and see where is the overhead.

> The key question, though, is "can I implement something using one approach
> that I cannot implement in the other".  The only place I can see a big
> difference here is the case where you want all of the interceptors to have a
> crack at, say, the requestMap() call, then go back and call all of them again
> for the authenticate() call.  (For those of you familiar with Apache modules,
> that's the way they work).  While one could discuss how often you need that
> kind of thing inside a servlet container (versus when writing webserver
> extensions), it can be implemented when needed with Valves by simply having
> more than one Valve in the pipeline, using shared state behind the scenes as
> required to accomplish the functional purpose required.

Sounds simple :-)

The situation is very common - for example include() and all getRealPath().
But we are going back to alghoritms - it's a problem common to recursive
programming, it's hard to control entry and exit.

Another thing you can't do with valves - you can't distinguish between
various proessing stages. The reason interceptor has 10 methods is that
there _are_  several distinct stages, and you have better control by
exposing them instead of hiding them in the processing chain ( inside
invoke() method).

You may want to check if a particular resource is "authorized" - the user
is authenticated and calls getResource() ( I know it's not required by the
spec, but spec do change) , you have the context  and you just need to call
the authorization stage.
Or getContext(uri) - you don't need to call the full valve chain, only the
valves that are involved in context mapping.


View raw message