I've debugged something similar two days ago on a legacy project (not mine).
It turned out it was custom Interceptors's fault.
Check the custom Interceptors i can see in your stack,
<interceptor-ref name="sessionLoggin"/>
<interceptor-ref name="appAccess"/>
and ensure that their code is Thread Safe (avoid fields on interceptors instead of synchronize all your stuff, use only local variables).
For example, consider the code:
public abstract class ThreadUnsafeInterceptor extends AbstractInterceptor {
private Map<String, Object> session; // <!-- Thread Unsafe
public final String intercept(ActionInvocation invocation) throws Exception {
session = invocation.getInvocationContext().getSession();
/* Do stuff */
System.out.println(session.get("myObject"));
return invocation.invoke();
}
}
This way, when User1 enters the method, it sets the shared session
object with its session;
if User2 enters the method while User1 has not yet finished, User2 will immediately override the session
object with its session, and User1 will refer to User2 session instead of its own.
To make it thread safe it should be like follows:
public abstract class ThreadSafeInterceptor extends AbstractInterceptor {
public final String intercept(ActionInvocation invocation) throws Exception {
Map<String, Object> session; // <!-- Thread Safe
session = invocation.getInvocationContext().getSession();
/* Do stuff */
System.out.println(session.get("myObject"));
return invocation.invoke();
}
}
EDIT:
Your interceptors present some problems:
1) Request must not be accessed this way (as described here):
HttpServletRequest request = ServletActionContext.getRequest();
the right way to access the request from within an Struts2 Interceptor is:
// Constants are from StrutsStatics interface
HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST);
2) If you don't want to return the invocation.invoke();
immediately, please note that assigning that to the result
String will fire the "flow", and the lines after the invoke()
will be executed AFTER the Action execution, as described here:
public String intercept(ActionInvocation invocation) throws Exception {
String className = invocation.getAction().getClass().getName();
long startTime = System.currentTimeMillis();
System.out.println("Before calling action: " + className);
String result = invocation.invoke();
long endTime = System.currentTimeMillis();
System.out.println("After calling action: " + className
+ " Time taken: " + (endTime - startTime) + " ms");
return result;
}