Fix issue introduced with earlier WW-4873 fix:

- Fixes error 500 processing failures for double-submit results with TokenSessionStoreInterceptor processing
- Fix to InvocationSessionStore, new unit test confirming fix in InvocationSessionStoreTest
- Minor whitespace fix to TokenSessionStoreInterceptor
This commit is contained in:
JCgH4164838Gh792C124B5
2019-03-25 01:00:10 -04:00
parent d460d71498
commit 5b0ec3400d
3 changed files with 51 additions and 5 deletions
@@ -126,11 +126,12 @@ public class TokenSessionStoreInterceptor extends TokenInterceptor {
params.remove(tokenName);
params.remove(TokenHelper.TOKEN_NAME_FIELD);
String sessionTokenName = TokenHelper.buildTokenSessionAttributeName(tokenName);
String sessionTokenName = TokenHelper.buildTokenSessionAttributeName(tokenName);
ActionInvocation savedInvocation = InvocationSessionStore.loadInvocation(sessionTokenName, token);
if (savedInvocation != null) {
// set the valuestack to the request scope
// Note: loadInvocation() restored invocation's PageContext (as savedInvocation's will already be closed)
ValueStack stack = savedInvocation.getStack();
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
@@ -158,8 +159,8 @@ public class TokenSessionStoreInterceptor extends TokenInterceptor {
// we know the token name and token must be there
String key = TokenHelper.getTokenName();
String token = TokenHelper.getToken(key);
String sessionTokenName = TokenHelper.buildTokenSessionAttributeName(key);
InvocationSessionStore.storeInvocation(sessionTokenName, token, invocation);
String sessionTokenName = TokenHelper.buildTokenSessionAttributeName(key);
InvocationSessionStore.storeInvocation(sessionTokenName, token, invocation);
return invocation.invoke();
}
@@ -20,6 +20,7 @@ package org.apache.struts2.util;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import org.apache.struts2.ServletActionContext;
import java.io.Serializable;
import java.util.HashMap;
@@ -57,9 +58,22 @@ public class InvocationSessionStore {
ActionInvocation savedInvocation = null;
if (invocationContext.invocation != null) {
// WW-5026 - Preserve the previous PageContext (even if null) and restore it to the
// ActionContext after loading the savedInvocation context. The saved context's PageContext
// would already be closed at this point (causing failures if used for output).
final ActionContext savedActionContext;
final ActionContext previousActionContext;
savedInvocation = invocationContext.invocation;
ActionContext.setContext(savedInvocation.getInvocationContext());
ActionContext.getContext().setValueStack(savedInvocation.getStack());
savedActionContext = savedInvocation.getInvocationContext();
previousActionContext = ActionContext.getContext();
ActionContext.setContext(savedActionContext);
savedActionContext.setValueStack(savedInvocation.getStack());
savedActionContext.setValueStack(savedInvocation.getStack());
if (previousActionContext != null) {
savedActionContext.put(ServletActionContext.PAGE_CONTEXT, previousActionContext.get(ServletActionContext.PAGE_CONTEXT));
} else {
savedActionContext.put(ServletActionContext.PAGE_CONTEXT, null);
}
}
return savedInvocation;
@@ -31,6 +31,8 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;
import org.apache.struts.mock.MockPageContext;
import org.apache.struts2.ServletActionContext;
/**
@@ -100,6 +102,35 @@ public class InvocationSessionStoreTest extends StrutsInternalTestCase {
assertNull(savedInvocation);//Currently we don't support invocation restore from serialized session
}
public void testStoreAndLoadPreservesPageContext() {
ActionContext actionContext = ActionContext.getContext();
// Create mock PageContext to put with the saved context (simulating a PageContext previously
// used and closed after generating JSP output).
MockPageContext mockSavedPageContext = new MockPageContext();
actionContext.put(ServletActionContext.PAGE_CONTEXT, mockSavedPageContext);
assertEquals(mockSavedPageContext, ActionContext.getContext().get(ServletActionContext.PAGE_CONTEXT));
InvocationSessionStore.storeInvocation(INVOCATION_KEY, TOKEN_VALUE, invocation);
ActionContext actionContext2 = new ActionContext(new HashMap<String, Object>());
actionContext2.setSession(session);
ActionContext.setContext(actionContext2);
assertEquals(actionContext2, ActionContext.getContext());
// Create mock PageContext to put with the current context (simulating a PageContext
// associated with the current (active) process flow). In real-world processing it
// will usually be null, but if non-null it should be preserved/restored upon load of the
// saved context.
MockPageContext mockPreviousPageContext = new MockPageContext();
actionContext2.put(ServletActionContext.PAGE_CONTEXT, mockPreviousPageContext);
assertEquals(mockPreviousPageContext, ActionContext.getContext().get(ServletActionContext.PAGE_CONTEXT));
InvocationSessionStore.loadInvocation(INVOCATION_KEY, TOKEN_VALUE);
assertEquals(actionContext, ActionContext.getContext());
assertEquals(mockPreviousPageContext, ActionContext.getContext().get(ServletActionContext.PAGE_CONTEXT));
}
protected void setUp() throws Exception {
super.setUp();
stack = ActionContext.getContext().getValueStack();