You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2019/04/01 06:27:23 UTC
[struts] branch master updated: Forward-port fix for WW-5026 to
2.6. - Equivalent to PR#342 for 2.5.x,
fixes double-submit error 500 failure with - 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 is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/struts.git
The following commit(s) were added to refs/heads/master by this push:
new bb7cf09 Forward-port fix for WW-5026 to 2.6. - Equivalent to PR#342 for 2.5.x, fixes double-submit error 500 failure with - 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
new f251d1c Merge pull request #345 from JCgH4164838Gh792C124B5/localS2_26x_B3
bb7cf09 is described below
commit bb7cf092bc9374af743de67ec9e2aa4d0f55cdf0
Author: JCgH4164838Gh792C124B5 <43...@users.noreply.github.com>
AuthorDate: Sun Mar 31 22:47:16 2019 -0400
Forward-port fix for WW-5026 to 2.6.
- Equivalent to PR#342 for 2.5.x, fixes double-submit error 500 failure with
- 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
---
.../interceptor/TokenSessionStoreInterceptor.java | 26 +++++++++++++++++-
.../struts2/util/InvocationSessionStore.java | 20 ++++++++++----
.../struts2/util/InvocationSessionStoreTest.java | 31 ++++++++++++++++++++++
3 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/core/src/main/java/org/apache/struts2/interceptor/TokenSessionStoreInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/TokenSessionStoreInterceptor.java
index e08fb07..863e804 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/TokenSessionStoreInterceptor.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/TokenSessionStoreInterceptor.java
@@ -112,6 +112,20 @@ public class TokenSessionStoreInterceptor extends TokenInterceptor {
}
}
+ /**
+ * Handles processing of invalid tokens. If a previously stored invocation is
+ * available, the method will attempt to return and render its result. Otherwise
+ * it will return INVALID_TOKEN_CODE.
+ *
+ * Note: Because a stored (previously completed) invocation's PageContext will be closed,
+ * this method must replace the stored PageContext with the current invocation's one (or a null).
+ * See {@link org.apache.struts2.util.InvocationSessionStore#loadInvocation(String key, String token)} for details.
+ *
+ * @param invocation
+ *
+ * @return
+ * @throws Exception
+ */
@Override
protected String handleInvalidToken(ActionInvocation invocation) throws Exception {
ActionContext ac = invocation.getInvocationContext();
@@ -130,7 +144,7 @@ public class TokenSessionStoreInterceptor extends TokenInterceptor {
ActionInvocation savedInvocation = InvocationSessionStore.loadInvocation(sessionTokenName, token);
if (savedInvocation != null) {
- // set the valuestack to the request scope
+ // set the savedInvocation's valuestack to the request scope
ValueStack stack = savedInvocation.getStack();
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
@@ -153,6 +167,16 @@ public class TokenSessionStoreInterceptor extends TokenInterceptor {
return INVALID_TOKEN_CODE;
}
+ /**
+ * Handles processing of valid tokens. Stores the current invocation for
+ * later use by {@link handleInvalidToken}.
+ * See {@link org.apache.struts2.util.InvocationSessionStore#storeInvocation(String key, String token, ActionInvocation invocation)} for details.
+ *
+ * @param invocation
+ *
+ * @return
+ * @throws Exception
+ */
@Override
protected String handleValidToken(ActionInvocation invocation) throws Exception {
// we know the token name and token must be there
diff --git a/core/src/main/java/org/apache/struts2/util/InvocationSessionStore.java b/core/src/main/java/org/apache/struts2/util/InvocationSessionStore.java
index 15662de..238df3c 100644
--- a/core/src/main/java/org/apache/struts2/util/InvocationSessionStore.java
+++ b/core/src/main/java/org/apache/struts2/util/InvocationSessionStore.java
@@ -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;
@@ -55,11 +56,20 @@ public class InvocationSessionStore {
return null;
}
- ActionInvocation savedInvocation = null;
- if (invocationContext.invocation != null) {
- savedInvocation = invocationContext.invocation;
- ActionContext.setContext(savedInvocation.getInvocationContext());
- ActionContext.getContext().setValueStack(savedInvocation.getStack());
+ final ActionInvocation savedInvocation = invocationContext.invocation;
+ if (savedInvocation != 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 = savedInvocation.getInvocationContext();
+ final ActionContext previousActionContext = ActionContext.getContext();
+ ActionContext.setContext(savedActionContext);
+ 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;
diff --git a/core/src/test/java/org/apache/struts2/util/InvocationSessionStoreTest.java b/core/src/test/java/org/apache/struts2/util/InvocationSessionStoreTest.java
index 8b5b8cd..8cfc3f4 100644
--- a/core/src/test/java/org/apache/struts2/util/InvocationSessionStoreTest.java
+++ b/core/src/test/java/org/apache/struts2/util/InvocationSessionStoreTest.java
@@ -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();