diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/domain/Job.java b/spring-batch-core/src/main/java/org/springframework/batch/core/domain/Job.java index 964866380..6e604ed1c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/domain/Job.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/domain/Job.java @@ -18,7 +18,6 @@ package org.springframework.batch.core.domain; import java.util.List; import org.springframework.batch.io.exception.BatchCriticalException; -import org.springframework.batch.repeat.ExitStatus; /** * Batch domain object representing a job. Job is an explicit abstraction @@ -39,6 +38,6 @@ public interface Job { boolean isRestartable(); - ExitStatus run(JobExecution execution) throws BatchCriticalException; + void run(JobExecution execution) throws BatchCriticalException; } \ No newline at end of file diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/domain/JobSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/domain/JobSupport.java index db479b1f7..e79e6dcb7 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/domain/JobSupport.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/domain/JobSupport.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.List; import org.springframework.batch.io.exception.BatchCriticalException; -import org.springframework.batch.repeat.ExitStatus; import org.springframework.beans.factory.BeanNameAware; import org.springframework.util.ClassUtils; @@ -134,7 +133,7 @@ public class JobSupport implements BeanNameAware, Job { /* (non-Javadoc) * @see org.springframework.batch.core.domain.Job#run(org.springframework.batch.core.domain.JobExecution) */ - public ExitStatus run(JobExecution execution) throws BatchCriticalException { + public void run(JobExecution execution) throws BatchCriticalException { throw new UnsupportedOperationException("JobSupport does not provide an implementation of run(). Use a smarter subclass."); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/domain/Step.java b/spring-batch-core/src/main/java/org/springframework/batch/core/domain/Step.java index 266984873..a555b2489 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/domain/Step.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/domain/Step.java @@ -16,14 +16,12 @@ package org.springframework.batch.core.domain; import org.springframework.batch.io.exception.BatchCriticalException; -import org.springframework.batch.repeat.ExitStatus; - /** * Batch domain interface representing the configuration of a step. As with the - * (@link Job), step configuration is meant to explicitly represent - * a the configuration of a step by a developer. This allows for the separation - * of what a developer configures from the myriad of concerns required for + * (@link Job), step configuration is meant to explicitly represent a the + * configuration of a step by a developer. This allows for the separation of + * what a developer configures from the myriad of concerns required for * executing a job. * * @author Dave Syer @@ -41,7 +39,7 @@ public interface Step { * again. */ boolean isAllowStartIfComplete(); - + /** * Flag to indicate if restart data needs to be saved for this step. * @return true if restart data should be saved @@ -53,11 +51,15 @@ public interface Step { * identifier. */ int getStartLimit(); - + /** - * It is not safe to re-use an instance of {@link StepExecutor} to process - * multiple concurrent executions. Use the factory method in {@link Step} to - * create a new instance and execute that. + * Process the step and assign progress and status meta information to the + * {@link StepExecution} provided. The {@link Step} is responsible for + * setting the meta information and also saving it if required by the + * implementation.
+ * + * It is not safe to re-use an instance of {@link Step} to process multiple + * concurrent executions. * * @param stepExecution an entity representing the step to be executed * @@ -65,6 +67,6 @@ public interface Step { * @throws BatchCriticalException if there is a problem that needs to be * signalled to the caller */ - ExitStatus process(StepExecution stepExecution) throws StepInterruptedException, BatchCriticalException; + void process(StepExecution stepExecution) throws StepInterruptedException, BatchCriticalException; } \ No newline at end of file diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/domain/StepSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/domain/StepSupport.java index bcbee4640..a7baba0a5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/domain/StepSupport.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/domain/StepSupport.java @@ -136,7 +136,7 @@ public class StepSupport implements Step, BeanNameAware { * * @see org.springframework.batch.core.domain.Step#process(org.springframework.batch.core.domain.StepExecution) */ - public org.springframework.batch.repeat.ExitStatus process(StepExecution stepExecution) + public void process(StepExecution stepExecution) throws StepInterruptedException, BatchCriticalException { throw new UnsupportedOperationException( "Cannot process a StepExecution. Use a smarter subclass of StepSupport."); diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/job/simple/SimpleJob.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/job/simple/SimpleJob.java index b1124dbf1..241672c9b 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/job/simple/SimpleJob.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/job/simple/SimpleJob.java @@ -55,7 +55,7 @@ public class SimpleJob extends JobSupport { * * @see org.springframework.batch.core.domain.Job#run(org.springframework.batch.core.domain.JobExecution) */ - public ExitStatus run(JobExecution execution) throws BatchCriticalException { + public void run(JobExecution execution) throws BatchCriticalException { JobInstance jobInstance = execution.getJobInstance(); updateStatus(execution, BatchStatus.STARTING); @@ -78,7 +78,8 @@ public class SimpleJob extends JobSupport { startedCount++; updateStatus(execution, BatchStatus.STARTED); StepExecution stepExecution = execution.createStepExecution(stepInstance); - status = step.process(stepExecution); + step.process(stepExecution); + status = stepExecution.getExitStatus(); } } @@ -111,7 +112,6 @@ public class SimpleJob extends JobSupport { jobRepository.saveOrUpdate(execution); } - return status; } private void updateStatus(JobExecution jobExecution, BatchStatus status) { diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/SimpleJobLauncher.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/SimpleJobLauncher.java index 87f4622b5..c68ad4327 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/SimpleJobLauncher.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/SimpleJobLauncher.java @@ -24,7 +24,6 @@ import org.springframework.batch.core.domain.JobParameters; import org.springframework.batch.core.domain.JobSupport; import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.repeat.ExitStatus; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.task.SyncTaskExecutor; import org.springframework.core.task.TaskExecutor; @@ -83,10 +82,7 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean { public void run() { try { logger.info("Job: [" + job + "] launched with the following parameters: [" + jobParameters + "]"); - ExitStatus exitStatus = job.run(jobExecution); - // The exit status should be set by the Job. TODO: remove - // this line... - jobExecution.setExitStatus(exitStatus); + job.run(jobExecution); logger.info("Job: [" + job + "] completed successfully with the following parameters: [" + jobParameters + "]"); } diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/simple/AbstractStep.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/simple/AbstractStep.java index e4fd4dec2..cbaf5c6fa 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/simple/AbstractStep.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/simple/AbstractStep.java @@ -22,7 +22,6 @@ import org.springframework.batch.core.domain.StepSupport; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.tasklet.Tasklet; import org.springframework.batch.io.exception.BatchCriticalException; -import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.exception.handler.ExceptionHandler; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.util.Assert; @@ -112,9 +111,9 @@ public abstract class AbstractStep extends StepSupport { /* (non-Javadoc) * @see org.springframework.batch.core.domain.StepSupport#process(org.springframework.batch.core.domain.StepExecution) */ - public ExitStatus process(StepExecution stepExecution) throws StepInterruptedException, BatchCriticalException { + public void process(StepExecution stepExecution) throws StepInterruptedException, BatchCriticalException { SimpleStepExecutor executor = createStepExecutor(); - return executor.process(stepExecution); + executor.process(stepExecution); } /** diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/simple/RepeatOperationsStep.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/simple/RepeatOperationsStep.java index daaed6c19..743cef001 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/simple/RepeatOperationsStep.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/simple/RepeatOperationsStep.java @@ -20,7 +20,6 @@ import org.springframework.batch.core.domain.Step; import org.springframework.batch.core.domain.StepExecution; import org.springframework.batch.core.domain.StepInterruptedException; import org.springframework.batch.io.exception.BatchCriticalException; -import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.RepeatOperations; /** @@ -78,7 +77,7 @@ public class RepeatOperationsStep extends AbstractStep implements RepeatOperatio /* (non-Javadoc) * @see org.springframework.batch.execution.step.simple.AbstractStep#process(org.springframework.batch.core.domain.StepExecution) */ - public ExitStatus process(StepExecution stepExecution) throws StepInterruptedException, BatchCriticalException { + public void process(StepExecution stepExecution) throws StepInterruptedException, BatchCriticalException { assertMandatoryProperties(); SimpleStepExecutor executor = (SimpleStepExecutor) super.createStepExecutor(); if (stepOperations != null) { @@ -87,6 +86,6 @@ public class RepeatOperationsStep extends AbstractStep implements RepeatOperatio if (chunkOperations != null) { executor.setChunkOperations(chunkOperations); } - return executor.process(stepExecution); + executor.process(stepExecution); } } diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java index 38e1d8494..4215746cd 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java @@ -173,7 +173,7 @@ public class SimpleStepExecutor { * execution * @see StepExecutor#process(StepExecution) */ - public ExitStatus process(final StepExecution stepExecution) throws BatchCriticalException, + public void process(final StepExecution stepExecution) throws BatchCriticalException, StepInterruptedException { final StepInstance stepInstance = stepExecution.getStep(); @@ -276,7 +276,6 @@ public class SimpleStepExecutor { }); updateStatus(stepExecution, BatchStatus.COMPLETED); - return status; } catch (RuntimeException e) { diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/tasklet/ItemOrientedTasklet.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/tasklet/ItemOrientedTasklet.java index 883fea698..5e5f0f7a6 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/tasklet/ItemOrientedTasklet.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/tasklet/ItemOrientedTasklet.java @@ -21,6 +21,7 @@ import org.springframework.batch.io.Skippable; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemRecoverer; import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.KeyedItemReader; import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.retry.RetryPolicy; import org.springframework.batch.retry.callback.ItemReaderRetryCallback; @@ -111,7 +112,8 @@ public class ItemOrientedTasklet implements Tasklet, Skippable, InitializingBean template.setRetryPolicy(itemProviderRetryPolicy); if (retryPolicy != null) { - retryCallback = new ItemReaderRetryCallback(itemProvider, itemWriter); + Assert.state(itemProvider instanceof KeyedItemReader, "ItemReader must be instance of KeyedItemReader to use the retry policy"); + retryCallback = new ItemReaderRetryCallback((KeyedItemReader) itemProvider, itemWriter); retryCallback.setRecoverer(itemRecoverer); } diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/job/simple/SimpleJobTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/job/simple/SimpleJobTests.java index 246fc77b8..f2abe69c4 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/job/simple/SimpleJobTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/job/simple/SimpleJobTests.java @@ -272,7 +272,7 @@ public class SimpleJobTests extends TestCase { this.runnable = runnable; } - public ExitStatus process(StepExecution stepExecution) throws StepInterruptedException, BatchCriticalException { + public void process(StepExecution stepExecution) throws StepInterruptedException, BatchCriticalException { if (exception instanceof RuntimeException) { throw (RuntimeException)exception; } @@ -282,7 +282,7 @@ public class SimpleJobTests extends TestCase { if (runnable!=null) { runnable.run(); } - return ExitStatus.FINISHED; + stepExecution.setExitStatus(ExitStatus.FINISHED); } } diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/SimpleJobLauncherTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/SimpleJobLauncherTests.java index 10c178e8e..e0b86c8b8 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/SimpleJobLauncherTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/SimpleJobLauncherTests.java @@ -41,8 +41,9 @@ public class SimpleJobLauncherTests extends TestCase { private MockControl repositoryControl = MockControl.createControl(JobRepository.class); private Job job = new JobSupport("foo") { - public ExitStatus run(JobExecution execution) { - return ExitStatus.FINISHED; + public void run(JobExecution execution) { + execution.setExitStatus(ExitStatus.FINISHED); + return; } }; @@ -88,7 +89,7 @@ public class SimpleJobLauncherTests extends TestCase { public void testRunWithException() throws Exception { job = new JobSupport() { - public ExitStatus run(JobExecution execution) { + public void run(JobExecution execution) { execution.setExitStatus(ExitStatus.FAILED); throw new RuntimeException("foo"); } @@ -104,7 +105,7 @@ public class SimpleJobLauncherTests extends TestCase { public void testRunWithError() throws Exception { job = new JobSupport() { - public ExitStatus run(JobExecution execution) { + public void run(JobExecution execution) { execution.setExitStatus(ExitStatus.FAILED); throw new Error("foo"); } 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 9d03297de..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 @@ -27,6 +27,7 @@ import org.springframework.batch.io.Skippable; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemRecoverer; import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.KeyedItemReader; import org.springframework.batch.item.reader.AbstractItemReader; import org.springframework.batch.item.writer.AbstractItemWriter; import org.springframework.batch.repeat.context.RepeatContextSupport; @@ -217,11 +218,7 @@ public class ItemOrientedTaskletTests extends TestCase { return true; } }); - module.setItemReader(new AbstractItemReader() { - public Object read() throws Exception { - return "foo"; - } - }); + module.setItemReader(new MockItemReader()); module.setItemWriter(new AbstractItemWriter() { public void write(Object data) throws Exception { throw new RuntimeException("FOO"); @@ -267,7 +264,16 @@ public class ItemOrientedTaskletTests extends TestCase { } } - private class SkippableItemReader implements ItemReader, + private class MockItemReader extends AbstractItemReader implements KeyedItemReader { + public Object read() throws Exception { + return "foo"; + } + public Object getKey(Object item) { + return item; + } + } + + private class SkippableItemReader implements KeyedItemReader, Skippable, StatisticsProvider { public Object read() throws Exception { return itemProvider.read(); 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 7752ee0cd..786c15c25 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 @@ -55,10 +55,6 @@ public class RestartableItemOrientedTaskletTests extends TestCase { assertEquals(this.data.getProperties(), data.getProperties()); } - public Object getKey(Object item) { - return null; - } - public boolean recover(Object data, Throwable cause) { return false; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/cursor/JdbcCursorItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/cursor/JdbcCursorItemReader.java index f5fc39efb..2f18b1018 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/cursor/JdbcCursorItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/cursor/JdbcCursorItemReader.java @@ -31,7 +31,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.batch.io.Skippable; import org.springframework.batch.io.support.AbstractTransactionalIoSource; -import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.KeyedItemReader; import org.springframework.batch.item.ResourceLifecycle; import org.springframework.batch.restart.GenericRestartData; import org.springframework.batch.restart.RestartData; @@ -117,7 +117,7 @@ import org.springframework.util.StringUtils; * @author Peter Zozom */ public class JdbcCursorItemReader extends AbstractTransactionalIoSource - implements ItemReader, ResourceLifecycle, DisposableBean, + implements KeyedItemReader, ResourceLifecycle, DisposableBean, InitializingBean, Restartable, StatisticsProvider, Skippable { private static Log log = LogFactory.getLog(JdbcCursorItemReader.class); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/DrivingQueryItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/DrivingQueryItemReader.java index 1dc05952f..2f37d3bcc 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/DrivingQueryItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/DrivingQueryItemReader.java @@ -19,7 +19,7 @@ import java.util.Iterator; import java.util.List; import org.springframework.batch.io.support.AbstractTransactionalIoSource; -import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.KeyedItemReader; import org.springframework.batch.item.ResourceLifecycle; import org.springframework.batch.repeat.synch.BatchTransactionSynchronizationManager; import org.springframework.batch.restart.RestartData; @@ -51,7 +51,7 @@ import org.springframework.util.Assert; * @since 1.0 */ public class DrivingQueryItemReader extends AbstractTransactionalIoSource - implements ItemReader, ResourceLifecycle, InitializingBean, + implements KeyedItemReader, ResourceLifecycle, InitializingBean, DisposableBean, Restartable { private boolean initialized = false; 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 f63d0f140..33619c813 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 @@ -16,9 +16,10 @@ package org.springframework.batch.item; +import org.springframework.batch.item.reader.AbstractItemReader; + /** - * Strategy interface for providing the data for a given batch stage execution. - *
+ * Strategy interface for providing the data.
* * Implementations are expected to be stateful and will be called multiple times * for each batch, with each call to {@link #next} returning a different value @@ -26,8 +27,8 @@ package org.springframework.batch.item; * * Implementations need to be thread safe and clients of a {@link ItemReader} * need to be aware that this is the case. Clients can code to this interface - * without worrying about thread safety by using the AbstractItemProvider base - * class.
+ * without worrying about thread safety by using the {@link AbstractItemReader} + * base class.
* * A richer interface (e.g. with a look ahead or peek) is not feasible because * we need to support transactions in an asynchronous batch. @@ -50,15 +51,6 @@ public interface ItemReader { */ Object read() throws Exception; - /** - * Get a unique identifier for the item that can be used to cache it between - * calls if necessary, and then identify it later. - * - * @param item the current item. - * @return a unique identifier. - */ - Object getKey(Object item); - /** * Close the reader, freeing any resources that may have been allocated * since the first call to read(). diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/KeyedItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/KeyedItemReader.java new file mode 100644 index 000000000..44441138c --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/KeyedItemReader.java @@ -0,0 +1,36 @@ +/* + * 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; + +/** + * Extension of the {@link ItemReader} interface that allows items to be + * identified and tagged by a unique key. + * + * @author Dave Syer + * + */ +public interface KeyedItemReader extends ItemReader { + + /** + * Get a unique identifier for the item that can be used to cache it between + * calls if necessary, and then identify it later. + * + * @param item the current item. + * @return a unique identifier. + */ + Object getKey(Object item); + +} 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 77f2d1a63..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 @@ -24,18 +24,11 @@ import org.springframework.batch.item.ItemReader; * */ public abstract class AbstractItemReader implements ItemReader { - - /** - * Simply returns the item itself. Will be adequate for many purposes, but - * not (for example) if the item is a message - in which case the identifier - * should be used. - * - * @see org.springframework.batch.item.ItemReader#getKey(java.lang.Object) - */ - public Object getKey(Object item) { - return item; - } + /** + * 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/ItemReaderAdapter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ItemReaderAdapter.java index abf0fad7a..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 @@ -33,11 +33,11 @@ public class ItemReaderAdapter extends AbstractMethodInvokingDelegator implement return invokeDelegateMethod(); } - //harmless implementation of method required by ItemReader interface - public Object getKey(Object item) { - return item; - } - + /** + * 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/JmsItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/JmsItemReader.java index f31f037dd..85a2c90e1 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/JmsItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/JmsItemReader.java @@ -24,6 +24,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.batch.item.FailedItemIdentifier; import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.KeyedItemReader; import org.springframework.batch.item.exception.UnexpectedInputException; import org.springframework.jms.JmsException; import org.springframework.jms.core.JmsOperations; @@ -39,7 +40,7 @@ import org.springframework.util.Assert; * @author Dave Syer * */ -public class JmsItemReader extends AbstractItemReader implements FailedItemIdentifier { +public class JmsItemReader extends AbstractItemReader implements KeyedItemReader, FailedItemIdentifier { protected Log logger = LogFactory.getLog(getClass()); @@ -151,7 +152,7 @@ public class JmsItemReader extends AbstractItemReader implements FailedItemIdent throw new UnexpectedInputException("Could not extract message ID", e); } } - return super.getKey(item); + return item; } /** diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/callback/ItemReaderRetryCallback.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/callback/ItemReaderRetryCallback.java index 97ce24ac1..c784c3119 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/callback/ItemReaderRetryCallback.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/callback/ItemReaderRetryCallback.java @@ -21,6 +21,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemRecoverer; import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.KeyedItemReader; import org.springframework.batch.retry.RetryCallback; import org.springframework.batch.retry.RetryContext; import org.springframework.batch.retry.RetryPolicy; @@ -47,13 +48,13 @@ public class ItemReaderRetryCallback implements RetryCallback { public static final String ITEM = ItemReaderRetryCallback.class.getName() + ".ITEM"; - private ItemReader provider; + private KeyedItemReader provider; private ItemWriter writer; private ItemRecoverer recoverer; - public ItemReaderRetryCallback(ItemReader provider, + public ItemReaderRetryCallback(KeyedItemReader provider, ItemWriter writer) { super(); this.provider = provider; @@ -127,7 +128,7 @@ public class ItemReaderRetryCallback implements RetryCallback { * * @return the {@link ItemReader} instance. */ - public ItemReader getReader() { + public KeyedItemReader getReader() { return provider; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/policy/ItemReaderRetryPolicy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/policy/ItemReaderRetryPolicy.java index 2c0a7cfb9..907791ea4 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/policy/ItemReaderRetryPolicy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/policy/ItemReaderRetryPolicy.java @@ -19,8 +19,8 @@ package org.springframework.batch.retry.policy; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.batch.item.FailedItemIdentifier; -import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemRecoverer; +import org.springframework.batch.item.KeyedItemReader; import org.springframework.batch.repeat.synch.RepeatSynchronizationManager; import org.springframework.batch.retry.RetryCallback; import org.springframework.batch.retry.RetryContext; @@ -109,7 +109,7 @@ public class ItemReaderRetryPolicy extends AbstractStatefulRetryPolicy { public RetryContext open(RetryCallback callback) { Assert.state(callback instanceof ItemReaderRetryCallback, "Callback must be ItemProviderRetryCallback"); - ItemProviderRetryContext context = new ItemProviderRetryContext( + ItemReaderRetryContext context = new ItemReaderRetryContext( (ItemReaderRetryCallback) callback); context.open(callback); return context; @@ -137,7 +137,7 @@ public class ItemReaderRetryPolicy extends AbstractStatefulRetryPolicy { return ((RetryPolicy) context).handleRetryExhausted(context); } - private class ItemProviderRetryContext extends RetryContextSupport + private class ItemReaderRetryContext extends RetryContextSupport implements RetryPolicy { private Object item; @@ -145,11 +145,11 @@ public class ItemReaderRetryPolicy extends AbstractStatefulRetryPolicy { // The delegate context... private RetryContext delegateContext; - private ItemReader reader; + private KeyedItemReader reader; private ItemRecoverer recoverer; - public ItemProviderRetryContext(ItemReaderRetryCallback callback) { + public ItemReaderRetryContext(ItemReaderRetryCallback callback) { super(RetrySynchronizationManager.getContext()); item = callback.next(this); this.reader = callback.getReader(); @@ -239,7 +239,7 @@ public class ItemReaderRetryPolicy extends AbstractStatefulRetryPolicy { * @param item * @return */ - protected boolean hasFailed(ItemReader provider, Object item) { + protected boolean hasFailed(KeyedItemReader provider, Object item) { if (provider instanceof FailedItemIdentifier) { return ((FailedItemIdentifier) provider).hasFailed(item); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/DelegatingItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/DelegatingItemReaderIntegrationTests.java index b0a8563f4..d5ce02528 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/DelegatingItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/DelegatingItemReaderIntegrationTests.java @@ -41,14 +41,6 @@ public class DelegatingItemReaderIntegrationTests extends AbstractDependencyInje } } - /** - * getKey(..) is implemented trivially. - */ - public void testGetKey() { - Object item = new Object(); - assertSame(item, provider.getKey(item)); - } - public void setProvider(ItemReaderAdapter provider) { this.provider = provider; } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/ListItemReaderRecoverer.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/ListItemReaderRecoverer.java index 89ec8b16c..f41bc01bc 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/ListItemReaderRecoverer.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/ListItemReaderRecoverer.java @@ -18,11 +18,11 @@ package org.springframework.batch.retry; import java.util.List; -import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemRecoverer; +import org.springframework.batch.item.KeyedItemReader; import org.springframework.batch.item.reader.ListItemReader; -public class ListItemReaderRecoverer extends ListItemReader implements ItemReader, ItemRecoverer { +public class ListItemReaderRecoverer extends ListItemReader implements KeyedItemReader, ItemRecoverer { /** * Delegate to super class constructor. @@ -43,5 +43,14 @@ public class ListItemReaderRecoverer extends ListItemReader implements ItemReade public boolean recover(Object item, Throwable cause) { return false; } + + /** + * Return the item (assume it is its own key). + * + * @see org.springframework.batch.item.KeyedItemReader#getKey(java.lang.Object) + */ + public Object getKey(Object item) { + return item; + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/callback/ItemReaderRetryCallbackTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/callback/ItemReaderRetryCallbackTests.java index f95a15ad9..f8a567228 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/callback/ItemReaderRetryCallbackTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/callback/ItemReaderRetryCallbackTests.java @@ -22,7 +22,6 @@ import java.util.List; import junit.framework.TestCase; -import org.springframework.batch.item.reader.ListItemReader; import org.springframework.batch.item.writer.AbstractItemWriter; import org.springframework.batch.retry.ListItemReaderRecoverer; import org.springframework.batch.retry.RetryContext; @@ -40,7 +39,7 @@ public class ItemReaderRetryCallbackTests extends TestCase { RetryTemplate template; - ListItemReader provider; + ListItemReaderRecoverer provider; ItemReaderRetryCallback callback; diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/policy/ItemReaderRetryPolicyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/policy/ItemReaderRetryPolicyTests.java index 7bec2480d..9a9354cb9 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/policy/ItemReaderRetryPolicyTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/policy/ItemReaderRetryPolicyTests.java @@ -24,7 +24,7 @@ import java.util.List; import junit.framework.TestCase; import org.springframework.batch.item.FailedItemIdentifier; -import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.KeyedItemReader; import org.springframework.batch.item.reader.ListItemReader; import org.springframework.batch.item.writer.AbstractItemWriter; import org.springframework.batch.repeat.RepeatContext; @@ -41,7 +41,7 @@ public class ItemReaderRetryPolicyTests extends TestCase { private ItemReaderRetryPolicy policy = new ItemReaderRetryPolicy(); - private ItemReader provider; + private org.springframework.batch.item.KeyedItemReader provider; private int count = 0; @@ -299,7 +299,7 @@ public class ItemReaderRetryPolicyTests extends TestCase { assertTrue(policy.hasFailed(provider, "foo")); } - private static class MockFailedItemProvider extends ListItemReader implements FailedItemIdentifier { + private static class MockFailedItemProvider extends ListItemReader implements KeyedItemReader, FailedItemIdentifier { private int hasFailedCount = 0; diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/item/AbstractItemReaderRecoverer.java b/spring-batch-integration/src/test/java/org/springframework/batch/item/AbstractItemReaderRecoverer.java index 55d7dcd51..c93c1daf1 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/item/AbstractItemReaderRecoverer.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/item/AbstractItemReaderRecoverer.java @@ -21,5 +21,8 @@ import org.springframework.batch.item.reader.AbstractItemReader; * @author Dave Syer * */ -public abstract class AbstractItemReaderRecoverer extends AbstractItemReader implements ItemRecoverer { +public abstract class AbstractItemReaderRecoverer extends AbstractItemReader implements KeyedItemReader, ItemRecoverer { + public Object getKey(Object item) { + return item; + } } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/jms/ExternalRetryInBatchTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/jms/ExternalRetryInBatchTests.java index e133d81f1..df009abda 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/jms/ExternalRetryInBatchTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/jms/ExternalRetryInBatchTests.java @@ -22,7 +22,7 @@ import java.util.List; import javax.sql.DataSource; import org.springframework.batch.item.AbstractItemReaderRecoverer; -import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.KeyedItemReader; import org.springframework.batch.item.writer.AbstractItemWriter; import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.RepeatCallback; @@ -48,7 +48,7 @@ public class ExternalRetryInBatchTests extends AbstractDependencyInjectionSpring private RepeatTemplate repeatTemplate; - private ItemReader provider; + private KeyedItemReader provider; private JdbcTemplate jdbcTemplate; diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/retry/jms/ExternalRetryTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/retry/jms/ExternalRetryTests.java index 99ae1bd36..e73259468 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/retry/jms/ExternalRetryTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/retry/jms/ExternalRetryTests.java @@ -22,7 +22,7 @@ import java.util.List; import javax.sql.DataSource; import org.springframework.batch.item.AbstractItemReaderRecoverer; -import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.KeyedItemReader; import org.springframework.batch.item.writer.AbstractItemWriter; import org.springframework.batch.retry.callback.ItemReaderRetryCallback; import org.springframework.batch.retry.policy.ItemReaderRetryPolicy; @@ -41,7 +41,7 @@ public class ExternalRetryTests extends AbstractDependencyInjectionSpringContext private RetryTemplate retryTemplate; - private ItemReader provider; + private KeyedItemReader provider; private JdbcTemplate jdbcTemplate; 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 9a35e53ba..f58cca01c 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 @@ -11,7 +11,7 @@ import org.apache.commons.logging.Log; 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.ItemReader; +import org.springframework.batch.item.KeyedItemReader; import org.springframework.batch.item.ResourceLifecycle; import org.springframework.batch.repeat.synch.BatchTransactionSynchronizationManager; import org.springframework.batch.sample.item.writer.StagingItemWriter; @@ -26,7 +26,7 @@ import org.springframework.transaction.support.TransactionSynchronizationAdapter import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; -public class StagingItemReader extends JdbcDaoSupport implements ItemReader, ResourceLifecycle, DisposableBean, +public class StagingItemReader extends JdbcDaoSupport implements KeyedItemReader, ResourceLifecycle, DisposableBean, StepContextAware { // Key for buffer in transaction synchronization manager