From 9d1ebb42c7fa5ad9d85f24d776bd3e53ec22f237 Mon Sep 17 00:00:00 2001 From: dsyer Date: Thu, 31 Jan 2008 00:44:50 +0000 Subject: [PATCH] IN PROGRESS - issue BATCH-7: Remove transaction synchronization and state management from input/output sources (formerly buffering) http://jira.springframework.org/browse/BATCH-7 Remove ResourceLifecycle and make existing implementations into ItemStream --- .../RestartableItemOrientedTasklet.java | 50 +++--- .../execution/launch/EmptyItemWriter.java | 4 +- .../step/simple/SimpleStepExecutorTests.java | 15 +- .../tasklet/ItemOrientedTaskletTests.java | 6 +- .../RestartableItemOrientedTaskletTests.java | 34 +++- .../io/file/SimpleFlatFileItemReader.java | 6 +- .../io/support/HibernateAwareItemWriter.java | 3 +- .../batch/io/xml/StaxEventItemReader.java | 2 +- .../batch/item/ItemReader.java | 10 +- .../batch/item/ItemStream.java | 22 +-- .../batch/item/ItemWriter.java | 8 +- .../batch/item/reader/AbstractItemReader.java | 10 +- .../item/reader/DelegatingItemReader.java | 20 ++- .../batch/item/reader/ItemReaderAdapter.java | 31 +--- .../item/stream/CompositeItemStream.java | 158 ++++++++++++++++++ .../batch/item/writer/AbstractItemWriter.java | 31 ++++ .../item/writer/CompositeItemWriter.java | 113 +------------ .../item/writer/DelegatingItemWriter.java | 4 +- .../batch/item/writer/ItemWriterAdapter.java | 38 +---- ...ropertyExtractingDelegatingItemWriter.java | 34 +--- .../batch/io/driving/FooInputSource.java | 5 +- .../HibernateAwareItemWriterTests.java | 35 ++-- .../item/writer/CompositeItemWriterTests.java | 50 +++--- .../support/AsynchronousRepeatTests.java | 2 +- .../dao/FlatFileCustomerCreditWriter.java | 9 +- .../batch/sample/dao/JdbcGameDao.java | 33 ---- .../sample/dao/JdbcPlayerSummaryDao.java | 33 ---- .../sample/item/reader/StagingItemReader.java | 19 --- .../writer/CustomerCreditIncreaseWriter.java | 6 +- .../writer/CustomerCreditUpdateWriter.java | 3 +- .../item/writer/CustomerUpdateWriter.java | 6 +- .../sample/item/writer/DummyItemWriter.java | 7 +- .../sample/item/writer/PersonWriter.java | 7 +- .../sample/item/writer/PlayerItemWriter.java | 6 +- .../sample/item/writer/StagingItemWriter.java | 33 ---- .../batch/sample/item/writer/TradeWriter.java | 4 +- .../jobs/compositeProcessorSampleJob.xml | 2 +- .../batch/sample/RestartFunctionalTests.java | 3 +- .../FlatFileCustomerCreditWriterTests.java | 3 +- 39 files changed, 416 insertions(+), 449 deletions(-) create mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/item/stream/CompositeItemStream.java create mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/AbstractItemWriter.java diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/tasklet/RestartableItemOrientedTasklet.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/tasklet/RestartableItemOrientedTasklet.java index 0532bd74d..345c6c131 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/tasklet/RestartableItemOrientedTasklet.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/tasklet/RestartableItemOrientedTasklet.java @@ -47,15 +47,15 @@ public class RestartableItemOrientedTasklet extends ItemOrientedTasklet implemen StreamContext itemProviderRestartData = null; StreamContext itemProcessorRestartData = null; - if (itemProvider != null) { - itemProviderRestartData = itemProvider.getRestartData(); - } - if (itemWriter != null) { - itemProcessorRestartData = itemWriter.getRestartData(); + if (itemProvider instanceof ItemStream) { + itemProviderRestartData = ((ItemStream) itemProvider).getRestartData(); } - RestartableItemOrientedTaskletRestartData restartData = new RestartableItemOrientedTaskletRestartData( - itemProviderRestartData, itemProcessorRestartData); + if (itemWriter instanceof ItemStream) { + itemProcessorRestartData = ((ItemStream) itemWriter).getRestartData(); + } + + RestartableItemOrientedTaskletRestartData restartData = new RestartableItemOrientedTaskletRestartData(itemProviderRestartData, itemProcessorRestartData); return restartData; } @@ -76,11 +76,11 @@ public class RestartableItemOrientedTasklet extends ItemOrientedTasklet implemen moduleRestartData = new RestartableItemOrientedTaskletRestartData(data.getProperties()); } - if (itemProvider != null) { - itemProvider.restoreFrom(moduleRestartData.readerData); + if (itemProvider instanceof ItemStream) { + ((ItemStream) itemProvider).restoreFrom(moduleRestartData.readerData); } - if (itemWriter != null) { - itemWriter.restoreFrom(moduleRestartData.writerData); + if (itemWriter instanceof ItemStream) { + ((ItemStream) itemWriter).restoreFrom(moduleRestartData.writerData); } } @@ -100,8 +100,10 @@ public class RestartableItemOrientedTasklet extends ItemOrientedTasklet implemen } public RestartableItemOrientedTaskletRestartData(Properties data) { - readerData = new GenericStreamContext(PropertiesConverter.stringToProperties(data.getProperty(READER_KEY))); - writerData = new GenericStreamContext(PropertiesConverter.stringToProperties(data.getProperty(WRITER_KEY))); + readerData = new GenericStreamContext(PropertiesConverter + .stringToProperties(data.getProperty(READER_KEY))); + writerData = new GenericStreamContext(PropertiesConverter.stringToProperties(data + .getProperty(WRITER_KEY))); } public Properties getProperties() { @@ -115,20 +117,18 @@ public class RestartableItemOrientedTasklet extends ItemOrientedTasklet implemen return props; } } - - /* - * (non-Javadoc) - * @see org.springframework.batch.item.ItemStream#close() - */ - public void close() throws Exception { - // no-op - } - - /* - * (non-Javadoc) + + /* (non-Javadoc) * @see org.springframework.batch.item.ItemStream#open() */ public void open() throws Exception { - // no-op + throw new UnsupportedOperationException("Not implemented."); + } + + /* (non-Javadoc) + * @see org.springframework.batch.item.ItemStream#close() + */ + public void close() throws Exception { + throw new UnsupportedOperationException("Not implemented."); } } diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/EmptyItemWriter.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/EmptyItemWriter.java index f77618541..5c6b9c996 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/EmptyItemWriter.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/EmptyItemWriter.java @@ -21,11 +21,11 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.batch.item.writer.AbstractItemWriter; +import org.springframework.batch.item.ItemWriter; import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; import org.springframework.beans.factory.InitializingBean; -public class EmptyItemWriter extends AbstractItemWriter implements InitializingBean { +public class EmptyItemWriter implements ItemWriter, InitializingBean { private boolean failed = false; diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/simple/SimpleStepExecutorTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/simple/SimpleStepExecutorTests.java index f33416d06..66e7b4ee2 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/simple/SimpleStepExecutorTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/simple/SimpleStepExecutorTests.java @@ -25,10 +25,10 @@ import java.util.Properties; import junit.framework.TestCase; +import org.springframework.batch.core.domain.JobSupport; 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.domain.JobSupport; import org.springframework.batch.core.domain.StepContribution; import org.springframework.batch.core.domain.StepExecution; import org.springframework.batch.core.domain.StepInstance; @@ -40,10 +40,10 @@ import org.springframework.batch.execution.scope.StepScope; import org.springframework.batch.execution.scope.StepSynchronizationManager; import org.springframework.batch.execution.tasklet.ItemOrientedTasklet; import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.StreamContext; import org.springframework.batch.item.reader.ListItemReader; -import org.springframework.batch.item.stream.ItemStreamAdapter; import org.springframework.batch.item.writer.AbstractItemWriter; import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.RepeatContext; @@ -455,7 +455,7 @@ public class SimpleStepExecutorTests extends TestCase { assertEquals(0, map.size()); } - private class MockRestartableTasklet extends ItemStreamAdapter implements Tasklet { + private class MockRestartableTasklet implements Tasklet, ItemStream { private boolean getRestartDataCalled = false; @@ -481,6 +481,15 @@ public class SimpleStepExecutorTests extends TestCase { public boolean isRestoreFromCalled() { return restoreFromCalled; } + + public void open() throws Exception { + throw new UnsupportedOperationException("Not implemented."); + } + + public void close() throws Exception { + throw new UnsupportedOperationException("Not implemented."); + } + } /* diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/tasklet/ItemOrientedTaskletTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/tasklet/ItemOrientedTaskletTests.java index 19cb3a4fe..6304ccb34 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/tasklet/ItemOrientedTaskletTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/tasklet/ItemOrientedTaskletTests.java @@ -273,7 +273,7 @@ public class ItemOrientedTaskletTests extends TestCase { } } - private class SkippableItemReader extends AbstractItemReader implements KeyedItemReader, + private class SkippableItemReader implements KeyedItemReader, Skippable, StatisticsProvider { public Object read() throws Exception { return itemProvider.read(); @@ -287,9 +287,11 @@ public class ItemOrientedTaskletTests extends TestCase { public Properties getStatistics() { return PropertiesConverter.stringToProperties("foo=bar"); } + public void close() throws Exception { + } } - private class SkippableItemWriter extends AbstractItemWriter implements ItemWriter, Skippable, + private class SkippableItemWriter implements ItemWriter, Skippable, StatisticsProvider { String props = "foo=bar"; diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/tasklet/RestartableItemOrientedTaskletTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/tasklet/RestartableItemOrientedTaskletTests.java index 0eb99e6c9..0dcd6c904 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/tasklet/RestartableItemOrientedTaskletTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/tasklet/RestartableItemOrientedTaskletTests.java @@ -21,11 +21,10 @@ import java.util.Properties; import junit.framework.TestCase; import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.StreamContext; -import org.springframework.batch.item.reader.AbstractItemReader; import org.springframework.batch.item.stream.GenericStreamContext; -import org.springframework.batch.item.writer.AbstractItemWriter; import org.springframework.batch.support.PropertiesConverter; /** @@ -33,16 +32,16 @@ import org.springframework.batch.support.PropertiesConverter; */ public class RestartableItemOrientedTaskletTests extends TestCase { - private static class MockProvider extends AbstractItemReader { + private static class MockProvider implements ItemReader, ItemStream { StreamContext data = new StreamContext() { public Properties getProperties() { return PropertiesConverter.stringToProperties("a=b"); } - + }; - + public Object read() { return null; } @@ -56,9 +55,21 @@ public class RestartableItemOrientedTaskletTests extends TestCase { assertEquals(this.data.getProperties(), data.getProperties()); } + public boolean recover(Object data, Throwable cause) { + return false; + } + + public void open() throws Exception { + throw new UnsupportedOperationException("Not implemented."); + } + + public void close() throws Exception { + throw new UnsupportedOperationException("Not implemented."); + } + } - private static class MockWriter extends AbstractItemWriter { + private static class MockWriter implements ItemWriter, ItemStream { StreamContext data = new StreamContext() { public Properties getProperties() { @@ -78,7 +89,12 @@ public class RestartableItemOrientedTaskletTests extends TestCase { assertEquals(this.data.getProperties(), data.getProperties()); } + public void open() throws Exception { + throw new UnsupportedOperationException("Not implemented."); + } + public void close() throws Exception { + throw new UnsupportedOperationException("Not implemented."); } } @@ -125,7 +141,7 @@ public class RestartableItemOrientedTaskletTests extends TestCase { // restore from restart data (see asserts in mock classes) module.restoreFrom(data); } - + public void testRestartFromNotRestartable() { // create and set up module @@ -138,7 +154,7 @@ public class RestartableItemOrientedTaskletTests extends TestCase { assertNotNull(data); // restore from restart data (see asserts in mock classes) module.restoreFrom(data); - // System.err.println(data.getProperties()); + //System.err.println(data.getProperties()); } - + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/SimpleFlatFileItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/SimpleFlatFileItemReader.java index 9205ab7f9..e2a185dec 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/SimpleFlatFileItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/SimpleFlatFileItemReader.java @@ -22,8 +22,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.batch.io.exception.FlatFileParsingException; import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.mapping.FieldSetMapper; import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.mapping.FieldSetMapper; import org.springframework.batch.io.file.separator.LineReader; import org.springframework.batch.io.file.separator.RecordSeparatorPolicy; import org.springframework.batch.io.file.separator.ResourceLineReader; @@ -170,8 +170,10 @@ public class SimpleFlatFileItemReader extends AbstractItemReader implements Item } /** - * Close and null out the delegate line reader. + * Close and null out the reader. * @throws Exception + * + * @see ResourceLifecycle */ public void close() throws Exception { try { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/HibernateAwareItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/HibernateAwareItemWriter.java index 3a78cc8c8..169b6bec4 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/HibernateAwareItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/HibernateAwareItemWriter.java @@ -20,7 +20,6 @@ import java.util.Set; import org.hibernate.SessionFactory; import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.stream.ItemStreamAdapter; import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.RepeatContext; import org.springframework.batch.repeat.RepeatInterceptor; @@ -45,7 +44,7 @@ import org.springframework.util.Assert; * @author Dave Syer * */ -public class HibernateAwareItemWriter extends ItemStreamAdapter implements ItemWriter, RepeatInterceptor, +public class HibernateAwareItemWriter implements ItemWriter, RepeatInterceptor, InitializingBean { /** diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/StaxEventItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/StaxEventItemReader.java index 72bcd7e7e..e20ef4048 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/StaxEventItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/StaxEventItemReader.java @@ -42,7 +42,7 @@ import org.springframework.util.Assert; * * @author Robert Kasanicky */ -public class StaxEventItemReader extends AbstractItemReader implements ItemReader, +public class StaxEventItemReader extends AbstractItemReader implements ItemReader, Skippable, ItemStream, StatisticsProvider, InitializingBean, DisposableBean { public static final String READ_COUNT_STATISTICS_NAME = "StaxEventReaderItemReader.readCount"; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemReader.java index 05f53f39c..a36561d88 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemReader.java @@ -38,7 +38,7 @@ import org.springframework.batch.item.reader.AbstractItemReader; * @author Lucas Ward * @since 1.0 */ -public interface ItemReader extends ItemStream { +public interface ItemReader { /** * Reads a piece of input data and advance to the next one. Implementations @@ -51,4 +51,12 @@ public interface ItemReader extends ItemStream { */ Object read() throws Exception; + /** + * Close the reader, freeing any resources that may have been allocated + * since the first call to read(). + * + * TODO: this is only used in sandbox? + * + */ + void close() throws Exception; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStream.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStream.java index 784c7d830..30a79e9c9 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStream.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStream.java @@ -35,16 +35,6 @@ package org.springframework.batch.item; * */ public interface ItemStream { - - void open() throws Exception; - - /** - * Close the reader, freeing any resources that may have been allocated - * since the first call to read(). - * - * @throws Exception if an underlying resource is unavailable - */ - void close() throws Exception; /** * Get {@link StreamContext} representing this object's current state. @@ -60,4 +50,16 @@ public interface ItemStream { * @param data */ void restoreFrom(StreamContext data); + + /** + * If any resources are needed for the stream to operate they need to be + * initialised here. + */ + void open() throws Exception; + + /** + * If any resources are needed for the stream to operate they need to be + * destroyed here. + */ + void close() throws Exception; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriter.java index c959dcd83..d94dc96b2 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriter.java @@ -25,7 +25,7 @@ package org.springframework.batch.item; * @author Dave Syer * @author Lucas Ward */ -public interface ItemWriter extends ItemStream { +public interface ItemWriter { /** * Process the supplied data element. Will be called multiple times during a @@ -38,4 +38,10 @@ public interface ItemWriter extends ItemStream { */ public void write(Object item) throws Exception; + /** + * Close the writer, allowing all allocated resources to be cleaned up. + * + * @throws Exception + */ + void close() throws Exception; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/AbstractItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/AbstractItemReader.java index 919bbc722..c9f33f7ca 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/AbstractItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/AbstractItemReader.java @@ -17,13 +17,19 @@ package org.springframework.batch.item.reader; import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.stream.ItemStreamAdapter; /** * Base class for {@link ItemReader} implementations. * @author Dave Syer * */ -public abstract class AbstractItemReader extends ItemStreamAdapter implements ItemReader { +public abstract class AbstractItemReader implements ItemReader { + + /** + * Do nothing. + * @see org.springframework.batch.item.ItemReader#close() + */ + public void close() throws Exception { + } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/DelegatingItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/DelegatingItemReader.java index f895bd971..2a75d64f3 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/DelegatingItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/DelegatingItemReader.java @@ -30,7 +30,7 @@ import org.springframework.util.Assert; * * @author Dave Syer */ -public class DelegatingItemReader extends AbstractItemReader implements ItemStream, Skippable, InitializingBean{ +public class DelegatingItemReader extends AbstractItemReader implements Skippable, InitializingBean, ItemStream { private ItemReader inputSource; @@ -87,4 +87,22 @@ public class DelegatingItemReader extends AbstractItemReader implements ItemStre ((Skippable)inputSource).skip(); } } + + /* (non-Javadoc) + * @see org.springframework.batch.item.ItemStream#open() + */ + public void open() throws Exception { + if (inputSource instanceof ItemStream) { + ((ItemStream) inputSource).open(); + } + } + + /* (non-Javadoc) + * @see org.springframework.batch.item.ItemStream#open() + */ + public void close() throws Exception { + if (inputSource instanceof ItemStream) { + ((ItemStream) inputSource).close(); + } + } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ItemReaderAdapter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ItemReaderAdapter.java index d3419b7ff..f9ffcebcf 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ItemReaderAdapter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ItemReaderAdapter.java @@ -16,11 +16,7 @@ package org.springframework.batch.item.reader; -import java.util.Properties; - import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.StreamContext; -import org.springframework.batch.item.stream.GenericStreamContext; import org.springframework.batch.support.AbstractMethodInvokingDelegator; /** @@ -39,33 +35,10 @@ public class ItemReaderAdapter extends AbstractMethodInvokingDelegator implement /** * Do nothing. - * @see org.springframework.batch.item.ItemStream#open() - */ - public void open() throws Exception { - // no-op - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#close() + * + * @see org.springframework.batch.item.ItemReader#close() */ public void close() throws Exception { - // no-op - } - - /** - * Return empty {@link StreamContext}. - * @see org.springframework.batch.item.ItemStream#getRestartData() - */ - public StreamContext getRestartData() { - return new GenericStreamContext(new Properties()); - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#restoreFrom(org.springframework.batch.item.StreamContext) - */ - public void restoreFrom(StreamContext data) { } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/stream/CompositeItemStream.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/stream/CompositeItemStream.java new file mode 100644 index 000000000..17ae317bc --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/stream/CompositeItemStream.java @@ -0,0 +1,158 @@ +/* + * Copyright 2006-2007 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.item.stream; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.StreamContext; + +/** + * @author Dave Syer + * + */ +public class CompositeItemStream implements ItemStream { + + private static final String SEPARATOR = "#"; + + private List delegates; + + public void setDelegates(List delegates) { + this.delegates = delegates; + } + + /** + * Compound restart data of all injected (Restartable) ItemProcessors, + * property keys are prefixed with list index of the ItemProcessor. + */ + public StreamContext getRestartData() { + Properties props = createCompoundProperties(new PropertiesExtractor() { + public Properties extractProperties(Object o) { + if (o instanceof ItemStream) { + return ((ItemStream) o).getRestartData().getProperties(); + } + else { + return null; + } + } + }); + return new GenericStreamContext(props); + } + + /** + * @param data contains values of restart data, property keys are expected + * to be prefixed with list index of the ItemProcessor. + */ + public void restoreFrom(StreamContext data) { + if (data == null || data.getProperties() == null) { + // do nothing + return; + } + + List restartDataList = parseProperties(data.getProperties()); + + // iterators would make the loop below less readable + for (int i = 0; i < delegates.size(); i++) { + if (delegates.get(i) instanceof ItemStream) { + ((ItemStream) delegates.get(i)).restoreFrom((StreamContext) restartDataList.get(i)); + } + } + + } + + /** + * Parses compound properties into a list of RestartData. + */ + private List parseProperties(Properties props) { + List restartDataList = new ArrayList(delegates.size()); + for (int i = 0; i < delegates.size(); i++) { + restartDataList.add(new GenericStreamContext(new Properties())); + } + + for (Iterator iterator = props.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + String key = (String) entry.getKey(); + String value = (String) entry.getValue(); + int separatorIndex = key.indexOf(SEPARATOR); + int i = Integer.valueOf(key.substring(0, separatorIndex)).intValue(); + ((StreamContext) restartDataList.get(i)).getProperties().setProperty(key.substring(separatorIndex + 1), + value); + } + return restartDataList; + } + + /** + * @param extractor used to extract Properties from {@link ItemReader}s + * @return compound Properties containing all the Properties from injected + * delegates with property keys prefixed by list index. + */ + private Properties createCompoundProperties(PropertiesExtractor extractor) { + Properties stats = new Properties(); + int index = 0; + for (Iterator iterator = delegates.listIterator(); iterator.hasNext();) { + Properties writerStats = extractor.extractProperties(iterator.next()); + if (writerStats != null) { + for (Iterator iterator2 = writerStats.entrySet().iterator(); iterator2.hasNext();) { + Map.Entry entry = (Map.Entry) iterator2.next(); + stats.setProperty("" + index + SEPARATOR + entry.getKey(), (String) entry.getValue()); + } + } + index++; + } + return stats; + } + + /** + * Extracts information from given object in the form of {@link Properties}. + * If the information is not available (e.g. unexpected object class) return + * null. + */ + private interface PropertiesExtractor { + Properties extractProperties(Object o); + } + + public void close() throws Exception { + for (Iterator iterator = delegates.listIterator(); iterator.hasNext();) { + Object delegate = iterator.next(); + if (delegate instanceof ItemStream) { + ((ItemStream) delegate).close(); + } + } + } + + public void open() throws Exception { + for (Iterator iterator = delegates.listIterator(); iterator.hasNext();) { + Object delegate = iterator.next(); + if (delegate instanceof ItemStream) { + ((ItemStream) delegate).open(); + } + } + } + + /** + * Public getter for the list of delegates. + * @return the delegates + */ + public List getDelegates() { + return delegates; + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/AbstractItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/AbstractItemWriter.java new file mode 100644 index 000000000..faab36072 --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/AbstractItemWriter.java @@ -0,0 +1,31 @@ +/* + * Copyright 2006-2008 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.item.writer; + +import org.springframework.batch.item.ItemWriter; + +/** + * Abstract {@link ItemWriter} that allows for base classes to only + * implement the close method if they need it. + * + * @author Lucas Ward + * + */ +public abstract class AbstractItemWriter implements ItemWriter{ + + public void close() throws Exception { + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/CompositeItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/CompositeItemWriter.java index b7cef6e09..7e8e8f942 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/CompositeItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/CompositeItemWriter.java @@ -1,131 +1,24 @@ package org.springframework.batch.item.writer; -import java.util.ArrayList; import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.StreamContext; -import org.springframework.batch.item.stream.GenericStreamContext; -import org.springframework.batch.item.stream.ItemStreamAdapter; +import org.springframework.batch.item.stream.CompositeItemStream; /** * Runs a collection of ItemProcessors in fixed-order sequence. * * @author Robert Kasanicky */ -public class CompositeItemWriter extends ItemStreamAdapter implements ItemWriter, ItemStream { - - private static final String SEPARATOR = "#"; - - private List delegates; +public class CompositeItemWriter extends CompositeItemStream implements ItemWriter { /** * Calls injected ItemProcessors in order. */ public void write(Object data) throws Exception { - for (Iterator iterator = delegates.listIterator(); iterator.hasNext();) { + for (Iterator iterator = getDelegates().listIterator(); iterator.hasNext();) { ((ItemWriter) iterator.next()).write(data); } } - /** - * Compound restart data of all injected (Restartable) ItemProcessors, - * property keys are prefixed with list index of the ItemProcessor. - */ - public StreamContext getRestartData() { - Properties props = createCompoundProperties(new PropertiesExtractor() { - public Properties extractProperties(ItemStream o) { - return o.getRestartData().getProperties(); - } - }); - return new GenericStreamContext(props); - } - - /** - * @param data contains values of restart data, property keys are expected - * to be prefixed with list index of the ItemProcessor. - */ - public void restoreFrom(StreamContext data) { - if (data == null || data.getProperties() == null) { - // do nothing - return; - } - - List restartDataList = parseProperties(data.getProperties()); - - // iterators would make the loop below less readable - for (int i = 0; i < delegates.size(); i++) { - if (delegates.get(i) instanceof ItemStream) { - ((ItemStream) delegates.get(i)).restoreFrom((StreamContext) restartDataList.get(i)); - } - } - - } - - public void setItemWriters(List itemProcessors) { - this.delegates = itemProcessors; - } - - /** - * Parses compound properties into a list of RestartData. - */ - private List parseProperties(Properties props) { - List restartDataList = new ArrayList(delegates.size()); - for (int i = 0; i < delegates.size(); i++) { - restartDataList.add(new GenericStreamContext(new Properties())); - } - - for (Iterator iterator = props.entrySet().iterator(); iterator.hasNext();) { - Map.Entry entry = (Map.Entry) iterator.next(); - String key = (String) entry.getKey(); - String value = (String) entry.getValue(); - int separatorIndex = key.indexOf(SEPARATOR); - int i = Integer.valueOf(key.substring(0, separatorIndex)).intValue(); - ((StreamContext) restartDataList.get(i)).getProperties() - .setProperty(key.substring(separatorIndex + 1), value); - } - return restartDataList; - } - - /** - * @param extractor used to extract Properties from {@link ItemReader}s - * @return compound Properties containing all the Properties from injected - * {@link ItemWriter}s with property keys prefixed by list index. - */ - private Properties createCompoundProperties(PropertiesExtractor extractor) { - Properties stats = new Properties(); - int index = 0; - for (Iterator iterator = delegates.listIterator(); iterator.hasNext();) { - Properties writerStats = extractor.extractProperties((ItemStream) iterator.next()); - if (writerStats != null) { - for (Iterator iterator2 = writerStats.entrySet().iterator(); iterator2.hasNext();) { - Map.Entry entry = (Map.Entry) iterator2.next(); - stats.setProperty("" + index + SEPARATOR + entry.getKey(), (String) entry.getValue()); - } - } - index++; - } - return stats; - } - - /** - * Extracts information from given object in the form of {@link Properties}. - * If the information is not available (e.g. unexpected object class) return - * null. - */ - private interface PropertiesExtractor { - Properties extractProperties(ItemStream o); - } - - public void close() throws Exception { - for (Iterator iterator = delegates.listIterator(); iterator.hasNext();) { - ((ItemWriter) iterator.next()).close(); - } - } - } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/DelegatingItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/DelegatingItemWriter.java index 262345d2d..bbd07e810 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/DelegatingItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/DelegatingItemWriter.java @@ -7,7 +7,6 @@ import org.springframework.batch.item.ItemStream; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.StreamContext; import org.springframework.batch.item.stream.GenericStreamContext; -import org.springframework.batch.item.stream.ItemStreamAdapter; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; @@ -18,7 +17,7 @@ import org.springframework.util.Assert; * @author Dave Syer * @author Robert Kasanicky */ -public class DelegatingItemWriter extends ItemStreamAdapter implements ItemWriter, Skippable, InitializingBean { +public class DelegatingItemWriter implements ItemWriter, Skippable, InitializingBean { private ItemWriter writer; @@ -88,6 +87,7 @@ public class DelegatingItemWriter extends ItemStreamAdapter implements ItemWrite Assert.notNull(writer); } + // YODO: remove public void close() throws Exception { writer.close(); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/ItemWriterAdapter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/ItemWriterAdapter.java index 0af53fcf9..c62257fe7 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/ItemWriterAdapter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/ItemWriterAdapter.java @@ -16,11 +16,7 @@ package org.springframework.batch.item.writer; -import java.util.Properties; - import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.StreamContext; -import org.springframework.batch.item.stream.GenericStreamContext; import org.springframework.batch.support.AbstractMethodInvokingDelegator; @@ -38,35 +34,13 @@ public class ItemWriterAdapter extends AbstractMethodInvokingDelegator implement invokeDelegateMethodWithArgument(item); } - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#open() - */ - public void open() throws Exception { - // no-op - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#close() - */ + /* + * No-op, can't call more than one method. + * + * (non-Javadoc) + * @see org.springframework.batch.item.ItemWriter#close() + */ public void close() throws Exception { - // no-op - } - - /** - * Return empty {@link StreamContext}. - * @see org.springframework.batch.item.ItemStream#getRestartData() - */ - public StreamContext getRestartData() { - return new GenericStreamContext(new Properties()); - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#restoreFrom(org.springframework.batch.item.StreamContext) - */ - public void restoreFrom(StreamContext data) { } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/PropertyExtractingDelegatingItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/PropertyExtractingDelegatingItemWriter.java index 9d52486f8..4af027cd2 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/PropertyExtractingDelegatingItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/PropertyExtractingDelegatingItemWriter.java @@ -16,11 +16,7 @@ package org.springframework.batch.item.writer; -import java.util.Properties; - import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.StreamContext; -import org.springframework.batch.item.stream.GenericStreamContext; import org.springframework.batch.support.AbstractMethodInvokingDelegator; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; @@ -70,35 +66,7 @@ public class PropertyExtractingDelegatingItemWriter extends AbstractMethodInvoki this.fieldsUsedAsTargetMethodArguments = fieldsUsedAsMethodArguments; } - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#open() - */ - public void open() throws Exception { - // no-op - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#close() - */ - public void close() throws Exception { - // no-op - } - /** - * Return empty {@link StreamContext}. - * @see org.springframework.batch.item.ItemStream#getRestartData() - */ - public StreamContext getRestartData() { - return new GenericStreamContext(new Properties()); - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#restoreFrom(org.springframework.batch.item.StreamContext) - */ - public void restoreFrom(StreamContext data) { - + public void close() throws Exception { } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooInputSource.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooInputSource.java index 4f27d9b76..135f1cfd9 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooInputSource.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooInputSource.java @@ -8,7 +8,7 @@ import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.jdbc.core.JdbcTemplate; -class FooItemReader extends AbstractItemReader implements ItemReader, ItemStream, DisposableBean, InitializingBean{ +class FooItemReader extends AbstractItemReader implements ItemStream, ItemReader, DisposableBean, InitializingBean{ DrivingQueryItemReader inputSource; FooDao fooDao = new SingleKeyFooDao(); @@ -44,5 +44,8 @@ class FooItemReader extends AbstractItemReader implements ItemReader, ItemStream } public void afterPropertiesSet() throws Exception { + } + + public void open() throws Exception { }; } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/HibernateAwareItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/HibernateAwareItemWriterTests.java index c09b49c47..c0ea8492d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/HibernateAwareItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/HibernateAwareItemWriterTests.java @@ -22,7 +22,7 @@ import java.util.Map; import junit.framework.TestCase; -import org.springframework.batch.item.writer.AbstractItemWriter; +import org.springframework.batch.item.ItemWriter; import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.RepeatContext; import org.springframework.batch.repeat.RepeatInterceptor; @@ -41,13 +41,12 @@ public class HibernateAwareItemWriterTests extends TestCase { public void flush() throws DataAccessException { list.add("flush"); } - public void clear() { - list.add("clear"); + list.add("clear"); }; } - private class StubItemWriter extends AbstractItemWriter implements RepeatInterceptor { + private class StubItemWriter implements ItemWriter, RepeatInterceptor { public void write(Object item) { list.add(item); } @@ -71,10 +70,13 @@ public class HibernateAwareItemWriterTests extends TestCase { public void open(RepeatContext context) { list.add(context); } + + public void close() throws Exception { + } } HibernateAwareItemWriter writer = new HibernateAwareItemWriter(); - + final List list = new ArrayList(); private RepeatContextSupport context; @@ -91,16 +93,15 @@ public class HibernateAwareItemWriterTests extends TestCase { writer.setHibernateTemplate(new HibernateTemplateWrapper()); list.clear(); } - - /* - * (non-Javadoc) + + /* (non-Javadoc) * @see junit.framework.TestCase#tearDown() */ protected void tearDown() throws Exception { Map map = TransactionSynchronizationManager.getResourceMap(); for (Iterator iterator = map.keySet().iterator(); iterator.hasNext();) { String key = (String) iterator.next(); - TransactionSynchronizationManager.unbindResource(key); + TransactionSynchronizationManager.unbindResource(key); } } @@ -115,10 +116,10 @@ public class HibernateAwareItemWriterTests extends TestCase { try { writer.afterPropertiesSet(); fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { + } catch (IllegalArgumentException e) { // expected - assertTrue("Wrong message for exception: " + e.getMessage(), e.getMessage().indexOf("delegate") >= 0); + assertTrue("Wrong message for exception: " + e.getMessage(), e + .getMessage().indexOf("delegate") >= 0); } } @@ -135,7 +136,7 @@ public class HibernateAwareItemWriterTests extends TestCase { /** * Test method for * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#write(java.lang.Object)}. - * @throws Exception + * @throws Exception */ public void testWrite() throws Exception { writer.write("foo"); @@ -157,8 +158,7 @@ public class HibernateAwareItemWriterTests extends TestCase { try { writer.close(context); fail("Expected RuntimeException"); - } - catch (RuntimeException e) { + } catch (RuntimeException e) { assertEquals("bar", e.getMessage()); } assertEquals(2, list.size()); @@ -169,7 +169,7 @@ public class HibernateAwareItemWriterTests extends TestCase { /** * Test method for * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#write(java.lang.Object)}. - * @throws Exception + * @throws Exception */ public void testWriteAndCloseWithFailure() throws Exception { final RuntimeException ex = new RuntimeException("bar"); @@ -182,8 +182,7 @@ public class HibernateAwareItemWriterTests extends TestCase { try { writer.close(context); fail("Expected RuntimeException"); - } - catch (RuntimeException e) { + } catch (RuntimeException e) { assertEquals("bar", e.getMessage()); } assertEquals(3, list.size()); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/CompositeItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/CompositeItemWriterTests.java index ab5ada97a..2b38984ba 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/CompositeItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/CompositeItemWriterTests.java @@ -8,10 +8,11 @@ import java.util.Properties; import junit.framework.TestCase; import org.easymock.MockControl; +import org.springframework.batch.item.ItemStream; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.StreamContext; import org.springframework.batch.item.stream.GenericStreamContext; -import org.springframework.batch.item.stream.ItemStreamAdapter; +import org.springframework.batch.item.writer.CompositeItemWriter; import org.springframework.batch.statistics.StatisticsProvider; /** @@ -48,7 +49,7 @@ public class CompositeItemWriterTests extends TestCase { controls.add(control); } - itemProcessor.setItemWriters(processors); + itemProcessor.setDelegates(processors); itemProcessor.write(data); for (Iterator iterator = controls.iterator(); iterator.hasNext();) { @@ -61,22 +62,27 @@ public class CompositeItemWriterTests extends TestCase { * All Restartable processors should be restarted, not-Restartable processors should be ignored. */ public void testRestart() { - final ItemWriter p2 = new ItemWriterStub(); - final ItemWriter p3 = new ItemWriterStub(); + //this mock with undefined behaviour makes sure not-Restartable processor is ignored + MockControl p1c = MockControl.createStrictControl(ItemWriter.class); + final ItemWriter p1 = (ItemWriter) p1c.getMock(); + + final ItemWriter p2 = new StubItemWriter(); + final ItemWriter p3 = new StubItemWriter(); List itemProcessors = new ArrayList(){{ + add(p1); add(p2); add(p3); }}; - itemProcessor.setItemWriters(itemProcessors); + itemProcessor.setDelegates(itemProcessors); StreamContext rd = itemProcessor.getRestartData(); itemProcessor.restoreFrom(rd); for (Iterator iterator = itemProcessors.iterator(); iterator.hasNext();) { ItemWriter processor = (ItemWriter) iterator.next(); - if (processor instanceof ItemWriterStub) { + if (processor instanceof StubItemWriter) { assertTrue("Injected processors are restarted", - ((ItemWriterStub)processor).restarted); + ((StubItemWriter)processor).restarted); } } @@ -86,35 +92,34 @@ public class CompositeItemWriterTests extends TestCase { final int NUMBER_OF_PROCESSORS = 10; - List controls = new ArrayList(NUMBER_OF_PROCESSORS); List processors = new ArrayList(NUMBER_OF_PROCESSORS); + final List list = new ArrayList(NUMBER_OF_PROCESSORS); for (int i = 0; i < NUMBER_OF_PROCESSORS; i++) { - MockControl control = MockControl.createStrictControl(ItemWriter.class); - ItemWriter processor = (ItemWriter) control.getMock(); - + ItemWriter processor = new AbstractItemWriter() { + public void write(Object item) throws Exception { + throw new IllegalStateException("No way!"); + } + public void close() throws Exception { + list.add(this); + } + }; processor.close(); - control.setVoidCallable(); - control.replay(); - processors.add(processor); - controls.add(control); } - itemProcessor.setItemWriters(processors); + itemProcessor.setDelegates(processors); itemProcessor.close(); - for (Iterator iterator = controls.iterator(); iterator.hasNext();) { - MockControl control = (MockControl) iterator.next(); - control.verify(); - } + assertEquals(NUMBER_OF_PROCESSORS, list.size()); + } /** * Stub for testing restart. Checks the restart data received is the same that was returned by * getRestartData() */ - private static class ItemWriterStub extends ItemStreamAdapter implements ItemWriter, StatisticsProvider { + private static class StubItemWriter implements ItemWriter, ItemStream, StatisticsProvider { private static final String RESTART_KEY = "restartData"; private static final String STATS_KEY = "stats"; @@ -149,9 +154,10 @@ public class CompositeItemWriterTests extends TestCase { } public void close() throws Exception { - } + public void open() throws Exception { + } } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/AsynchronousRepeatTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/AsynchronousRepeatTests.java index ab5a59625..3d136984c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/AsynchronousRepeatTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/AsynchronousRepeatTests.java @@ -19,9 +19,9 @@ package org.springframework.batch.repeat.support; import java.util.HashSet; import java.util.Set; -import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.RepeatCallback; import org.springframework.batch.repeat.RepeatContext; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.callback.ItemReaderRepeatCallback; import org.springframework.core.task.SimpleAsyncTaskExecutor; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/FlatFileCustomerCreditWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/FlatFileCustomerCreditWriter.java index 81699d050..888c1ef65 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/FlatFileCustomerCreditWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/FlatFileCustomerCreditWriter.java @@ -16,6 +16,7 @@ package org.springframework.batch.sample.dao; +import org.springframework.batch.item.ItemStream; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.sample.domain.CustomerCredit; import org.springframework.beans.factory.DisposableBean; @@ -56,12 +57,16 @@ public class FlatFileCustomerCreditWriter implements CustomerCreditDao, } public void open() throws Exception { - outputSource.open(); + if (outputSource instanceof ItemStream) { + ((ItemStream) outputSource).open(); + } opened = true; } public void close() throws Exception { - outputSource.close(); + if (outputSource instanceof ItemStream) { + ((ItemStream) outputSource).close(); + } } /* diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcGameDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcGameDao.java index 8cf446687..cb2b26b5c 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcGameDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcGameDao.java @@ -1,10 +1,6 @@ package org.springframework.batch.sample.dao; -import java.util.Properties; - import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.StreamContext; -import org.springframework.batch.item.stream.GenericStreamContext; import org.springframework.batch.sample.domain.Game; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.util.Assert; @@ -38,36 +34,7 @@ public class JdbcGameDao extends JdbcDaoSupport implements ItemWriter { this.getJdbcTemplate().update(INSERT_GAME, args); } - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#open() - */ - public void open() throws Exception { - // no-op - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#close() - */ public void close() throws Exception { - // no-op - } - - /** - * Return empty {@link StreamContext}. - * @see org.springframework.batch.item.ItemStream#getRestartData() - */ - public StreamContext getRestartData() { - return new GenericStreamContext(new Properties()); - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#restoreFrom(org.springframework.batch.item.StreamContext) - */ - public void restoreFrom(StreamContext data) { - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcPlayerSummaryDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcPlayerSummaryDao.java index 4f736305b..c1a5593a1 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcPlayerSummaryDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcPlayerSummaryDao.java @@ -1,10 +1,6 @@ package org.springframework.batch.sample.dao; -import java.util.Properties; - import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.StreamContext; -import org.springframework.batch.item.stream.GenericStreamContext; import org.springframework.batch.sample.domain.PlayerSummary; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.util.Assert; @@ -32,36 +28,7 @@ public class JdbcPlayerSummaryDao extends JdbcDaoSupport implements ItemWriter { getJdbcTemplate().update(INSERT_SUMMARY, args); } - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#open() - */ - public void open() throws Exception { - // no-op - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#close() - */ public void close() throws Exception { - // no-op - } - - /** - * Return empty {@link StreamContext}. - * @see org.springframework.batch.item.ItemStream#getRestartData() - */ - public StreamContext getRestartData() { - return new GenericStreamContext(new Properties()); - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#restoreFrom(org.springframework.batch.item.StreamContext) - */ - public void restoreFrom(StreamContext data) { - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/reader/StagingItemReader.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/reader/StagingItemReader.java index 8f73bbcf1..c944ca3ac 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/reader/StagingItemReader.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/reader/StagingItemReader.java @@ -5,7 +5,6 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.Properties; import org.apache.commons.lang.SerializationUtils; import org.apache.commons.logging.Log; @@ -13,8 +12,6 @@ import org.apache.commons.logging.LogFactory; import org.springframework.batch.execution.scope.StepContext; import org.springframework.batch.execution.scope.StepContextAware; import org.springframework.batch.item.KeyedItemReader; -import org.springframework.batch.item.StreamContext; -import org.springframework.batch.item.stream.GenericStreamContext; import org.springframework.batch.repeat.synch.BatchTransactionSynchronizationManager; import org.springframework.batch.sample.item.writer.StagingItemWriter; import org.springframework.beans.factory.DisposableBean; @@ -252,21 +249,5 @@ public class StagingItemReader extends JdbcDaoSupport implements KeyedItemReader return "list=" + list + "; iter.hasNext()=" + iter.hasNext(); } } - - /** - * Return empty {@link StreamContext}. - * @see org.springframework.batch.item.ItemStream#getRestartData() - */ - public StreamContext getRestartData() { - return new GenericStreamContext(new Properties()); - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#restoreFrom(org.springframework.batch.item.StreamContext) - */ - public void restoreFrom(StreamContext data) { - - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerCreditIncreaseWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerCreditIncreaseWriter.java index 914ab0d40..5316da281 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerCreditIncreaseWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerCreditIncreaseWriter.java @@ -3,7 +3,6 @@ package org.springframework.batch.sample.item.writer; import java.math.BigDecimal; import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.writer.AbstractItemWriter; import org.springframework.batch.sample.dao.CustomerCreditDao; import org.springframework.batch.sample.domain.CustomerCredit; @@ -12,7 +11,7 @@ import org.springframework.batch.sample.domain.CustomerCredit; * * @author Robert Kasanicky */ -public class CustomerCreditIncreaseWriter extends AbstractItemWriter implements ItemWriter { +public class CustomerCreditIncreaseWriter implements ItemWriter { public static final BigDecimal FIXED_AMOUNT = new BigDecimal(1000); @@ -35,9 +34,6 @@ public class CustomerCreditIncreaseWriter extends AbstractItemWriter implements customerCreditDao.writeCredit(customerCredit); } - public void open() throws Exception { - } - public void close() throws Exception { } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerCreditUpdateWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerCreditUpdateWriter.java index d178865a8..24fec5d03 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerCreditUpdateWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerCreditUpdateWriter.java @@ -17,13 +17,12 @@ package org.springframework.batch.sample.item.writer; import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.writer.AbstractItemWriter; import org.springframework.batch.sample.dao.CustomerCreditDao; import org.springframework.batch.sample.domain.CustomerCredit; -public class CustomerCreditUpdateWriter extends AbstractItemWriter implements ItemWriter { +public class CustomerCreditUpdateWriter implements ItemWriter { private double creditFilter = 800; private CustomerCreditDao dao; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerUpdateWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerUpdateWriter.java index f73b8839b..fe5c1edb1 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerUpdateWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerUpdateWriter.java @@ -17,7 +17,6 @@ package org.springframework.batch.sample.item.writer; import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.writer.AbstractItemWriter; import org.springframework.batch.sample.dao.JdbcCustomerDebitWriter; import org.springframework.batch.sample.domain.CustomerDebit; import org.springframework.batch.sample.domain.Trade; @@ -28,7 +27,7 @@ import org.springframework.batch.sample.domain.Trade; * * @author Robert Kasanicky */ -public class CustomerUpdateWriter extends AbstractItemWriter implements ItemWriter { +public class CustomerUpdateWriter implements ItemWriter { private JdbcCustomerDebitWriter dao; public void write(Object data) { @@ -43,6 +42,9 @@ public class CustomerUpdateWriter extends AbstractItemWriter implements ItemWrit this.dao = outputSource; } + public void close() { + } + public void init() { } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/DummyItemWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/DummyItemWriter.java index e88202c3a..e3e381c42 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/DummyItemWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/DummyItemWriter.java @@ -15,16 +15,19 @@ */ package org.springframework.batch.sample.item.writer; -import org.springframework.batch.item.writer.AbstractItemWriter; +import org.springframework.batch.item.ItemWriter; /** * @author Dave Syer * */ -public class DummyItemWriter extends AbstractItemWriter { +public class DummyItemWriter implements ItemWriter { public void write(Object item) throws Exception { // NO-OP } + public void close() throws Exception { + } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/PersonWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/PersonWriter.java index ef264a962..e98ad5cb1 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/PersonWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/PersonWriter.java @@ -18,12 +18,12 @@ package org.springframework.batch.sample.item.writer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.batch.item.writer.AbstractItemWriter; +import org.springframework.batch.item.ItemWriter; import org.springframework.batch.sample.domain.Person; -public class PersonWriter extends AbstractItemWriter { +public class PersonWriter implements ItemWriter { private static Log log = LogFactory.getLog(PersonWriter.class); public void write(Object data) { @@ -36,6 +36,9 @@ public class PersonWriter extends AbstractItemWriter { log.debug("Processing: " + data); } + public void close() { + } + public void init() { } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/PlayerItemWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/PlayerItemWriter.java index f2be20e83..71b9e50c1 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/PlayerItemWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/PlayerItemWriter.java @@ -1,10 +1,10 @@ package org.springframework.batch.sample.item.writer; -import org.springframework.batch.item.writer.AbstractItemWriter; +import org.springframework.batch.item.ItemWriter; import org.springframework.batch.sample.dao.PlayerDao; import org.springframework.batch.sample.domain.Player; -public class PlayerItemWriter extends AbstractItemWriter { +public class PlayerItemWriter implements ItemWriter { PlayerDao playerDao; @@ -16,4 +16,6 @@ public class PlayerItemWriter extends AbstractItemWriter { this.playerDao = playerDao; } + public void close() throws Exception { + } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/StagingItemWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/StagingItemWriter.java index eac1fdf7f..7d89feb6f 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/StagingItemWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/StagingItemWriter.java @@ -2,14 +2,11 @@ package org.springframework.batch.sample.item.writer; import java.io.Serializable; import java.sql.Types; -import java.util.Properties; import org.apache.commons.lang.SerializationUtils; import org.springframework.batch.execution.scope.StepContext; import org.springframework.batch.execution.scope.StepContextAware; import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.StreamContext; -import org.springframework.batch.item.stream.GenericStreamContext; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; import org.springframework.util.Assert; @@ -76,37 +73,7 @@ public class StagingItemWriter extends JdbcDaoSupport implements new int[] { Types.BIGINT, Types.BIGINT, Types.BLOB, Types.CHAR}); } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#open() - */ - public void open() throws Exception { - // no-op - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#close() - */ public void close() throws Exception { - // no-op - } - - /** - * Return empty {@link StreamContext}. - * @see org.springframework.batch.item.ItemStream#getRestartData() - */ - public StreamContext getRestartData() { - return new GenericStreamContext(new Properties()); - } - - /** - * Do nothing. - * @see org.springframework.batch.item.ItemStream#restoreFrom(org.springframework.batch.item.StreamContext) - */ - public void restoreFrom(StreamContext data) { - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/TradeWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/TradeWriter.java index de8883f66..2ed389d9a 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/TradeWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/TradeWriter.java @@ -18,13 +18,13 @@ package org.springframework.batch.sample.item.writer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.batch.item.writer.AbstractItemWriter; +import org.springframework.batch.item.ItemWriter; import org.springframework.batch.sample.dao.TradeDao; import org.springframework.batch.sample.domain.Trade; -public class TradeWriter extends AbstractItemWriter { +public class TradeWriter implements ItemWriter { private static Log log = LogFactory.getLog(TradeWriter.class); private TradeDao dao; diff --git a/spring-batch-samples/src/main/resources/jobs/compositeProcessorSampleJob.xml b/spring-batch-samples/src/main/resources/jobs/compositeProcessorSampleJob.xml index 45a762e10..8ab0bf7a9 100644 --- a/spring-batch-samples/src/main/resources/jobs/compositeProcessorSampleJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/compositeProcessorSampleJob.xml @@ -25,7 +25,7 @@ - + diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RestartFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RestartFunctionalTests.java index af10952ee..38e0a4e76 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RestartFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RestartFunctionalTests.java @@ -75,7 +75,8 @@ public class RestartFunctionalTests extends AbstractBatchLauncherTests { } int medium = jdbcTemplate.queryForInt("SELECT COUNT(*) FROM TRADE"); -System.err.println(medium); + // assert based on commit inyerval = 2 + assertEquals(before+2, medium); runJob(); diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/FlatFileCustomerCreditWriterTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/FlatFileCustomerCreditWriterTests.java index a1ddc9e36..3e15c5aab 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/FlatFileCustomerCreditWriterTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/FlatFileCustomerCreditWriterTests.java @@ -5,6 +5,7 @@ import java.math.BigDecimal; import junit.framework.TestCase; import org.easymock.MockControl; +import org.springframework.batch.item.ItemStream; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.sample.domain.CustomerCredit; @@ -74,7 +75,7 @@ public class FlatFileCustomerCreditWriterTests extends TestCase { outputControl.verify(); } - private interface ResourceLifecycleItemWriter extends ItemWriter { + private interface ResourceLifecycleItemWriter extends ItemWriter, ItemStream{ } }