Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id AA270200D6B for ; Sat, 16 Dec 2017 10:45:16 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id A8459160C11; Sat, 16 Dec 2017 09:45:16 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id A09B3160BFB for ; Sat, 16 Dec 2017 10:45:15 +0100 (CET) Received: (qmail 17913 invoked by uid 500); 16 Dec 2017 09:45:14 -0000 Mailing-List: contact issues-help@struts.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@struts.apache.org Delivered-To: mailing list issues@struts.apache.org Received: (qmail 17903 invoked by uid 99); 16 Dec 2017 09:45:14 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 16 Dec 2017 09:45:14 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id A58E9C1CA7 for ; Sat, 16 Dec 2017 09:45:13 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -99.211 X-Spam-Level: X-Spam-Status: No, score=-99.211 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_NONE=-0.0001, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01, USER_IN_WHITELIST=-100] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id 5EHM4MXxQGZ7 for ; Sat, 16 Dec 2017 09:45:10 +0000 (UTC) Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with ESMTP id 4B9695F39C for ; Sat, 16 Dec 2017 09:45:09 +0000 (UTC) Received: from jira-lw-us.apache.org (unknown [207.244.88.139]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id 5BEFEE0635 for ; Sat, 16 Dec 2017 09:45:08 +0000 (UTC) Received: from jira-lw-us.apache.org (localhost [127.0.0.1]) by jira-lw-us.apache.org (ASF Mail Server at jira-lw-us.apache.org) with ESMTP id 2B8B4240EA for ; Sat, 16 Dec 2017 09:45:05 +0000 (UTC) Date: Sat, 16 Dec 2017 09:45:05 +0000 (UTC) From: "ASF GitHub Bot (JIRA)" To: issues@struts.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Commented] (WW-4873) NotSerializableException - org.apache.struts2.dispatcher.StrutsRequestWrapper MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 archived-at: Sat, 16 Dec 2017 09:45:16 -0000 [ https://issues.apache.org/jira/browse/WW-4873?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16293730#comment-16293730 ] ASF GitHub Bot commented on WW-4873: ------------------------------------ lukaszlenart closed pull request #192: WW-4873 Makes ActionInvocation not serializable and InvocationSessionStore$InvocationContext transient URL: https://github.com/apache/struts/pull/192 This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionInvocation.java b/core/src/main/java/com/opensymphony/xwork2/ActionInvocation.java index 908349806..472f23ea7 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ActionInvocation.java +++ b/core/src/main/java/com/opensymphony/xwork2/ActionInvocation.java @@ -21,8 +21,6 @@ import com.opensymphony.xwork2.interceptor.PreResultListener; import com.opensymphony.xwork2.util.ValueStack; -import java.io.Serializable; - /** * An {@link ActionInvocation} represents the execution state of an {@link Action}. It holds the Interceptors and the Action instance. * By repeated re-entrant execution of the invoke() method, initially by the {@link ActionProxy}, then by the Interceptors, the @@ -31,7 +29,7 @@ * @author Jason Carreira * @see com.opensymphony.xwork2.ActionProxy */ -public interface ActionInvocation extends Serializable { +public interface ActionInvocation { /** * Get the Action associated with this ActionInvocation. @@ -178,20 +176,4 @@ void init(ActionProxy proxy) ; - /** - * Prepares instance of ActionInvocation to be serializable, - * which simple means removing all unserializable fields, eg. Container - * - * @return ActionInvocation which can be serialize (eg. into HttpSession) - */ - ActionInvocation serialize(); - - /** - * Performs opposite process to restore back ActionInvocation after deserialisation - * - * @param actionContext current {@link ActionContext} - * @return fully operational ActionInvocation - */ - ActionInvocation deserialize(ActionContext actionContext); - } diff --git a/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java b/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java index 5777007c1..6b039d680 100644 --- a/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java +++ b/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java @@ -500,27 +500,4 @@ protected String saveResult(ActionConfig actionConfig, Object methodResult) { } } - /** - * Version ready to be serialize - * - * @return instance without reference to {@link Container} - */ - public ActionInvocation serialize() { - DefaultActionInvocation that = this; - that.container = null; - return that; - } - - /** - * Restoring Container - * - * @param actionContext current {@link ActionContext} - * @return instance which can be used to invoke action - */ - public ActionInvocation deserialize(ActionContext actionContext) { - DefaultActionInvocation that = this; - that.container = actionContext.getContainer(); - return that; - } - } diff --git a/core/src/main/java/com/opensymphony/xwork2/mock/MockActionInvocation.java b/core/src/main/java/com/opensymphony/xwork2/mock/MockActionInvocation.java index 9053273dc..f37e8a6ae 100644 --- a/core/src/main/java/com/opensymphony/xwork2/mock/MockActionInvocation.java +++ b/core/src/main/java/com/opensymphony/xwork2/mock/MockActionInvocation.java @@ -124,12 +124,4 @@ public ActionEventListener getActionEventListener() { public void init(ActionProxy proxy) { } - public ActionInvocation serialize() { - return this; - } - - public ActionInvocation deserialize(ActionContext actionContext) { - return this; - } - } 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 5f1ad483d..15662de38 100644 --- a/core/src/main/java/org/apache/struts2/util/InvocationSessionStore.java +++ b/core/src/main/java/org/apache/struts2/util/InvocationSessionStore.java @@ -20,7 +20,6 @@ import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.util.ValueStack; import java.io.Serializable; import java.util.HashMap; @@ -56,10 +55,14 @@ public static ActionInvocation loadInvocation(String key, String token) { return null; } - ValueStack stack = invocationContext.invocation.getStack(); - ActionContext.getContext().setValueStack(stack); + ActionInvocation savedInvocation = null; + if (invocationContext.invocation != null) { + savedInvocation = invocationContext.invocation; + ActionContext.setContext(savedInvocation.getInvocationContext()); + ActionContext.getContext().setValueStack(savedInvocation.getStack()); + } - return invocationContext.invocation.deserialize(ActionContext.getContext()); + return savedInvocation; } /** @@ -71,7 +74,7 @@ public static ActionInvocation loadInvocation(String key, String token) { * @param invocation the action invocation */ public static void storeInvocation(String key, String token, ActionInvocation invocation) { - InvocationContext invocationContext = new InvocationContext(invocation.serialize(), token); + InvocationContext invocationContext = new InvocationContext(invocation, token); Map invocationMap = getInvocationMap(); invocationMap.put(key, invocationContext); setInvocationMap(invocationMap); @@ -109,7 +112,9 @@ static Map getInvocationMap() { private static final long serialVersionUID = -286697666275777888L; - ActionInvocation invocation; + //WW-4873 transient since 2.5.15 + transient ActionInvocation invocation; + String token; public InvocationContext(ActionInvocation invocation, String token) { diff --git a/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java b/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java index 334839082..89e5b9645 100644 --- a/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java @@ -75,34 +75,6 @@ public void testInvoke() throws Exception { assertTrue(mockInterceptor3.isExecuted()); } - public void testSerialization() throws Exception { - // given - DefaultActionInvocation actionInvocation = new DefaultActionInvocation(new HashMap(), false); - actionInvocation.setContainer(new MockContainer()); - - // when - DefaultActionInvocation serializable = (DefaultActionInvocation) actionInvocation.serialize(); - - // then - assertNull(actionInvocation.container); - assertNull(serializable.container); - } - - public void testDeserialization() throws Exception { - // given - DefaultActionInvocation actionInvocation = new DefaultActionInvocation(new HashMap(), false); - MockContainer mockContainer = new MockContainer(); - ActionContext.getContext().setContainer(mockContainer); - - // when - DefaultActionInvocation deserializable = (DefaultActionInvocation) actionInvocation.deserialize(ActionContext.getContext()); - - // then - assertNotNull(actionInvocation.container); - assertNotNull(deserializable.container); - assertEquals(mockContainer, deserializable.container); - } - public void testInvokingExistingExecuteMethod() throws Exception { // given DefaultActionInvocation dai = new DefaultActionInvocation(new HashMap(), false) { diff --git a/core/src/test/java/com/opensymphony/xwork2/spring/interceptor/TestActionInvocation.java b/core/src/test/java/com/opensymphony/xwork2/spring/interceptor/TestActionInvocation.java index 34392fbd3..fc37d4a55 100644 --- a/core/src/test/java/com/opensymphony/xwork2/spring/interceptor/TestActionInvocation.java +++ b/core/src/test/java/com/opensymphony/xwork2/spring/interceptor/TestActionInvocation.java @@ -86,12 +86,4 @@ public void setActionEventListener(ActionEventListener listener) { public void init(ActionProxy proxy) { } - public ActionInvocation serialize() { - return this; - } - - public ActionInvocation deserialize(ActionContext actionContext) { - return this; - } - } 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 f122dc78d..8b5b8cd0d 100644 --- a/core/src/test/java/org/apache/struts2/util/InvocationSessionStoreTest.java +++ b/core/src/test/java/org/apache/struts2/util/InvocationSessionStoreTest.java @@ -25,6 +25,10 @@ import com.opensymphony.xwork2.util.ValueStack; import org.apache.struts2.StrutsInternalTestCase; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.HashMap; import java.util.Map; @@ -40,7 +44,7 @@ private ActionInvocation invocation; - private Map session; + private Map session; private Mock invocationMock; private ValueStack stack; @@ -62,6 +66,40 @@ public void testValueStackReset() { assertEquals(stack, actionContext.getValueStack()); } + public void testActionContextReset() { + ActionContext actionContext = ActionContext.getContext(); + InvocationSessionStore.storeInvocation(INVOCATION_KEY, TOKEN_VALUE, invocation); + + ActionContext actionContext2 = new ActionContext(new HashMap()); + actionContext2.setSession(session); + ActionContext.setContext(actionContext2); + assertEquals(actionContext2, ActionContext.getContext()); + + InvocationSessionStore.loadInvocation(INVOCATION_KEY, TOKEN_VALUE); + assertEquals(actionContext, ActionContext.getContext()); + } + + public void testStoreAndLoadFromDeserializedSession() throws Exception { + InvocationSessionStore.storeInvocation(INVOCATION_KEY, TOKEN_VALUE, invocation); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(session);//WW-4873 invocation is not serializable but we should not fail at this line + oos.close(); + byte b[] = baos.toByteArray(); + baos.close(); + + ByteArrayInputStream bais = new ByteArrayInputStream(b); + ObjectInputStream ois = new ObjectInputStream(bais); + session = (Map) ois.readObject(); + ActionContext.getContext().setSession(session); + ois.close(); + bais.close(); + + ActionInvocation savedInvocation = InvocationSessionStore.loadInvocation(INVOCATION_KEY, TOKEN_VALUE); + assertNull(savedInvocation);//Currently we don't support invocation restore from serialized session + } + protected void setUp() throws Exception { super.setUp(); stack = ActionContext.getContext().getValueStack(); @@ -69,13 +107,12 @@ protected void setUp() throws Exception { ActionContext actionContext = new ActionContext(stack.getContext()); ActionContext.setContext(actionContext); - session = new HashMap(); + session = new HashMap<>(); actionContext.setSession(session); invocationMock = new Mock(ActionInvocation.class); invocation = (ActionInvocation) invocationMock.proxy(); - invocationMock.matchAndReturn("serialize", invocation); - invocationMock.matchAndReturn("deserialize", actionContext, invocation); + invocationMock.matchAndReturn("getInvocationContext", actionContext); actionContext.setValueStack(stack); invocationMock.matchAndReturn("getStack", stack); diff --git a/plugins/dwr/src/main/java/org/apache/struts2/validators/DWRValidator.java b/plugins/dwr/src/main/java/org/apache/struts2/validators/DWRValidator.java index 04c371afb..b77b59a6b 100644 --- a/plugins/dwr/src/main/java/org/apache/struts2/validators/DWRValidator.java +++ b/plugins/dwr/src/main/java/org/apache/struts2/validators/DWRValidator.java @@ -110,7 +110,6 @@ public ValidationAwareSupport doPost(String namespace, String actionName, Map pa } public static class ValidatorActionInvocation extends DefaultActionInvocation { - private static final long serialVersionUID = -7645433725470191275L; protected ValidatorActionInvocation(Map extraContext, boolean pushAction) throws Exception { super(extraContext, pushAction); diff --git a/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java b/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java index 01e3a11c5..dd8492799 100644 --- a/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java +++ b/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java @@ -556,8 +556,6 @@ protected void setUp() throws Exception { class MockActionInvocationEx extends MockActionInvocation { - private static final long serialVersionUID = 3057703805130170757L; - private boolean invoked; @Override diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionInvocation.java b/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionInvocation.java index e018591c6..0857a780e 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionInvocation.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionInvocation.java @@ -46,8 +46,6 @@ */ public class RestActionInvocation extends DefaultActionInvocation { - private static final long serialVersionUID = 3485701178946428716L; - private static final Logger LOG = LogManager.getLogger(RestActionInvocation.class); private ContentTypeHandlerManager handlerSelector; diff --git a/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/OldDecorator2NewStrutsDecorator.java b/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/OldDecorator2NewStrutsDecorator.java index f7b35de2d..b172eb4fb 100644 --- a/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/OldDecorator2NewStrutsDecorator.java +++ b/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/OldDecorator2NewStrutsDecorator.java @@ -140,8 +140,6 @@ protected String getEncoding() { static class DummyActionInvocation implements ActionInvocation { - private static final long serialVersionUID = -4808072199157363028L; - ActionSupport action; public DummyActionInvocation(ActionSupport action) { @@ -196,14 +194,6 @@ public void setActionEventListener(ActionEventListener listener) { public void init(ActionProxy proxy) { } - public ActionInvocation serialize() { - return null; - } - - public ActionInvocation deserialize(ActionContext actionContext) { - return null; - } - } } ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: users@infra.apache.org > NotSerializableException - org.apache.struts2.dispatcher.StrutsRequestWrapper > ----------------------------------------------------------------------------- > > Key: WW-4873 > URL: https://issues.apache.org/jira/browse/WW-4873 > Project: Struts 2 > Issue Type: Bug > Affects Versions: 2.5.13 > Reporter: Michael Hum > Assignee: Yasser Zamani > Fix For: 2.5.15 > > > We are attempting to test session replication on our websphere servers but run into the given error when websphere tries to serialize the session. > {code} > [10/18/17 10:33:38:094 EDT] 00000335 WASSession E MTMBuffWrapper getBytes write object exception. e= java.io.NotSerializableException: org.apache.struts2.dispatcher.StrutsRequestWrapper > {code} > It appears the ActionInvocation stores the ActionContext which stores the offending property: com.opensymphony.xwork2.dispatcher.HttpServletRequest --> StrutsRequestWrapper > After a little digging we narrowed it down to our use of the TokenSessionStoreInterceptor which stores the value in the session and uses it to redirect the failed request to the original one. Is this intended/expected? Or is there no requirement that the contents in the session be serializable - in which case we would have to look to our own solution. -- This message was sent by Atlassian JIRA (v6.4.14#64029)