RESOLVED - issue BATCH-404: FactoryBeans for step configuration
http://jira.springframework.org/browse/BATCH-404 Tidied up listener registration and integration a bit
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry including="**/*.java" kind="src" path="src/main/java"/>
|
||||
<classpathentry including="**/*.java" kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry including="**/*.java" kind="src" output="bin/test-classes" path="src/test/java"/>
|
||||
<classpathentry excluding="**/*.java" including="**" kind="src" path="src/main/resources"/>
|
||||
<classpathentry excluding="**/*.java" including="**" kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry exported="true" kind="con" path="org.devzuz.q.maven.jdt.core.mavenClasspathContainer"/>
|
||||
<classpathentry excluding="**/*.java" including="**" kind="src" output="bin/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.devzuz.q.maven.jdt.core.mavenClasspathContainer"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>spring-batch-core</name>
|
||||
<comment>Core domain for batch processing, expressing a domain of Jobs, Steps, Chunks, etc.</comment>
|
||||
<projects>
|
||||
<project>spring-batch-infrastructure</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.springframework.ide.eclipse.core.springbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.springframework.ide.eclipse.core.springnature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.devzuz.q.maven.jdt.core.mavenNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>spring-batch-core</name>
|
||||
<comment>Core domain for batch processing, expressing a domain of Jobs, Steps, Chunks, etc.</comment>
|
||||
<projects>
|
||||
<project>spring-batch-infrastructure</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.springframework.ide.eclipse.core.springbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.springframework.ide.eclipse.core.springnature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.devzuz.q.maven.jdt.core.mavenNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
|
||||
@@ -15,8 +15,12 @@
|
||||
*/
|
||||
package org.springframework.batch.core.domain;
|
||||
|
||||
|
||||
/**
|
||||
* Provide callbacks at specific points in the lifecycle of a {@link Job}.
|
||||
* Implementations can be stateful if they are careful to either ensure thread
|
||||
* safety, or to use one instance of a listener per job, assuming that job
|
||||
* instances themselves are not used by more than one thread.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@@ -30,7 +34,7 @@ public interface JobListener {
|
||||
void beforeJob(JobExecution jobExecution);
|
||||
|
||||
/**
|
||||
*
|
||||
* Callback after successful completion of a job.
|
||||
*/
|
||||
void afterJob();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.springframework.batch.execution.step.ItemOrientedStep;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.springframework.util.Assert;
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractStepFactoryBean extends AbstractFactoryBean implements BeanNameAware {
|
||||
public abstract class AbstractStepFactoryBean implements FactoryBean, BeanNameAware {
|
||||
|
||||
private String name;
|
||||
|
||||
@@ -49,6 +49,8 @@ public abstract class AbstractStepFactoryBean extends AbstractFactoryBean implem
|
||||
|
||||
private JobRepository jobRepository;
|
||||
|
||||
private boolean singleton = true;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@@ -140,7 +142,12 @@ public abstract class AbstractStepFactoryBean extends AbstractFactoryBean implem
|
||||
this.transactionManager = transactionManager;
|
||||
}
|
||||
|
||||
protected Object createInstance() throws Exception {
|
||||
/**
|
||||
* Create a {@link Step} from the configuration provided.
|
||||
*
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
||||
*/
|
||||
public final Object getObject() throws Exception {
|
||||
ItemOrientedStep step = new ItemOrientedStep(getName());
|
||||
applyConfiguration(step);
|
||||
return step;
|
||||
@@ -156,7 +163,7 @@ public abstract class AbstractStepFactoryBean extends AbstractFactoryBean implem
|
||||
Assert.notNull(getItemWriter(), "ItemWriter must be provided");
|
||||
Assert.notNull(jobRepository, "JobRepository must be provided");
|
||||
Assert.notNull(transactionManager, "TransactionManager must be provided");
|
||||
|
||||
|
||||
step.setItemProcessor(new SimpleItemHandler(itemReader, itemWriter));
|
||||
step.setTransactionManager(transactionManager);
|
||||
step.setJobRepository(jobRepository);
|
||||
@@ -169,4 +176,23 @@ public abstract class AbstractStepFactoryBean extends AbstractFactoryBean implem
|
||||
return Step.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true by default, but in most cases a {@link Step} should not be
|
||||
* treated as thread safe. Clients are recommended to create a new step for
|
||||
* each job execution.
|
||||
*
|
||||
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||
*/
|
||||
public boolean isSingleton() {
|
||||
return this.singleton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the singleton flag.
|
||||
* @param singleton the value to set. Defaults to true.
|
||||
*/
|
||||
public void setSingleton(boolean singleton) {
|
||||
this.singleton = singleton;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,9 +39,6 @@ import org.springframework.batch.retry.support.RetryTemplate;
|
||||
* limit given by the {@link RetryPolicy}. When the retry is exhausted instead
|
||||
* of the item being skipped it is handled by an {@link ItemRecoverer}.<br/>
|
||||
*
|
||||
* TODO: checking for null retry callback is a sucky way of determining if a
|
||||
* stateful retry has been requested.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@@ -51,6 +48,8 @@ public class StatefulRetryStepFactoryBean extends DefaultStepFactoryBean {
|
||||
|
||||
private ItemKeyGenerator itemKeyGenerator;
|
||||
|
||||
private ItemRecoverer itemRecoverer;
|
||||
|
||||
/**
|
||||
* Public setter for the {@link RetryPolicy}.
|
||||
* @param retryPolicy the {@link RetryPolicy} to set
|
||||
@@ -73,6 +72,18 @@ public class StatefulRetryStepFactoryBean extends DefaultStepFactoryBean {
|
||||
this.itemKeyGenerator = itemKeyGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the {@link ItemRecoverer}. If this is set the
|
||||
* {@link ItemRecoverer#recover(Object, Throwable)} will be called when
|
||||
* retry is exhausted, and within the business transaction (which will not
|
||||
* roll back because of any other item-related errors).
|
||||
*
|
||||
* @param itemRecoverer the {@link ItemRecoverer} to set
|
||||
*/
|
||||
public void setItemRecoverer(ItemRecoverer itemRecoverer) {
|
||||
this.itemRecoverer = itemRecoverer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param step
|
||||
*
|
||||
@@ -87,36 +98,20 @@ public class StatefulRetryStepFactoryBean extends DefaultStepFactoryBean {
|
||||
// exception handler limit, so this is a hack for now.
|
||||
getStepOperations().setExceptionHandler(new SimpleLimitExceptionHandler(Integer.MAX_VALUE));
|
||||
|
||||
ItemReaderRetryCallback retryCallback = new ItemReaderRetryCallback(getItemReader(), getKeyGenerator(),
|
||||
ItemReaderRetryCallback retryCallback = new ItemReaderRetryCallback(getItemReader(), itemKeyGenerator,
|
||||
getItemWriter());
|
||||
retryCallback.setRecoverer(itemRecoverer);
|
||||
ItemReaderRetryPolicy itemProviderRetryPolicy = new ItemReaderRetryPolicy(retryPolicy);
|
||||
|
||||
RetryTemplate retryTemplate = new RetryTemplate();
|
||||
retryTemplate.setRetryPolicy(itemProviderRetryPolicy);
|
||||
|
||||
StatefulRetryItemHandler itemProcessor = new StatefulRetryItemHandler(getItemReader(), getItemWriter(), retryTemplate, retryCallback);
|
||||
|
||||
StatefulRetryItemHandler itemProcessor = new StatefulRetryItemHandler(getItemReader(), getItemWriter(),
|
||||
retryTemplate, retryCallback);
|
||||
|
||||
step.setItemProcessor(itemProcessor);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an {@link ItemKeyGenerator} or null if none is found.
|
||||
*/
|
||||
private ItemKeyGenerator getKeyGenerator() {
|
||||
|
||||
if (itemKeyGenerator != null) {
|
||||
return itemKeyGenerator;
|
||||
}
|
||||
if (getItemReader() instanceof ItemKeyGenerator) {
|
||||
return (ItemKeyGenerator) getItemReader();
|
||||
}
|
||||
if (getItemWriter() instanceof ItemKeyGenerator) {
|
||||
return (ItemKeyGenerator) getItemWriter();
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
@@ -129,10 +124,11 @@ public class StatefulRetryStepFactoryBean extends DefaultStepFactoryBean {
|
||||
/**
|
||||
* @param itemReader
|
||||
* @param itemWriter
|
||||
* @param retryCallback
|
||||
* @param retryTemplate
|
||||
* @param retryCallback
|
||||
* @param retryTemplate
|
||||
*/
|
||||
public StatefulRetryItemHandler(ItemReader itemReader, ItemWriter itemWriter, RetryOperations retryTemplate, ItemReaderRetryCallback retryCallback) {
|
||||
public StatefulRetryItemHandler(ItemReader itemReader, ItemWriter itemWriter, RetryOperations retryTemplate,
|
||||
ItemReaderRetryCallback retryCallback) {
|
||||
super(itemReader, itemWriter);
|
||||
this.retryOperations = retryTemplate;
|
||||
this.retryCallback = retryCallback;
|
||||
|
||||
@@ -79,8 +79,6 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
|
||||
ExecutionContext executionContext;
|
||||
|
||||
private JobExecution jobExecution;
|
||||
|
||||
public void setUp() throws Exception {
|
||||
|
||||
jobExecutionDao = (JobExecutionDao) jobExecutionDaoControl.getMock();
|
||||
|
||||
@@ -393,7 +393,7 @@ public class ItemOrientedStepTests extends TestCase {
|
||||
|
||||
public void testAfterStep() throws Exception{
|
||||
|
||||
final ExitStatus customStatus = new ExitStatus(true, "custom code");
|
||||
final ExitStatus customStatus = new ExitStatus(false, "custom code");
|
||||
|
||||
itemOrientedStep.setStepListeners(new StepListener[] {new StepListenerSupport() {
|
||||
public ExitStatus afterStep() {
|
||||
|
||||
@@ -26,7 +26,6 @@ import junit.framework.TestCase;
|
||||
import org.springframework.batch.core.domain.BatchListener;
|
||||
import org.springframework.batch.core.domain.BatchStatus;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.listener.ItemListenerSupport;
|
||||
import org.springframework.batch.execution.job.SimpleJob;
|
||||
@@ -36,7 +35,6 @@ import org.springframework.batch.execution.repository.dao.MapJobInstanceDao;
|
||||
import org.springframework.batch.execution.repository.dao.MapStepExecutionDao;
|
||||
import org.springframework.batch.execution.step.AbstractStep;
|
||||
import org.springframework.batch.execution.step.ItemOrientedStep;
|
||||
import org.springframework.batch.execution.step.support.DefaultStepFactoryBean;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.reader.ListItemReader;
|
||||
@@ -84,7 +82,6 @@ public class DefaultStepFactoryBeanTests extends TestCase {
|
||||
|
||||
private DefaultStepFactoryBean getStep(String[] args) throws Exception {
|
||||
DefaultStepFactoryBean factory = new DefaultStepFactoryBean();
|
||||
factory.setSingleton(false);
|
||||
|
||||
List items = TransactionAwareProxyFactory.createTransactionalList();
|
||||
items.addAll(Arrays.asList(args));
|
||||
@@ -95,13 +92,6 @@ public class DefaultStepFactoryBeanTests extends TestCase {
|
||||
factory.setJobRepository(repository);
|
||||
factory.setTransactionManager(new ResourcelessTransactionManager());
|
||||
factory.setBeanName("stepName");
|
||||
// step.setItemRecoverer(new ItemRecoverer() {
|
||||
// public boolean recover(Object item, Throwable cause) {
|
||||
// recovered.add(item);
|
||||
// assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
// return true;
|
||||
// }
|
||||
// });
|
||||
return factory;
|
||||
}
|
||||
|
||||
@@ -115,12 +105,10 @@ public class DefaultStepFactoryBeanTests extends TestCase {
|
||||
step.setName("step2");
|
||||
job.addStep(step);
|
||||
|
||||
JobInstance jobInstance = repository.createJobExecution(job, new JobParameters()).getJobInstance();
|
||||
JobExecution jobExecution = repository.createJobExecution(job, new JobParameters());
|
||||
|
||||
JobExecution jobExecutionContext = new JobExecution(jobInstance);
|
||||
|
||||
job.execute(jobExecutionContext);
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecutionContext.getStatus());
|
||||
job.execute(jobExecution);
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
assertEquals(3, processed.size());
|
||||
assertTrue(processed.contains("foo"));
|
||||
}
|
||||
@@ -154,6 +142,7 @@ public class DefaultStepFactoryBeanTests extends TestCase {
|
||||
public void onReadError(Exception ex) {
|
||||
recovered.add(ex);
|
||||
}
|
||||
|
||||
public void onWriteError(Exception ex, Object item) {
|
||||
recovered.add(ex);
|
||||
}
|
||||
@@ -173,8 +162,6 @@ public class DefaultStepFactoryBeanTests extends TestCase {
|
||||
assertEquals(null, provider.read());
|
||||
assertEquals(3, recovered.size());
|
||||
}
|
||||
|
||||
// TODO: test recovery and stateful retry
|
||||
|
||||
public void testExceptionTerminates() throws Exception {
|
||||
DefaultStepFactoryBean factory = getStep(new String[] { "foo", "bar", "spam" });
|
||||
|
||||
@@ -44,7 +44,14 @@ public class RepeatOperationsStepFactoryBeanTests extends TestCase {
|
||||
private List list;
|
||||
|
||||
private JobExecution jobExecution = new JobExecution(new JobInstance(new Long(0L), new JobParameters(),
|
||||
new JobSupport("job")));;
|
||||
new JobSupport("job")));
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
factory.setItemReader(new ListItemReader(new ArrayList()));
|
||||
factory.setItemWriter(new EmptyItemWriter());
|
||||
factory.setJobRepository(new JobRepositorySupport());
|
||||
factory.setTransactionManager(new ResourcelessTransactionManager());
|
||||
}
|
||||
|
||||
public void testType() throws Exception {
|
||||
assertEquals(Step.class, factory.getObjectType());
|
||||
@@ -70,8 +77,6 @@ public class RepeatOperationsStepFactoryBeanTests extends TestCase {
|
||||
}
|
||||
});
|
||||
|
||||
factory.setSingleton(false);
|
||||
|
||||
Step step = (Step) factory.getObject();
|
||||
step.execute(new StepExecution(step, jobExecution));
|
||||
|
||||
|
||||
@@ -15,24 +15,115 @@
|
||||
*/
|
||||
package org.springframework.batch.execution.step.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.domain.JobParametersBuilder;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
import org.springframework.batch.execution.repository.SimpleJobRepository;
|
||||
import org.springframework.batch.execution.repository.dao.MapJobExecutionDao;
|
||||
import org.springframework.batch.execution.repository.dao.MapJobInstanceDao;
|
||||
import org.springframework.batch.execution.repository.dao.MapStepExecutionDao;
|
||||
import org.springframework.batch.execution.step.ItemOrientedStep;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemRecoverer;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.reader.ListItemReader;
|
||||
import org.springframework.batch.item.writer.AbstractItemWriter;
|
||||
import org.springframework.batch.retry.policy.AlwaysRetryPolicy;
|
||||
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
|
||||
import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class StatefulRetryStepFactoryBeanTests extends TestCase {
|
||||
|
||||
private AbstractStepFactoryBean factory = new StatefulRetryStepFactoryBean();
|
||||
|
||||
private StatefulRetryStepFactoryBean factory = new StatefulRetryStepFactoryBean();
|
||||
|
||||
private List recovered = new ArrayList();
|
||||
|
||||
private List processed = new ArrayList();
|
||||
|
||||
private SimpleJobRepository repository = new SimpleJobRepository(new MapJobInstanceDao(), new MapJobExecutionDao(),
|
||||
new MapStepExecutionDao());
|
||||
|
||||
JobExecution jobExecution;
|
||||
|
||||
private ItemWriter processor = new AbstractItemWriter() {
|
||||
public void write(Object data) throws Exception {
|
||||
processed.add((String) data);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
|
||||
MapJobInstanceDao.clear();
|
||||
MapJobExecutionDao.clear();
|
||||
MapStepExecutionDao.clear();
|
||||
|
||||
factory.setBeanName("step");
|
||||
|
||||
factory.setItemReader(new ListItemReader(new ArrayList()));
|
||||
factory.setItemWriter(processor);
|
||||
factory.setJobRepository(repository);
|
||||
factory.setTransactionManager(new ResourcelessTransactionManager());
|
||||
|
||||
JobSupport job = new JobSupport("jobName");
|
||||
job.setRestartable(true);
|
||||
JobParameters jobParameters = new JobParametersBuilder().addString("statefulTest", "make_this_unique").toJobParameters();
|
||||
jobExecution = repository.createJobExecution(job, jobParameters);
|
||||
jobExecution.setEndTime(new Date());
|
||||
|
||||
}
|
||||
|
||||
public void testType() throws Exception {
|
||||
assertEquals(Step.class, factory.getObjectType());
|
||||
}
|
||||
|
||||
|
||||
public void testDefaultValue() throws Exception {
|
||||
assertTrue(factory.getObject() instanceof Step);
|
||||
}
|
||||
|
||||
public void testRecovery() throws Exception {
|
||||
factory.setItemRecoverer(new ItemRecoverer() {
|
||||
public boolean recover(Object item, Throwable cause) {
|
||||
recovered.add(item);
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
List items = TransactionAwareProxyFactory.createTransactionalList();
|
||||
items.addAll(Arrays.asList(new String[] { "a", "b", "c" }));
|
||||
ItemReader provider = new ListItemReader(items) {
|
||||
int count = 0;
|
||||
public Object read() {
|
||||
count++;
|
||||
if (count == 2) {
|
||||
throw new RuntimeException("Temporary error - retry for success.");
|
||||
}
|
||||
return super.read();
|
||||
}
|
||||
};
|
||||
factory.setItemReader(provider);
|
||||
factory.setRetryPolicy(new AlwaysRetryPolicy());
|
||||
ItemOrientedStep step = (ItemOrientedStep) factory.getObject();
|
||||
|
||||
step.execute(new StepExecution(step, jobExecution));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,12 +26,9 @@ import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
import org.springframework.batch.execution.repository.SimpleJobRepository;
|
||||
import org.springframework.batch.execution.repository.dao.JobExecutionDao;
|
||||
import org.springframework.batch.execution.repository.dao.JobInstanceDao;
|
||||
import org.springframework.batch.execution.repository.dao.MapJobExecutionDao;
|
||||
import org.springframework.batch.execution.repository.dao.MapJobInstanceDao;
|
||||
import org.springframework.batch.execution.repository.dao.MapStepExecutionDao;
|
||||
import org.springframework.batch.execution.repository.dao.StepExecutionDao;
|
||||
import org.springframework.batch.execution.step.ItemOrientedStep;
|
||||
import org.springframework.batch.item.reader.AbstractItemReader;
|
||||
import org.springframework.batch.item.reader.ItemReaderAdapter;
|
||||
@@ -42,14 +39,6 @@ import org.springframework.batch.support.transaction.ResourcelessTransactionMana
|
||||
|
||||
public class StepExecutorInterruptionTests extends TestCase {
|
||||
|
||||
private JobRepository jobRepository;
|
||||
|
||||
private JobInstanceDao jobInstanceDao = new MapJobInstanceDao();
|
||||
|
||||
private JobExecutionDao jobExecutionDao = new MapJobExecutionDao();
|
||||
|
||||
private StepExecutionDao stepExecutionDao = new MapStepExecutionDao();
|
||||
|
||||
private ItemOrientedStep step;
|
||||
|
||||
private JobExecution jobExecution;
|
||||
@@ -61,7 +50,7 @@ public class StepExecutorInterruptionTests extends TestCase {
|
||||
MapJobExecutionDao.clear();
|
||||
MapStepExecutionDao.clear();
|
||||
|
||||
jobRepository = new SimpleJobRepository(jobInstanceDao, jobExecutionDao, stepExecutionDao);
|
||||
JobRepository jobRepository = new SimpleJobRepository(new MapJobInstanceDao(), new MapJobExecutionDao(), new MapStepExecutionDao());
|
||||
|
||||
JobSupport jobConfiguration = new JobSupport();
|
||||
step = new ItemOrientedStep("interruptedStep");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry including="**/*.java" kind="src" path="src/main/java"/>
|
||||
<classpathentry including="**/*.java" kind="src" output="bin/test-classes" path="src/test/java"/>
|
||||
<classpathentry excluding="**/*.java" including="**" kind="src" output="bin/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="src" output="bin/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="bin/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.devzuz.q.maven.jdt.core.mavenClasspathContainer"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#Fri Feb 29 13:52:09 GMT 2008
|
||||
#Tue Mar 04 12:26:32 GMT 2008
|
||||
eclipse.preferences.version=1
|
||||
instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4
|
||||
org.eclipse.jdt.core.compiler.compliance=1.4
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.4
|
||||
|
||||
@@ -49,7 +49,7 @@ public class ExitStatus implements Serializable {
|
||||
* Convenient constant value representing finished processing.
|
||||
*/
|
||||
public static final ExitStatus FINISHED = new ExitStatus(false, "COMPLETED");
|
||||
|
||||
|
||||
/**
|
||||
* Convenient constant value representing interrupted processing.
|
||||
*/
|
||||
@@ -131,8 +131,11 @@ public class ExitStatus implements Serializable {
|
||||
|
||||
/**
|
||||
* Create a new {@link ExitStatus} with a logical combination of the
|
||||
* continuable flag, and a concatenation of the codes. If the input is null
|
||||
* we just return this.
|
||||
* continuable flag, and a concatenation of the descriptions. The exit code
|
||||
* is only replaced if the result is continuable or the input is not
|
||||
* continuable.<br/>
|
||||
*
|
||||
* If the input is null just return this.
|
||||
*
|
||||
* @param status an {@link ExitStatus} to combine with this one.
|
||||
* @return a new {@link ExitStatus} with {@link #isContinuable()} the
|
||||
@@ -142,7 +145,11 @@ public class ExitStatus implements Serializable {
|
||||
if (status == null) {
|
||||
return this;
|
||||
}
|
||||
return and(status.continuable).replaceExitCode(status.exitCode).addExitDescription(status.exitDescription);
|
||||
ExitStatus result = and(status.continuable).addExitDescription(status.exitDescription);
|
||||
if (result.continuable || !status.continuable) {
|
||||
result = result.replaceExitCode(status.exitCode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -21,12 +21,13 @@ import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ExitStatusTests extends TestCase {
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}.
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}.
|
||||
*/
|
||||
public void testExitStatusBooleanInt() {
|
||||
ExitStatus status = new ExitStatus(true, "10");
|
||||
@@ -35,7 +36,8 @@ public class ExitStatusTests extends TestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}.
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}.
|
||||
*/
|
||||
public void testExitStatusConstantsContinuable() {
|
||||
ExitStatus status = ExitStatus.CONTINUABLE;
|
||||
@@ -44,14 +46,15 @@ public class ExitStatusTests extends TestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}.
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}.
|
||||
*/
|
||||
public void testExitStatusConstantsFinished() {
|
||||
ExitStatus status = ExitStatus.FINISHED;
|
||||
assertFalse(status.isContinuable());
|
||||
assertEquals("COMPLETED", status.getExitCode());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test equality of exit statuses.
|
||||
*
|
||||
@@ -60,13 +63,13 @@ public class ExitStatusTests extends TestCase {
|
||||
public void testEqualsWithSameProperties() throws Exception {
|
||||
assertEquals(ExitStatus.CONTINUABLE, new ExitStatus(true, "CONTINUABLE"));
|
||||
}
|
||||
|
||||
public void testEqualsSelf(){
|
||||
|
||||
public void testEqualsSelf() {
|
||||
ExitStatus status = new ExitStatus(true, "test");
|
||||
assertEquals(status, status);
|
||||
}
|
||||
|
||||
public void testEquals(){
|
||||
|
||||
public void testEquals() {
|
||||
assertEquals(new ExitStatus(true, "test"), new ExitStatus(true, "test"));
|
||||
}
|
||||
|
||||
@@ -89,57 +92,93 @@ public class ExitStatusTests extends TestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.repeat.ExitStatus#and(boolean)}.
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.repeat.ExitStatus#and(boolean)}.
|
||||
*/
|
||||
public void testAndBoolean() {
|
||||
assertTrue(ExitStatus.CONTINUABLE.and(true).isContinuable());
|
||||
assertFalse(ExitStatus.CONTINUABLE.and(false).isContinuable());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}.
|
||||
*/
|
||||
public void testAndExitStatus() {
|
||||
assertTrue(ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE.isContinuable()).isContinuable());
|
||||
assertFalse(ExitStatus.CONTINUABLE.and(ExitStatus.FINISHED.isContinuable()).isContinuable());
|
||||
assertTrue(ExitStatus.FINISHED.and(ExitStatus.CONTINUABLE.isContinuable()).getExitCode()
|
||||
== ExitStatus.FINISHED.getExitCode());
|
||||
ExitStatus status = new ExitStatus(false, "CUSTOM_CODE", "CUSTOM_DESCRIPTION");
|
||||
assertTrue(status.and(true).getExitCode() == "CUSTOM_CODE");
|
||||
assertTrue(status.and(true).getExitDescription() == "CUSTOM_DESCRIPTION");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}.
|
||||
*/
|
||||
public void testAndExitStatusStillContinuable() {
|
||||
assertTrue(ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE).isContinuable());
|
||||
assertFalse(ExitStatus.CONTINUABLE.and(ExitStatus.FINISHED).isContinuable());
|
||||
assertTrue(ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE).getExitCode() == ExitStatus.CONTINUABLE
|
||||
.getExitCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}.
|
||||
*/
|
||||
public void testAndExitStatusWhenFinishedAddedToContinuable() {
|
||||
assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.CONTINUABLE.and(ExitStatus.FINISHED).getExitCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}.
|
||||
*/
|
||||
public void testAndExitStatusWhenContinuableAddedToFinished() {
|
||||
assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.FINISHED.and(ExitStatus.CONTINUABLE).getExitCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}.
|
||||
*/
|
||||
public void testAndExitStatusWhenCustomContinuableAddedToContinuable() {
|
||||
assertEquals("CUSTOM", ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE.replaceExitCode("CUSTOM"))
|
||||
.getExitCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}.
|
||||
*/
|
||||
public void testAndExitStatusWhenCustomContinuableAddedToFinished() {
|
||||
assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.FINISHED.and(ExitStatus.CONTINUABLE.replaceExitCode("CUSTOM"))
|
||||
.getExitCode());
|
||||
}
|
||||
|
||||
public void testAddExitCode() throws Exception {
|
||||
ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode("FOO");
|
||||
assertTrue(ExitStatus.CONTINUABLE!=status);
|
||||
assertTrue(ExitStatus.CONTINUABLE != status);
|
||||
assertTrue(status.isContinuable());
|
||||
assertEquals("FOO", status.getExitCode());
|
||||
}
|
||||
|
||||
public void testAddExitCodeToExistingStatus() throws Exception {
|
||||
ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode("FOO").replaceExitCode("BAR");
|
||||
assertTrue(ExitStatus.CONTINUABLE!=status);
|
||||
assertTrue(ExitStatus.CONTINUABLE != status);
|
||||
assertTrue(status.isContinuable());
|
||||
assertEquals("BAR", status.getExitCode());
|
||||
}
|
||||
|
||||
public void testAddExitCodeToSameStatus() throws Exception {
|
||||
ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode(ExitStatus.CONTINUABLE.getExitCode());
|
||||
assertTrue(ExitStatus.CONTINUABLE!=status);
|
||||
assertTrue(ExitStatus.CONTINUABLE != status);
|
||||
assertTrue(status.isContinuable());
|
||||
assertEquals(ExitStatus.CONTINUABLE.getExitCode(), status.getExitCode());
|
||||
}
|
||||
|
||||
public void testAddExitDescription() throws Exception {
|
||||
ExitStatus status = ExitStatus.CONTINUABLE.addExitDescription("Foo");
|
||||
assertTrue(ExitStatus.CONTINUABLE!=status);
|
||||
assertTrue(ExitStatus.CONTINUABLE != status);
|
||||
assertTrue(status.isContinuable());
|
||||
assertEquals("Foo", status.getExitDescription());
|
||||
}
|
||||
|
||||
public void testAddExitDescriptionToSameStatus() throws Exception {
|
||||
ExitStatus status = ExitStatus.CONTINUABLE.addExitDescription("Foo").addExitDescription("Foo");
|
||||
assertTrue(ExitStatus.CONTINUABLE!=status);
|
||||
assertTrue(ExitStatus.CONTINUABLE != status);
|
||||
assertTrue(status.isContinuable());
|
||||
assertEquals("Foo", status.getExitDescription());
|
||||
}
|
||||
@@ -149,12 +188,12 @@ public class ExitStatusTests extends TestCase {
|
||||
assertEquals("FOO", status.getExitCode());
|
||||
assertEquals("Bar", status.getExitDescription());
|
||||
}
|
||||
|
||||
|
||||
public void testRunningIsRunning() throws Exception {
|
||||
assertTrue(ExitStatus.RUNNING.isRunning());
|
||||
assertTrue(new ExitStatus(true, "RUNNING").isRunning());
|
||||
}
|
||||
|
||||
|
||||
public void testUnkownIsRunning() throws Exception {
|
||||
assertTrue(ExitStatus.UNKNOWN.isRunning());
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry including="**/*.java" kind="src" path="src/main/java"/>
|
||||
<classpathentry including="**/*.java" kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry including="**/*.java" kind="src" output="bin/test-classes" path="src/test/java"/>
|
||||
<classpathentry excluding="**/*.java" including="**" kind="src" path="src/main/resources"/>
|
||||
<classpathentry excluding="**/*.java" including="**" kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry excluding="**/*.java" including="**" kind="src" output="bin/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.devzuz.q.maven.jdt.core.mavenClasspathContainer"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
|
||||
Reference in New Issue
Block a user