Added the implementation of a post processor to lazily init partition
related artifacts * Added BeanFactoryPostProcessor * Fixed StepContext creation (now creates one per thread) * Fixed StepContext exit status processing (now keeps track of being set manualy or not * Created new Flow implementation to handle JSR-352 state transitions * Updated flow parsing to not default to completed if no other transitions are provided
This commit is contained in:
@@ -26,7 +26,7 @@ import org.springframework.batch.core.job.flow.support.state.AbstractState;
|
||||
*/
|
||||
public class StateSupport extends AbstractState {
|
||||
|
||||
private FlowExecutionStatus status;
|
||||
protected FlowExecutionStatus status;
|
||||
|
||||
public StateSupport(String name) {
|
||||
this(name, FlowExecutionStatus.COMPLETED);
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.core.ExitStatus;
|
||||
import org.springframework.batch.core.job.flow.FlowExecution;
|
||||
@@ -41,9 +42,14 @@ import org.springframework.batch.core.job.flow.StateSupport;
|
||||
*/
|
||||
public class SimpleFlowTests {
|
||||
|
||||
private SimpleFlow flow = new SimpleFlow("job");
|
||||
protected SimpleFlow flow;
|
||||
|
||||
private FlowExecutor executor = new JobFlowExecutorSupport();
|
||||
protected FlowExecutor executor = new JobFlowExecutorSupport();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
flow = new SimpleFlow("job");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testEmptySteps() throws Exception {
|
||||
@@ -205,22 +211,13 @@ public class SimpleFlowTests {
|
||||
assertNull(state);
|
||||
}
|
||||
|
||||
private List<StateTransition> collect(StateTransition s1, StateTransition s2) {
|
||||
protected List<StateTransition> collect(StateTransition... states) {
|
||||
List<StateTransition> list = new ArrayList<StateTransition>();
|
||||
list.add(s1);
|
||||
list.add(s2);
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<StateTransition> collect(StateTransition s1, StateTransition s2, StateTransition s3) {
|
||||
List<StateTransition> list = collect(s1, s2);
|
||||
list.add(s3);
|
||||
return list;
|
||||
}
|
||||
for (StateTransition stateTransition : states) {
|
||||
list.add(stateTransition);
|
||||
}
|
||||
|
||||
private List<StateTransition> collect(StateTransition s1, StateTransition s2, StateTransition s3, StateTransition s4) {
|
||||
List<StateTransition> list = collect(s1, s2, s3);
|
||||
list.add(s4);
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -228,7 +225,7 @@ public class SimpleFlowTests {
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
private static class StubState extends StateSupport {
|
||||
protected static class StubState extends StateSupport {
|
||||
|
||||
/**
|
||||
* @param string
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
package org.springframework.batch.core.jsr;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.batch.runtime.context.StepContext;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext;
|
||||
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
|
||||
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
|
||||
public class StepContextFactoryBeanTests {
|
||||
|
||||
private StepContextFactoryBean factory;
|
||||
@Mock
|
||||
private BatchPropertyContext propertyContext;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
factory = new StepContextFactoryBean();
|
||||
factory.setBatchPropertyContext(propertyContext);
|
||||
}
|
||||
|
||||
@Test(expected=FactoryBeanNotInitializedException.class)
|
||||
public void testNoStepExecutionRegistered() throws Exception {
|
||||
factory.getObject();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectSingleThread() throws Exception {
|
||||
StepSynchronizationManager.register(new StepExecution("step1", new JobExecution(5l), 3l));
|
||||
|
||||
StepContext context1 = factory.getObject();
|
||||
StepContext context2 = factory.getObject();
|
||||
|
||||
assertTrue(context1 == context2);
|
||||
assertEquals(3l, context1.getStepExecutionId());
|
||||
|
||||
StepSynchronizationManager.close();
|
||||
|
||||
StepSynchronizationManager.register(new StepExecution("step2", new JobExecution(5l), 2l));
|
||||
|
||||
StepContext context3 = factory.getObject();
|
||||
StepContext context4 = factory.getObject();
|
||||
|
||||
assertTrue(context3 == context4);
|
||||
assertTrue(context3 != context2);
|
||||
assertEquals(2l, context3.getStepExecutionId());
|
||||
|
||||
StepSynchronizationManager.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectSingleThreadWithProperties() throws Exception {
|
||||
Properties props = new Properties();
|
||||
props.put("key1", "value1");
|
||||
|
||||
when(propertyContext.getStepProperties("step3")).thenReturn(props);
|
||||
|
||||
StepSynchronizationManager.register(new StepExecution("step3", new JobExecution(5l), 3l));
|
||||
|
||||
StepContext context1 = factory.getObject();
|
||||
StepContext context2 = factory.getObject();
|
||||
|
||||
assertTrue(context1 == context2);
|
||||
assertEquals(3l, context1.getStepExecutionId());
|
||||
assertEquals("value1", context1.getProperties().get("key1"));
|
||||
|
||||
StepSynchronizationManager.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectMultiThread() throws Exception {
|
||||
List<Future<StepContext>> stepContexts = new ArrayList<Future<StepContext>>();
|
||||
|
||||
AsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
final long count = i;
|
||||
stepContexts.add(executor.submit(new Callable<StepContext>() {
|
||||
|
||||
@Override
|
||||
public StepContext call() throws Exception {
|
||||
try {
|
||||
StepSynchronizationManager.register(new StepExecution("step" + count, new JobExecution(count)));
|
||||
StepContext context = factory.getObject();
|
||||
Thread.sleep(1000l);
|
||||
return context;
|
||||
} catch (Throwable ignore) {
|
||||
return null;
|
||||
}finally {
|
||||
StepSynchronizationManager.release();
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
Set<StepContext> contexts = new HashSet<StepContext>();
|
||||
for (Future<StepContext> future : stepContexts) {
|
||||
contexts.add(future.get());
|
||||
}
|
||||
|
||||
assertEquals(4, contexts.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectMultiThreadWithProperties() throws Exception {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
Properties props = new Properties();
|
||||
props.put("step" + i, "step" + i + "value");
|
||||
|
||||
when(propertyContext.getStepProperties("step" + i)).thenReturn(props);
|
||||
}
|
||||
|
||||
List<Future<StepContext>> stepContexts = new ArrayList<Future<StepContext>>();
|
||||
|
||||
AsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
final long count = i;
|
||||
stepContexts.add(executor.submit(new Callable<StepContext>() {
|
||||
|
||||
@Override
|
||||
public StepContext call() throws Exception {
|
||||
try {
|
||||
StepSynchronizationManager.register(new StepExecution("step" + count, new JobExecution(count)));
|
||||
StepContext context = factory.getObject();
|
||||
Thread.sleep(1000l);
|
||||
return context;
|
||||
} catch (Throwable ignore) {
|
||||
return null;
|
||||
}finally {
|
||||
StepSynchronizationManager.release();
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
Set<StepContext> contexts = new HashSet<StepContext>();
|
||||
for (Future<StepContext> future : stepContexts) {
|
||||
contexts.add(future.get());
|
||||
}
|
||||
|
||||
assertEquals(4, contexts.size());
|
||||
|
||||
for (StepContext stepContext : contexts) {
|
||||
assertEquals(stepContext.getStepName() + "value", stepContext.getProperties().get(stepContext.getStepName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,12 +32,15 @@ import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobParametersBuilder;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.util.ExecutionContextUserSupport;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
public class StepContextTests {
|
||||
|
||||
private StepExecution stepExecution;
|
||||
private StepContext stepContext;
|
||||
private ExecutionContext executionContext;
|
||||
private ExecutionContextUserSupport executionContextUserSupport = new ExecutionContextUserSupport(ClassUtils.getShortName(StepContext.class));
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -68,6 +71,8 @@ public class StepContextTests {
|
||||
@Test
|
||||
public void testBasicProperties() {
|
||||
assertEquals(javax.batch.runtime.BatchStatus.STARTED, stepContext.getBatchStatus());
|
||||
assertEquals(null, stepContext.getExitStatus());
|
||||
stepContext.setExitStatus("customExitStatus");
|
||||
assertEquals("customExitStatus", stepContext.getExitStatus());
|
||||
assertEquals(5l, stepContext.getStepExecutionId());
|
||||
assertEquals("testStep", stepContext.getStepName());
|
||||
@@ -121,7 +126,7 @@ public class StepContextTests {
|
||||
String data = "saved data";
|
||||
stepContext.setPersistentUserData(data);
|
||||
assertEquals(data, stepContext.getPersistentUserData());
|
||||
assertEquals(data, executionContext.get("batch_jsr_persistentUserData"));
|
||||
assertEquals(data, executionContext.get(executionContextUserSupport.getKey("batch_jsr_persistentUserData")));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -15,11 +15,15 @@ import org.springframework.batch.core.ExitStatus;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobParametersBuilder;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.item.util.ExecutionContextUserSupport;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
public class StepExecutionTests {
|
||||
|
||||
private StepExecution stepExecution;
|
||||
private javax.batch.runtime.StepExecution jsrStepExecution;
|
||||
//The API that sets the persisted user data is on the StepContext so the key within the ExecutionContext is StepContext
|
||||
private ExecutionContextUserSupport executionContextUserSupport = new ExecutionContextUserSupport(ClassUtils.getShortName(StepContext.class));
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -39,7 +43,7 @@ public class StepExecutionTests {
|
||||
stepExecution.setWriteSkipCount(8);
|
||||
stepExecution.setStartTime(new Date(0));
|
||||
stepExecution.setEndTime(new Date(10000000));
|
||||
stepExecution.getExecutionContext().put("batch_jsr_persistentUserData", "persisted data");
|
||||
stepExecution.getExecutionContext().put(executionContextUserSupport.getKey("batch_jsr_persistentUserData"), "persisted data");
|
||||
|
||||
jsrStepExecution = new org.springframework.batch.core.jsr.StepExecution(stepExecution);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.batch.core.jsr.configuration.xml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@@ -38,7 +40,6 @@ import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.springframework.batch.core.jsr.job.flow.support;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.ExitStatus;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.job.flow.FlowExecution;
|
||||
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
|
||||
import org.springframework.batch.core.job.flow.State;
|
||||
import org.springframework.batch.core.job.flow.StateSupport;
|
||||
import org.springframework.batch.core.job.flow.support.JobFlowExecutorSupport;
|
||||
import org.springframework.batch.core.job.flow.support.SimpleFlowTests;
|
||||
import org.springframework.batch.core.job.flow.support.StateTransition;
|
||||
|
||||
public class DefaultFlowTests extends SimpleFlowTests {
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
flow = new DefaultFlow("flow1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextBasedOnBatchStatus() throws Exception {
|
||||
StepExecution stepExecution = new StepExecution("step1", new JobExecution(5l));
|
||||
stepExecution.setExitStatus(new ExitStatus("unmapped exit code"));
|
||||
stepExecution.setStatus(BatchStatus.FAILED);
|
||||
executor = new FlowExecutor(stepExecution);
|
||||
|
||||
State startState = new StateSupport("step1", new FlowExecutionStatus("unmapped exit code"));
|
||||
State endState = new StateSupport("failed", FlowExecutionStatus.FAILED);
|
||||
|
||||
StateTransition failureTransition = StateTransition.createStateTransition(startState, "FAILED", "failed");
|
||||
StateTransition endTransition = StateTransition.createEndStateTransition(endState);
|
||||
flow.setStateTransitions(collect(failureTransition, endTransition));
|
||||
flow.afterPropertiesSet();
|
||||
FlowExecution execution = flow.start(executor);
|
||||
assertEquals(FlowExecutionStatus.FAILED, execution.getStatus());
|
||||
assertEquals("failed", execution.getName());
|
||||
}
|
||||
|
||||
public static class FlowExecutor extends JobFlowExecutorSupport {
|
||||
|
||||
private StepExecution stepExecution;
|
||||
|
||||
public FlowExecutor(StepExecution stepExecution) {
|
||||
this.stepExecution = stepExecution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StepExecution getStepExecution() {
|
||||
return stepExecution;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user