/*
* #%L
* BroadleafCommerce Integration
* %%
* Copyright (C) 2009 - 2016 Broadleaf Commerce
* %%
* Licensed 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.
* #L%
*/
/**
*
*/
package org.broadleafcommerce.common.workflow;
import org.broadleafcommerce.core.workflow.Activity;
import org.broadleafcommerce.core.workflow.BaseActivity;
import org.broadleafcommerce.core.workflow.DefaultProcessContextImpl;
import org.broadleafcommerce.core.workflow.ProcessContext;
import org.broadleafcommerce.core.workflow.ProcessContextFactory;
import org.broadleafcommerce.core.workflow.SequenceProcessor;
import org.broadleafcommerce.core.workflow.WorkflowException;
import org.broadleafcommerce.core.workflow.state.RollbackFailureException;
import org.broadleafcommerce.core.workflow.state.RollbackHandler;
import org.broadleafcommerce.test.BaseTest;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
/**
* Ensures that activities are rolled back in the correct order
*
* @author Phillip Verheyden (phillipuniverse)
*/
public class RollbackTest extends BaseTest {
@Resource(name = "testRollbackWorkflow")
protected SequenceProcessor testRollbackWorkflow;
@Test
public void testRollbackOrder() {
List<String> results = new ArrayList<String>();
boolean exceptionThrown = false;
try {
testRollbackWorkflow.doActivities(results);
} catch (WorkflowException e) {
exceptionThrown = true;
}
List<String> expected = Arrays.asList("Activity1",
"Activity2",
"ActivityA",
"RollbackActivityA",
"NestedActivityException",
"RollbackActivity2",
"RollbackActivity1");
Assert.assertTrue(exceptionThrown);
Assert.assertEquals(results, expected, "Rollback occurred out of order");
}
public static class SimpleActivity extends BaseActivity<ProcessContext<List<String>>> {
protected String name;
public SimpleActivity(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public ProcessContext<List<String>> execute(ProcessContext<List<String>> context) throws Exception {
context.getSeedData().add(name);
return context;
}
@Override
public boolean getAutomaticallyRegisterRollbackHandler() {
return true;
}
}
public static class SimpleRollbackHandler implements RollbackHandler<List<String>> {
@Override
public void rollbackState(Activity<? extends ProcessContext<List<String>>> activity, ProcessContext<List<String>> processContext, Map<String, Object> stateConfiguration) throws RollbackFailureException {
processContext.getSeedData().add("Rollback" + ((SimpleActivity) activity).getName());
}
}
public static class NestedActivity extends BaseActivity<ProcessContext<List<String>>> {
protected SequenceProcessor workflow;
public NestedActivity(SequenceProcessor workflow) {
this.workflow = workflow;
}
@Override
public ProcessContext<List<String>> execute(ProcessContext<List<String>> context) throws Exception {
try {
workflow.doActivities(context.getSeedData());
} catch (WorkflowException e) {
context.getSeedData().add("NestedActivityException");
throw e;
}
return context;
}
}
public static class ExceptionActivity extends BaseActivity<ProcessContext<List<String>>> {
@Override
public ProcessContext<List<String>> execute(ProcessContext<List<String>> context) throws Exception {
throw new RuntimeException();
}
}
public static class DummyProcessContextFactory implements ProcessContextFactory<Object, Object> {
@Override
public ProcessContext<Object> createContext(Object preSeedData) throws WorkflowException {
ProcessContext<Object> context = new DefaultProcessContextImpl<>();
context.setSeedData(preSeedData);
return context;
}
}
}