Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WW-4873 Makes ActionInvocation not serializable and InvocationSessionStore$InvocationContext transient #192

Merged
merged 2 commits into from
Dec 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 1 addition & 19 deletions core/src/main/java/com/opensymphony/xwork2/ActionInvocation.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 <code>invoke()</code> method, initially by the {@link ActionProxy}, then by the Interceptors, the
Expand All @@ -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.
Expand Down Expand Up @@ -178,20 +176,4 @@ public interface ActionInvocation extends Serializable {

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);

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,4 @@ public ActionEventListener getActionEventListener() {
public void init(ActionProxy proxy) {
}

public ActionInvocation serialize() {
return this;
}

public ActionInvocation deserialize(ActionContext actionContext) {
return this;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -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);
Expand Down Expand Up @@ -109,7 +112,9 @@ private static class InvocationContext implements Serializable {

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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,34 +75,6 @@ public void testInvoke() throws Exception {
assertTrue(mockInterceptor3.isExecuted());
}

public void testSerialization() throws Exception {
// given
DefaultActionInvocation actionInvocation = new DefaultActionInvocation(new HashMap<String, Object>(), 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<String, Object>(), 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<String, Object>(), false) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -40,7 +44,7 @@ public class InvocationSessionStoreTest extends StrutsInternalTestCase {


private ActionInvocation invocation;
private Map session;
private Map<String, Object> session;
private Mock invocationMock;
private ValueStack stack;

Expand All @@ -62,20 +66,53 @@ 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<String, Object>());
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();

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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, Object> extraContext, boolean pushAction) throws Exception {
super(extraContext, pushAction);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -556,8 +556,6 @@ protected void setUp() throws Exception {

class MockActionInvocationEx extends MockActionInvocation {

private static final long serialVersionUID = 3057703805130170757L;

private boolean invoked;

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,6 @@ protected String getEncoding() {

static class DummyActionInvocation implements ActionInvocation {

private static final long serialVersionUID = -4808072199157363028L;

ActionSupport action;

public DummyActionInvocation(ActionSupport action) {
Expand Down Expand Up @@ -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;
}

}

}