RESOLVED - issue BATCH-1520: Allow null ItemWriter as long as ItemProcessor is provided
This commit is contained in:
@@ -183,6 +183,9 @@ public abstract class AbstractListenerFactoryBean implements FactoryBean, Initia
|
||||
* interface, or contains the marker annotations
|
||||
*/
|
||||
public static boolean isListener(Object target, Class<?> listenerType, ListenerMetaData[] metaDataValues) {
|
||||
if (target == null) {
|
||||
return false;
|
||||
}
|
||||
if (listenerType.isInstance(target)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -113,6 +113,13 @@ public class SimpleChunkProcessor<I, O> implements ChunkProcessor<I>, Initializi
|
||||
* @throws Exception
|
||||
*/
|
||||
protected final O doProcess(I item) throws Exception {
|
||||
|
||||
if (itemProcessor==null) {
|
||||
@SuppressWarnings("unchecked")
|
||||
O result = (O) item;
|
||||
return result;
|
||||
}
|
||||
|
||||
try {
|
||||
listener.beforeProcess(item);
|
||||
O result = itemProcessor.process(item);
|
||||
@@ -123,6 +130,7 @@ public class SimpleChunkProcessor<I, O> implements ChunkProcessor<I>, Initializi
|
||||
listener.onProcessError(item, e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,6 +140,11 @@ public class SimpleChunkProcessor<I, O> implements ChunkProcessor<I>, Initializi
|
||||
* @throws Exception
|
||||
*/
|
||||
protected final void doWrite(List<O> items) throws Exception {
|
||||
|
||||
if (itemWriter==null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
listener.beforeWrite(items);
|
||||
writeItems(items);
|
||||
@@ -141,6 +154,7 @@ public class SimpleChunkProcessor<I, O> implements ChunkProcessor<I>, Initializi
|
||||
listener.onWriteError(e, items);
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,7 +167,9 @@ public class SimpleChunkProcessor<I, O> implements ChunkProcessor<I>, Initializi
|
||||
}
|
||||
|
||||
protected void writeItems(List<O> items) throws Exception {
|
||||
itemWriter.write(items);
|
||||
if (itemWriter!=null) {
|
||||
itemWriter.write(items);
|
||||
}
|
||||
}
|
||||
|
||||
public final void process(StepContribution contribution, Chunk<I> inputs) throws Exception {
|
||||
|
||||
@@ -77,6 +77,8 @@ public class SimpleStepFactoryBean<T, S> implements FactoryBean, BeanNameAware {
|
||||
|
||||
private ItemReader<? extends T> itemReader;
|
||||
|
||||
private ItemProcessor<? super T, ? extends S> itemProcessor;
|
||||
|
||||
private ItemWriter<? super S> itemWriter;
|
||||
|
||||
private PlatformTransactionManager transactionManager;
|
||||
@@ -97,13 +99,6 @@ public class SimpleStepFactoryBean<T, S> implements FactoryBean, BeanNameAware {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private ItemProcessor<? super T, ? extends S> itemProcessor = new ItemProcessor<T, S>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public S process(T item) throws Exception {
|
||||
return (S) item;
|
||||
}
|
||||
};
|
||||
|
||||
private int commitInterval = 0;
|
||||
|
||||
private TaskExecutor taskExecutor;
|
||||
@@ -469,9 +464,9 @@ public class SimpleStepFactoryBean<T, S> implements FactoryBean, BeanNameAware {
|
||||
*/
|
||||
protected void applyConfiguration(TaskletStep step) {
|
||||
|
||||
Assert.notNull(getItemReader(), "ItemReader must be provided");
|
||||
Assert.notNull(getItemWriter(), "ItemWriter must be provided");
|
||||
Assert.notNull(transactionManager, "TransactionManager must be provided");
|
||||
Assert.state(getItemReader()!=null, "ItemReader must be provided");
|
||||
Assert.state(getItemWriter()!=null || getItemProcessor()!=null, "ItemWriter or ItemProcessor must be provided");
|
||||
Assert.state(transactionManager!=null, "TransactionManager must be provided");
|
||||
|
||||
step.setTransactionManager(transactionManager);
|
||||
step.setTransactionAttribute(getTransactionAttribute());
|
||||
|
||||
@@ -296,6 +296,30 @@ public class FaultTolerantStepFactoryBeanTests {
|
||||
.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullWriter() throws Exception {
|
||||
|
||||
factory.setItemWriter(null);
|
||||
Step step = (Step) factory.getObject();
|
||||
|
||||
step.execute(stepExecution);
|
||||
|
||||
assertEquals(0, stepExecution.getSkipCount());
|
||||
assertEquals(0, stepExecution.getReadSkipCount());
|
||||
assertEquals(5, stepExecution.getReadCount());
|
||||
// Write count is incremented even if nothing happens
|
||||
assertEquals(5, stepExecution.getWriteCount());
|
||||
assertEquals(0, stepExecution.getFilterCount());
|
||||
assertEquals(0, stepExecution.getRollbackCount());
|
||||
|
||||
// writer skips "4"
|
||||
assertTrue(reader.getRead().contains("4"));
|
||||
|
||||
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
|
||||
assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step
|
||||
.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check items causing errors are skipped as expected.
|
||||
*/
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.springframework.batch.core.repository.dao.MapJobInstanceDao;
|
||||
import org.springframework.batch.core.repository.dao.MapStepExecutionDao;
|
||||
import org.springframework.batch.core.repository.support.SimpleJobRepository;
|
||||
import org.springframework.batch.core.step.AbstractStep;
|
||||
import org.springframework.batch.item.ItemProcessor;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.support.ListItemReader;
|
||||
@@ -83,7 +84,7 @@ public class SimpleStepFactoryBeanTests {
|
||||
job.setBeanName("simpleJob");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testMandatoryProperties() throws Exception {
|
||||
new SimpleStepFactoryBean<String, String>().getObject();
|
||||
}
|
||||
@@ -325,11 +326,15 @@ public class SimpleStepFactoryBeanTests {
|
||||
|
||||
final List<String> listenerCalls = new ArrayList<String>();
|
||||
|
||||
class TestItemListenerWriter implements ItemWriter<String>, ItemReadListener<String>,
|
||||
ItemWriteListener<String>, ItemProcessListener<String, String>, ChunkListener {
|
||||
class TestItemListenerWriter implements ItemWriter<String>, ItemProcessor<String, String>,
|
||||
ItemReadListener<String>, ItemWriteListener<String>, ItemProcessListener<String, String>, ChunkListener {
|
||||
public void write(List<? extends String> items) throws Exception {
|
||||
}
|
||||
|
||||
public String process(String item) throws Exception {
|
||||
return item;
|
||||
}
|
||||
|
||||
public void afterRead(String item) {
|
||||
listenerCalls.add("read");
|
||||
}
|
||||
@@ -369,7 +374,9 @@ public class SimpleStepFactoryBeanTests {
|
||||
|
||||
}
|
||||
|
||||
factory.setItemWriter(new TestItemListenerWriter());
|
||||
TestItemListenerWriter itemWriter = new TestItemListenerWriter();
|
||||
factory.setItemWriter(itemWriter);
|
||||
factory.setItemProcessor(itemWriter);
|
||||
|
||||
Step step = (Step) factory.getObject();
|
||||
|
||||
@@ -409,7 +416,7 @@ public class SimpleStepFactoryBeanTests {
|
||||
}
|
||||
|
||||
TestItemListenerWriter itemWriter = new TestItemListenerWriter();
|
||||
factory.setListeners(new StepListener[] {itemWriter});
|
||||
factory.setListeners(new StepListener[] { itemWriter });
|
||||
factory.setItemWriter(itemWriter);
|
||||
|
||||
Step step = (Step) factory.getObject();
|
||||
@@ -425,6 +432,31 @@ public class SimpleStepFactoryBeanTests {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullWriter() throws Exception {
|
||||
|
||||
SimpleStepFactoryBean<String, String> factory = getStepFactory(new String[] { "foo", "bar", "spam" });
|
||||
factory.setItemWriter(null);
|
||||
factory.setItemProcessor(new ItemProcessor<String, String>() {
|
||||
public String process(String item) throws Exception {
|
||||
written.add(item);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
Step step = (Step) factory.getObject();
|
||||
|
||||
job.setSteps(Collections.singletonList(step));
|
||||
|
||||
JobExecution jobExecution = repository.createJobExecution(job.getName(), new JobParameters());
|
||||
|
||||
job.execute(jobExecution);
|
||||
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
assertEquals("[foo, bar, spam]", written.toString());
|
||||
|
||||
}
|
||||
|
||||
private SimpleStepFactoryBean<String, String> getStepFactory(String... args) throws Exception {
|
||||
SimpleStepFactoryBean<String, String> factory = new SimpleStepFactoryBean<String, String>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user