Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ public class BackgroundProcess implements Serializable {

private static final long serialVersionUID = 3884464776311686443L;

protected Object action;
protected ActionInvocation invocation;
//WW-4900 transient since 2.5.15
transient protected ActionInvocation invocation;
transient protected Exception exception;

protected String result;
protected Exception exception;
protected boolean done;

/**
Expand All @@ -46,7 +47,6 @@ public class BackgroundProcess implements Serializable {
*/
public BackgroundProcess(String threadName, final ActionInvocation invocation, int threadPriority) {
this.invocation = invocation;
this.action = invocation.getAction();
try {
final Thread t = new Thread(new Runnable() {
public void run() {
Expand Down Expand Up @@ -96,7 +96,7 @@ protected void afterInvocation() throws Exception {
* @return the action.
*/
public Object getAction() {
return action;
return invocation.getAction();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ protected String doIntercept(ActionInvocation actionInvocation) throws Exception
synchronized (httpSession) {
BackgroundProcess bp = (BackgroundProcess) session.get(KEY + name);

//WW-4900 Checks if from a de-serialized session? so background thread missed, let's start a new one.
if (bp != null && bp.getInvocation() == null) {
session.remove(KEY + name);
bp = null;
}

if ((!executeAfterValidationPass || secondTime) && bp == null) {
bp = getNewBackgroundProcess(name, actionInvocation, threadPriority);
session.put(KEY + name, bp);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.struts2.interceptor;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import org.apache.struts2.StrutsInternalTestCase;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
* Test case for BackgroundProcessTest.
*/
public class BackgroundProcessTest extends StrutsInternalTestCase {

public void testSerializeDeserialize() throws Exception {
MockActionInvocation invocation = new MockActionInvocation();
invocation.setResultCode("BackgroundProcessTest.testSerializeDeserialize");
invocation.setInvocationContext(ActionContext.getContext());

BackgroundProcess bp = new BackgroundProcess("BackgroundProcessTest.testSerializeDeserialize", invocation
, Thread.MIN_PRIORITY);

bp.exception = new Exception();
bp.done = true;

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(bp);
oos.close();
assertTrue("should have serialized data", baos.size() > 0);
byte b[] = baos.toByteArray();
baos.close();

ByteArrayInputStream bais = new ByteArrayInputStream(b);
ObjectInputStream ois = new ObjectInputStream(bais);
BackgroundProcess deserializedBp = (BackgroundProcess) ois.readObject();
ois.close();
bais.close();

assertNull("invocation should not be serialized", deserializedBp.invocation);
assertNull("exception should not be serialized", deserializedBp.exception);
assertEquals(bp.result, deserializedBp.result);
assertEquals(bp.done, deserializedBp.done);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
import org.apache.struts2.views.jsp.StrutsMockHttpSession;

import javax.servlet.http.HttpSession;
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 Down Expand Up @@ -159,6 +163,41 @@ public void testWaitDelayAndJobAlreadyDone2() throws Exception {
assertTrue("Job done already after 500 so there should not be such long delay", diff <= 1000);
}

public void testFromDeserializedSession() throws Exception {
waitInterceptor.setDelay(0);
waitInterceptor.setDelaySleepInterval(0);

ActionProxy proxy = buildProxy("action1");
String result = proxy.execute();
assertEquals("wait", result);

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(session);//WW-4900 action1 and invocation are 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();
context.put(ActionContext.SESSION, session);
ois.close();
bais.close();

Thread.sleep(1000);

ActionProxy proxy2 = buildProxy("action1");
String result2 = proxy2.execute();
assertEquals("wait", result2);//WW-4900 A new thread should be started when background thread missed

Thread.sleep(1000);

ActionProxy proxy3 = buildProxy("action1");
String result3 = proxy3.execute();
assertEquals("success", result3);
}

protected ActionProxy buildProxy(String actionName) throws Exception {
return actionProxyFactory.createActionProxy("", actionName, null, context);
}
Expand Down