It seems that if I have two concurrent requests being made to the same action, e.g mysite.com/fooAction, then struts resets the first action\'s instance while that instance
If I understand the question correctly - If a single request is made, then the result of printing the action references indicate that they are same.
However if concurrent requests are made, then the action references differ.
If this is indeed so, then its likely due to customizations.
By default, the only place where the 'action' reference is initialized in case of DefaultActionInvocation is in createAction which in turn is invoked only in init(ActionProxy) in the same class and which in turn is supposed to be invoked only once and is done from prepare() of DefaultActionProxy which in turn is only invoked from createActionProxy() of DefaultActionProxyFactory.
As such for a given instance of ActionInvocation the action would (should) always be the same.
Update 2 (Regarding the example s2 project) :
While I did not actually run the code, I did go through it.
The Json interceptor is stateful. However it is required to be stateless. This explains why concurrent requests result in the action instances being different.
As per the interceptor doc here :
An interceptor is a stateless class that follows the interceptor pattern, as found in javax.servlet.Filter and in AOP languages.
...Interceptors must be stateless and not assume that a new instance will be created for each request or Action.
As I understand it :
The first request assigns the local Action instance in the interceptor and goes to sleep.
The second request re-assigns the Action instance (interceptor being singleton) and also goes to sleep.
The first request wakes up and continues with the execution. Upon returning and comparing the action instances again, sees the Action instance in the interceptor from the second request and fetches the action instance for the current request from the ActionInvocation again. They will indeed be different. This explains the observed behaviour. Also, it should be visible even if ai.invoke() or ai.invokeActionOnly() is not called.
Also the 'servletConfig' interceptor is already included in the 'defaultStack' along with a bunch of others. You can find the details here