I have been chasing down a bug for months where data is incorrectly posted, and 
I chased it down to what I believe is a major failing in the interceptor chain.

From what I see through my blurry and tired eyes is that an interceptor list 
containing an instance of each interceptor is created for each action mapping.  
When an action is called, each interceptor is called in turn.  All well in 
good... BUT...

These methods are not synchronized.  The actionMapping for a given action holds 
on to an instance of each interceptor that it calls in turn for every request 
(the same instance)!  So for example, you have two requests coming in for the 
same action at the same time, and it requires both the ServletRequestAware and 
SessionAware functionality from ServletConfigInterceptor.  
        Request 1 enters the interceptor (assigning the context) and is 
assigned the request 1 ServletRequestAware information. 
        Request 2 enters the interceptor (assigning the context) and is 
assigned the request 2 ServletRequestAware information. 
        Request 1 speeds along and is now assigned the request 2 
ServletRequestAware information. 
        Request 2 speeds along and is assigned the request 2 
ServletRequestAware information.

Now, I see the keyword final for the context, etc.. in this interceptor, and I 
honestly don't know if that makes the methods immune for multiple requests for 
synchronized items.  Presuming it does, great!  However, there are many (and I 
mean more than one or two) interceptors which don't make use of the final 
keyword, that are not synchronized, and set local variables based on the 
action/context that are mutable and can change during another call to the 
interceptor.
        ParameterRemoverInterceptor...
        PrepareInterceptor...
        MethodFilterInterceptor...
        ScopedModelDrivenInterceptor...
etc. etc...

I searched the documentation, and nowhere does it infer that interceptors were 
all prototypes, and from what I see they are functionally prototypes within an 
action.

If I am correct here, there are several solutions.  However, I am noticing that 
Struts is currently failing under heavy loads where there are likely many 
requests to a main landing page at the same moment.  I have defined my own 
interceptors, and without knowing the true architecture, I captured the request 
in a class variable then dispatched the request onward to other components for 
additional processing... when I get control, I access the request again, and 
with the preResultListener method.  I noticed that the request magically 
changes in the ActionInvocation, and it wasn't until I noticed the object 
itself never changing that I first checked spring, and then the struts code for 
answers.

So I have been contributing code, and I normally am pretty accurate with these 
things.  However, I would be very happy to hear that I am incorrect in these 
assertions :)

Thanks in advance,

Christian Stone

(References)
StrutsObjectFactory - creates the interceptor.
InterceptorBuilder.constructInterceptorReference() - returns the list.
DefaultConfiguration.buildFullActionConfig() - generates a list of instances 
for an action mapping.  This list is persistent for the lifecycle of the 
application!
and XmlConfigurationProvider (same as DefaultConfiguration).





Reply via email to