BATCH-1712: use parent bean def for handler to avoid clashes of step instances
This commit is contained in:
@@ -20,6 +20,8 @@ import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -27,6 +29,8 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.batch.core.*;
|
||||
import org.springframework.batch.core.partition.PartitionHandler;
|
||||
import org.springframework.batch.core.partition.StepExecutionSplitter;
|
||||
import org.springframework.batch.core.partition.support.PartitionStep;
|
||||
import org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
@@ -41,7 +45,6 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Josh Long
|
||||
@@ -50,102 +53,185 @@ import org.springframework.util.ReflectionUtils;
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class PartitionStepParserTests implements ApplicationContextAware {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("job1")
|
||||
private Job job1;
|
||||
@Autowired
|
||||
@Qualifier("job1")
|
||||
private Job job1;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("job2")
|
||||
private Job job2;
|
||||
@Autowired
|
||||
@Qualifier("job2")
|
||||
private Job job2;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("job3")
|
||||
private Job job3;
|
||||
@Autowired
|
||||
@Qualifier("job3")
|
||||
private Job job3;
|
||||
|
||||
@Autowired
|
||||
private JobRepository jobRepository;
|
||||
@Autowired
|
||||
@Qualifier("job4")
|
||||
private Job job4;
|
||||
|
||||
@Autowired
|
||||
private MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean;
|
||||
@Autowired
|
||||
@Qualifier("job5")
|
||||
private Job job5;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
@Autowired
|
||||
@Qualifier("nameStoringTasklet")
|
||||
private NameStoringTasklet nameStoringTasklet;
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
@Autowired
|
||||
private JobRepository jobRepository;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mapJobRepositoryFactoryBean.clear();
|
||||
}
|
||||
@Autowired
|
||||
private MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T accessPrivateField(Object o, String fieldName) {
|
||||
Field field = ReflectionUtils.findField(o.getClass(), fieldName);
|
||||
boolean previouslyAccessibleValue = field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
T val = (T) ReflectionUtils.getField(field, o);
|
||||
field.setAccessible(previouslyAccessibleValue);
|
||||
return val;
|
||||
}
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
* BATCH-1509 we now support the ability define steps inline for partitioned steps.
|
||||
* this demonstates that the execution proceeds as expected and that the partitionhandler has a reference to the inline step definition
|
||||
*/
|
||||
@Test
|
||||
public void testNestedPartitionStepStepReference() throws Throwable {
|
||||
assertNotNull("the reference to the job3 configured in the XML file must not be null", job3);
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job3.getName(), new JobParameters());
|
||||
private List<String> savedStepNames = new ArrayList<String>();
|
||||
|
||||
job3.execute(jobExecution);
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
for (StepExecution se : jobExecution.getStepExecutions()) {
|
||||
String stepExecutionName = se.getStepName();
|
||||
if (stepExecutionName.equalsIgnoreCase("j3s1")) { // the partitioned step
|
||||
PartitionStep partitionStep = (PartitionStep) this.applicationContext.getBean(stepExecutionName);
|
||||
@Before
|
||||
public void setUp() {
|
||||
nameStoringTasklet.setStepNamesList(savedStepNames);
|
||||
mapJobRepositoryFactoryBean.clear();
|
||||
}
|
||||
|
||||
// prove that the reference in the {@link TaskExecutorPartitionHandler} is the step configured inline
|
||||
TaskExecutorPartitionHandler taskExecutorPartitionHandler = accessPrivateField(partitionStep, "partitionHandler");
|
||||
TaskletStep taskletStep = accessPrivateField(taskExecutorPartitionHandler, "step");
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T accessPrivateField(Object o, String fieldName) {
|
||||
Field field = ReflectionUtils.findField(o.getClass(), fieldName);
|
||||
boolean previouslyAccessibleValue = field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
T val = (T) ReflectionUtils.getField(field, o);
|
||||
field.setAccessible(previouslyAccessibleValue);
|
||||
return val;
|
||||
}
|
||||
|
||||
assertNotNull("the taskletStep wasn't configured with a step. " +
|
||||
"We're trusting that the factory ensured " +
|
||||
"a reference was given.", taskletStep);
|
||||
}
|
||||
}
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
}
|
||||
@Test
|
||||
public void testCustomHandlerRefStep() throws Exception {
|
||||
assertNotNull(job5);
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job5.getName(), new JobParameters());
|
||||
job5.execute(jobExecution);
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
List<String> stepNames = getStepNames(jobExecution);
|
||||
assertEquals(1, stepNames.size());
|
||||
assertEquals("[j5s1]", stepNames.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultHandlerStep() throws Exception {
|
||||
assertNotNull(job1);
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job1.getName(), new JobParameters());
|
||||
job1.execute(jobExecution);
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
List<String> stepNames = getStepNames(jobExecution);
|
||||
assertEquals(3, stepNames.size());
|
||||
assertEquals("[s1, step1:partition0, step1:partition1]", stepNames.toString());
|
||||
}
|
||||
/**
|
||||
* BATCH-1509 we now support the ability define steps inline for partitioned
|
||||
* steps. this demonstates that the execution proceeds as expected and that
|
||||
* the partitionhandler has a reference to the inline step definition
|
||||
*/
|
||||
@Test
|
||||
public void testNestedPartitionStep() throws Throwable {
|
||||
assertNotNull("the reference to the job4 configured in the XML file must not be null", job4);
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job4.getName(), new JobParameters());
|
||||
|
||||
@Test
|
||||
public void testHandlerRefStep() throws Exception {
|
||||
assertNotNull(job2);
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job2.getName(), new JobParameters());
|
||||
job2.execute(jobExecution);
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
List<String> stepNames = getStepNames(jobExecution);
|
||||
assertEquals(5, stepNames.size());
|
||||
assertEquals("[s2, s3, step1:partition0, step1:partition1, step1:partition2]", stepNames.toString());
|
||||
}
|
||||
job4.execute(jobExecution);
|
||||
|
||||
private List<String> getStepNames(JobExecution jobExecution) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
|
||||
list.add(stepExecution.getStepName());
|
||||
}
|
||||
Collections.sort(list);
|
||||
return list;
|
||||
}
|
||||
for (StepExecution se : jobExecution.getStepExecutions()) {
|
||||
String stepExecutionName = se.getStepName();
|
||||
if (stepExecutionName.equalsIgnoreCase("j4s1")) { // the partitioned
|
||||
// step
|
||||
PartitionStep partitionStep = (PartitionStep) this.applicationContext.getBean(stepExecutionName);
|
||||
|
||||
// prove that the reference in the {@link
|
||||
// TaskExecutorPartitionHandler} is the step configured inline
|
||||
TaskExecutorPartitionHandler taskExecutorPartitionHandler = accessPrivateField(partitionStep,
|
||||
"partitionHandler");
|
||||
TaskletStep taskletStep = accessPrivateField(taskExecutorPartitionHandler, "step");
|
||||
|
||||
assertNotNull("the taskletStep wasn't configured with a step. "
|
||||
+ "We're trusting that the factory ensured " + "a reference was given.", taskletStep);
|
||||
}
|
||||
}
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
// Step names not saved by this one (it geosn't have that tasklet)
|
||||
assertEquals("[]", savedStepNames.toString());
|
||||
List<String> stepNames = getStepNames(jobExecution);
|
||||
assertEquals(4, stepNames.size());
|
||||
assertEquals("[j4s1, j4s1:partition0, j4s1:partition1, j4s1:partition2]", stepNames.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* BATCH-1509 we now support the ability define steps inline for partitioned
|
||||
* steps. this demonstates that the execution proceeds as expected and that
|
||||
* the partitionhandler has a reference to the inline step definition
|
||||
*/
|
||||
@Test
|
||||
public void testNestedPartitionStepStepReference() throws Throwable {
|
||||
assertNotNull("the reference to the job3 configured in the XML file must not be null", job3);
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job3.getName(), new JobParameters());
|
||||
|
||||
job3.execute(jobExecution);
|
||||
|
||||
for (StepExecution se : jobExecution.getStepExecutions()) {
|
||||
String stepExecutionName = se.getStepName();
|
||||
if (stepExecutionName.equalsIgnoreCase("j3s1")) { // the partitioned
|
||||
// step
|
||||
PartitionStep partitionStep = (PartitionStep) this.applicationContext.getBean(stepExecutionName);
|
||||
|
||||
// prove that the reference in the {@link
|
||||
// TaskExecutorPartitionHandler} is the step configured inline
|
||||
TaskExecutorPartitionHandler taskExecutorPartitionHandler = accessPrivateField(partitionStep,
|
||||
"partitionHandler");
|
||||
TaskletStep taskletStep = accessPrivateField(taskExecutorPartitionHandler, "step");
|
||||
|
||||
assertNotNull("the taskletStep wasn't configured with a step. "
|
||||
+ "We're trusting that the factory ensured " + "a reference was given.", taskletStep);
|
||||
}
|
||||
}
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
Collections.sort(savedStepNames);
|
||||
assertEquals("[j3s1:partition0, j3s1:partition1, j3s1:partition2]", savedStepNames.toString());
|
||||
List<String> stepNames = getStepNames(jobExecution);
|
||||
assertEquals(4, stepNames.size());
|
||||
assertEquals("[j3s1, j3s1:partition0, j3s1:partition1, j3s1:partition2]", stepNames.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultHandlerStep() throws Exception {
|
||||
assertNotNull(job1);
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job1.getName(), new JobParameters());
|
||||
job1.execute(jobExecution);
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
Collections.sort(savedStepNames);
|
||||
assertEquals("[step1:partition0, step1:partition1]", savedStepNames.toString());
|
||||
List<String> stepNames = getStepNames(jobExecution);
|
||||
assertEquals(3, stepNames.size());
|
||||
assertEquals("[s1, step1:partition0, step1:partition1]", stepNames.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandlerRefStep() throws Exception {
|
||||
assertNotNull(job2);
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job2.getName(), new JobParameters());
|
||||
job2.execute(jobExecution);
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
Collections.sort(savedStepNames);
|
||||
assertEquals("[s3, step1:partition0, step1:partition1, step1:partition2]", savedStepNames.toString());
|
||||
List<String> stepNames = getStepNames(jobExecution);
|
||||
assertEquals(5, stepNames.size());
|
||||
assertEquals("[s2, s3, step1:partition0, step1:partition1, step1:partition2]", stepNames.toString());
|
||||
}
|
||||
|
||||
private List<String> getStepNames(JobExecution jobExecution) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
|
||||
list.add(stepExecution.getStepName());
|
||||
}
|
||||
Collections.sort(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static class CustomPartitionHandler implements PartitionHandler {
|
||||
|
||||
public Collection<StepExecution> handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution)
|
||||
throws Exception {
|
||||
return Arrays.asList(stepExecution);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.core.ExitStatus;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
@@ -60,12 +59,11 @@ public class TaskExecutorPartitionHandlerTests {
|
||||
handler.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Ignore //TODO update or simply remove?
|
||||
@Test
|
||||
public void testAfterPropertiesSet() throws Exception {
|
||||
public void testNullStep() throws Exception {
|
||||
handler = new TaskExecutorPartitionHandler();
|
||||
try {
|
||||
handler.afterPropertiesSet();
|
||||
handler.handle(stepExecutionSplitter, stepExecution);
|
||||
fail("Expected IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
|
||||
Reference in New Issue
Block a user