Updated javadocs where necessary.
This commit is contained in:
@@ -15,15 +15,41 @@
|
||||
*/
|
||||
package org.springframework.batch.core;
|
||||
|
||||
import org.springframework.batch.item.ItemProcessor;
|
||||
|
||||
/**
|
||||
* Listener interface for the processing of an item. Implementations
|
||||
* of this interface will be notified before and after an item is
|
||||
* passed to the {@link ItemProcessor} and in the event of any
|
||||
* exceptions thrown by the processor.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface ItemProcessListener<T, S> extends StepListener {
|
||||
|
||||
/**
|
||||
* Called before {@link ItemProcessor#process(Object)}.
|
||||
*
|
||||
* @param item to be processed.
|
||||
*/
|
||||
void beforeProcess(T item);
|
||||
|
||||
/**
|
||||
* Called after {@link ItemProcessor#process(Object)} returns. If the
|
||||
* processor returns null, this method will still be called, with
|
||||
* a null result, allowing for notification of 'filtered' items.
|
||||
*
|
||||
* @param item to be processed
|
||||
* @param result of processing
|
||||
*/
|
||||
void afterProcess(T item, S result);
|
||||
|
||||
/**
|
||||
* Called if an exception was thrown from {@link ItemProcessor#process(Object)}.
|
||||
*
|
||||
* @param item attempted to be processed
|
||||
* @param e - exception thrown during processing.
|
||||
*/
|
||||
void onProcessError(T item, Exception e);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,9 @@ import java.util.List;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
|
||||
/**
|
||||
* Listener interface around the writing of an item.
|
||||
* Listener interface for the writing of items. Implementations
|
||||
* of this interface will be notified before, after, and in case
|
||||
* of any exception thrown while writing a list of items.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
@@ -35,9 +37,10 @@ public interface ItemWriteListener<S> extends StepListener {
|
||||
void beforeWrite(List<? extends S> items);
|
||||
|
||||
/**
|
||||
* Called after {@link ItemWriter#write(java.util.List)} If the item is last
|
||||
* in a chunk, this will be called before any transaction is committed, and
|
||||
* before {@link ChunkListener#afterChunk()}
|
||||
* Called after {@link ItemWriter#write(java.util.List)} This will be
|
||||
* called before any transaction is committed, and before
|
||||
* {@link ChunkListener#afterChunk()}
|
||||
*
|
||||
* @param items written items
|
||||
*/
|
||||
void afterWrite(List<? extends S> items);
|
||||
|
||||
@@ -162,9 +162,7 @@ public class JobParameters implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of all parameters, including string, long, and date. It should
|
||||
* be noted that a Collections$UnmodifiableMap is returned, ensuring
|
||||
* immutability.
|
||||
* Get a map of all parameters, including string, long, and date.
|
||||
*
|
||||
* @return an unmodifiable map containing all parameters.
|
||||
*/
|
||||
@@ -173,7 +171,7 @@ public class JobParameters implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the prameters is empty, false otherwise.
|
||||
* @return true if the parameters is empty, false otherwise.
|
||||
*/
|
||||
public boolean isEmpty(){
|
||||
return parameters.isEmpty();
|
||||
|
||||
@@ -23,16 +23,17 @@ import java.util.Map;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Helper class for creating {@link JobParameters}. Useful because of all
|
||||
* {@link JobParameters} are immutable, and require 3 separate maps of the three
|
||||
* supported types to ensure typesafety. Once created, it can be used in the
|
||||
* Helper class for creating {@link JobParameters}. Useful because all
|
||||
* {@link JobParameter} objects are immutable, and must be instantiated separately
|
||||
* to ensure typesafety. Once created, it can be used in the
|
||||
* same was a java.lang.StringBuilder (except, order is irrelevant), by adding
|
||||
* various parameters types and creating a valid JobRuntimeParametres once
|
||||
* various parameter types and creating a valid {@link JobParameters} once
|
||||
* finished.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @since 1.0
|
||||
* @see JobParameters
|
||||
* @see JobParameter
|
||||
*/
|
||||
public class JobParametersBuilder {
|
||||
|
||||
@@ -67,7 +68,7 @@ public class JobParametersBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Date parameter for the given key.
|
||||
* Add a new {@link Date} parameter for the given key.
|
||||
*
|
||||
* @param key - parameter accessor.
|
||||
* @param parameter - runtime parameter
|
||||
|
||||
@@ -27,10 +27,8 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Batch domain object representation the execution of a step. Unlike
|
||||
* JobExecution, there are four additional properties: itemCount, commitCount,
|
||||
* rollbackCount and execution context. These values represent how many items
|
||||
* the step has processed, how many times it has been committed and rolled back,
|
||||
* and any other information the developer wishes to store, respectively.
|
||||
* {@link JobExecution}, there are additional properties related the
|
||||
* processing of items such as commit count, etc.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
|
||||
@@ -26,8 +26,9 @@ package org.springframework.batch.core;
|
||||
public interface StepExecutionListener extends StepListener {
|
||||
|
||||
/**
|
||||
* Initialise the state of the listener with the {@link StepExecution} from
|
||||
* Initialize the state of the listener with the {@link StepExecution} from
|
||||
* the current scope.
|
||||
*
|
||||
* @param stepExecution
|
||||
*/
|
||||
void beforeStep(StepExecution stepExecution);
|
||||
|
||||
@@ -16,8 +16,17 @@
|
||||
|
||||
package org.springframework.batch.core.configuration.support;
|
||||
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
/**
|
||||
* Factory for the creation of {@link ApplicationContext}s. This interface
|
||||
* is primarily useful when creating a new {@link ApplicationContext} per
|
||||
* execution of a {@link Job}.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*/
|
||||
public interface ApplicationContextFactory {
|
||||
|
||||
ConfigurableApplicationContext createApplicationContext();
|
||||
|
||||
@@ -24,6 +24,13 @@ import org.springframework.context.support.AbstractXmlApplicationContext;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link ApplicationContextFactory} implementation that takes a parent context and a path
|
||||
* to the context to create. Each time the createApplicationContext method is called, a new
|
||||
* {@link ApplicationContext} will be returned. It should be noted that if a path isn't
|
||||
* set, the parent will always be returned.
|
||||
*
|
||||
*/
|
||||
public class ClassPathXmlApplicationContextFactory implements ApplicationContextFactory, ApplicationContextAware {
|
||||
|
||||
private ConfigurableApplicationContext parent;
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.springframework.batch.core.StepExecution;
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface JobExplorer {
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
* @see MapJobExplorerFactoryBean
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractJobExplorerFactoryBean implements FactoryBean {
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.springframework.util.Assert;
|
||||
* to describe what kind of database they are using.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class JobExplorerFactoryBean extends AbstractJobExplorerFactoryBean
|
||||
implements InitializingBean {
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
* {@link SimpleJobExplorer} using in-memory DAO implementations.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MapJobExplorerFactoryBean extends AbstractJobExplorerFactoryBean {
|
||||
|
||||
|
||||
@@ -29,10 +29,7 @@ import org.springframework.batch.core.repository.dao.JobInstanceDao;
|
||||
import org.springframework.batch.core.repository.dao.StepExecutionDao;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* Implementation of {@link JobExplorer} using the injected DAOs.
|
||||
* <p>
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Lucas Ward
|
||||
|
||||
@@ -45,10 +45,10 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Batch domain object representing a job. Job is an explicit abstraction
|
||||
* representing the configuration of a job specified by a developer. It should
|
||||
* be noted that restart policy is applied to the job as a whole and not to a
|
||||
* step.
|
||||
* Abstract implementation of the {@link Job} interface. Common dependencies such as a
|
||||
* {@link JobRepository}, {@link JobExecutionListener}s, and various configuration
|
||||
* parameters are set here. Therefore, common error handling and listener calling
|
||||
* activities are abstracted away from implementations.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
|
||||
@@ -32,7 +32,8 @@ import org.springframework.batch.core.repository.JobRestartException;
|
||||
/**
|
||||
* Simple implementation of {@link Job} interface providing the ability to run a
|
||||
* {@link JobExecution}. Sequentially executes a job by iterating through its
|
||||
* list of steps.
|
||||
* list of steps. Any {@link Step} that fails will fail the job. The job is
|
||||
* considered complete when all steps have been executed.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface Flow {
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.springframework.batch.core.job.flow;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class FlowExecution implements Comparable<FlowExecution> {
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.batch.core.repository.JobRestartException;
|
||||
* its execution step by step.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface FlowExecutor {
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.HashSet;
|
||||
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.ExitStatus;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobExecutionException;
|
||||
import org.springframework.batch.core.JobInterruptedException;
|
||||
@@ -31,8 +32,13 @@ import org.springframework.batch.core.repository.JobRestartException;
|
||||
import org.springframework.batch.core.step.StepHolder;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* Implementation of the {@link Job} interface that allows for complex flows
|
||||
* of steps, rather than requiring sequential execution. In general, this
|
||||
* job implementation was designed to be used behind a parser, allowing for
|
||||
* a namespace to abstract away details.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class FlowJob extends AbstractJob {
|
||||
|
||||
|
||||
@@ -19,8 +19,13 @@ import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* Interface allowing for programmatic access to the decision on what the status
|
||||
* of a flow should be. For example, if some condition that's stored in the
|
||||
* database indicates that the job should stop for a manual check, a decider
|
||||
* implementation could check that value to determine the status of the flow.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface JobExecutionDecider {
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.batch.core.job.flow;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface State {
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
* if unambiguous.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SimpleFlow implements Flow, InitializingBean {
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.util.StringUtils;
|
||||
* execution of the originating State.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class StateTransition implements Comparable<StateTransition> {
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.springframework.batch.core.job.flow.State;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractState implements State {
|
||||
|
||||
|
||||
@@ -21,8 +21,10 @@ import org.springframework.batch.core.job.flow.FlowExecutor;
|
||||
import org.springframework.batch.core.job.flow.JobExecutionDecider;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* State that requires a decider to make the status decision.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DecisionState extends AbstractState {
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.springframework.batch.core.job.flow.State;
|
||||
* continuing if just starting.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class EndState extends AbstractState {
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.springframework.batch.core.job.flow.FlowExecutionStatus;
|
||||
* single exit status.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface FlowExecutionAggregator {
|
||||
|
||||
|
||||
@@ -22,8 +22,13 @@ import org.springframework.batch.core.job.flow.FlowExecution;
|
||||
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* Implementation of the {@link FlowExecutionAggregator} interface that aggregates
|
||||
* {@link FlowExecutionStatus}', using the status with the high precedence as the
|
||||
* aggregate status. See {@link FlowExecutionStatus} for details on status
|
||||
* precedence.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MaxValueFlowExecutionAggregator implements FlowExecutionAggregator {
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.springframework.core.task.TaskRejectedException;
|
||||
* parallel subflows.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SplitState extends AbstractState {
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.batch.core.step.StepHolder;
|
||||
* execute the specified {@link Step}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class StepState extends AbstractState implements StepHolder {
|
||||
|
||||
|
||||
@@ -18,8 +18,11 @@ package org.springframework.batch.core.launch;
|
||||
import org.springframework.batch.core.JobExecutionException;
|
||||
|
||||
/**
|
||||
* Execution indicating that a JobExecution that is not currently running has
|
||||
* been requested to stop.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class JobExecutionNotRunningException extends JobExecutionException {
|
||||
|
||||
|
||||
@@ -42,7 +42,9 @@ public interface JobLauncher {
|
||||
* always be returned by this method, regardless of whether or not the
|
||||
* execution was successful. If there is a past {@link JobExecution} which
|
||||
* has paused, the same {@link JobExecution} is returned instead of a new
|
||||
* one created.
|
||||
* one created. A exception will only be thrown if there is a failure to
|
||||
* start the job. If the job encounters some error while processing, the
|
||||
* JobExecution will be returned, and the status will need to be inspected.
|
||||
*
|
||||
* @return the {@link JobExecution} if it returns synchronously. If the
|
||||
* implementation is asynchronous, the status might well be unknown.
|
||||
|
||||
@@ -31,13 +31,13 @@ import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteExcep
|
||||
import org.springframework.batch.core.repository.JobRestartException;
|
||||
|
||||
/**
|
||||
* A really low level interface for inspecting and controlling jobs with access
|
||||
* Low level interface for inspecting and controlling jobs with access
|
||||
* only to primitive and collection types. Suitable for a command-line client
|
||||
* (e.g. that launches a new process for each operation), or a remote launcher
|
||||
* like a JMX console.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface JobOperator {
|
||||
|
||||
|
||||
@@ -28,8 +28,9 @@ package org.springframework.batch.core.launch.support;
|
||||
public class JvmSystemExiter implements SystemExiter {
|
||||
|
||||
/**
|
||||
* Delegate call to System.exit() with the argument provided. Do not use
|
||||
* this at home children!
|
||||
* Delegate call to System.exit() with the argument provided. This should only
|
||||
* be used in a scenario where a particular status needs to be returned to
|
||||
* a Batch scheduler.
|
||||
*
|
||||
* @see org.springframework.batch.core.launch.support.SystemExiter#exit(int)
|
||||
*/
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.JobParametersIncrementer;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.UnexpectedJobExecutionException;
|
||||
import org.springframework.batch.core.configuration.JobRegistry;
|
||||
import org.springframework.batch.core.configuration.ListableJobRegistry;
|
||||
import org.springframework.batch.core.converter.DefaultJobParametersConverter;
|
||||
import org.springframework.batch.core.converter.JobParametersConverter;
|
||||
@@ -55,9 +56,20 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple implementation of the JobOperator interface. Due to the amount of
|
||||
* functionality the implementation is combining, the following dependencies
|
||||
* are required:
|
||||
*
|
||||
* <ul>
|
||||
* <li> {@link JobLauncher}
|
||||
* <li> {@link JobExplorer}
|
||||
* <li> {@link JobRepository}
|
||||
* <li> {@link JobRegistry}
|
||||
* </ul>
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Lucas Ward
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SimpleJobOperator implements JobOperator, InitializingBean {
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.batch.item.ExecutionContext;
|
||||
* caller.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface PartitionHandler {
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.batch.core.StepExecution;
|
||||
* execution independent from the fabric they are going to run on.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface StepExecutionSplitter {
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.springframework.util.Assert;
|
||||
* ignored.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MultiResourcePartitioner implements Partitioner {
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.springframework.util.Assert;
|
||||
* load using a {@link PartitionHandler}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PartitionStep extends AbstractStep {
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.batch.item.ExecutionContext;
|
||||
* key ranges, or a set of unique filenames.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface Partitioner {
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.batch.item.ExecutionContext;
|
||||
* size.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SimplePartitioner implements Partitioner {
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ import org.springframework.batch.item.ExecutionContext;
|
||||
* <code>{step1:partition0, step1:partition1, ...}</code>.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SimpleStepExecutionSplitter implements StepExecutionSplitter {
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.util.Assert;
|
||||
* into a single result.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class StepExecutionAggregator {
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ import org.springframework.util.Assert;
|
||||
* filesystem scanning and copying.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class TaskExecutorPartitionHandler implements PartitionHandler, InitializingBean {
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.springframework.transaction.annotation.Isolation;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Repository responsible for persistence of batch metadata entities.
|
||||
* Repository responsible for persistence of batch meta-data entities.
|
||||
* </p>
|
||||
*
|
||||
* @see JobInstance
|
||||
|
||||
@@ -19,8 +19,7 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.StepExecutionListener;
|
||||
import org.springframework.batch.item.database.JdbcCursorItemReader;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jdbc.core.PreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.SqlTypeValue;
|
||||
@@ -28,9 +27,13 @@ import org.springframework.jdbc.core.StatementCreatorUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link PreparedStatementSetter} interface that also
|
||||
* implements {@link StepExecutionListener} and uses {@link JobParameters} to
|
||||
* set the parameters on a PreparedStatement.
|
||||
* Implementation of the {@link PreparedStatementSetter} interface that accepts
|
||||
* a list of values to be set on a PreparedStatement. This is usually used in
|
||||
* conjunction with the {@link JdbcCursorItemReader} to allow for the replacement
|
||||
* of bind variables when generating the cursor. The order of the list will be
|
||||
* used to determine the ordering of setting variables. For example, the first
|
||||
* item in the list will be the first bind variable set. (i.e. it will
|
||||
* correspond to the first '?' in the SQL statement)
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
@@ -38,24 +41,24 @@ import org.springframework.util.Assert;
|
||||
public class ListPreparedStatementSetter implements
|
||||
PreparedStatementSetter, InitializingBean {
|
||||
|
||||
private List<?> parameterKeys;
|
||||
private List<?> parameters;
|
||||
|
||||
public void setValues(PreparedStatement ps) throws SQLException {
|
||||
for (int i = 0; i < parameterKeys.size(); i++) {
|
||||
StatementCreatorUtils.setParameterValue(ps, i + 1, SqlTypeValue.TYPE_UNKNOWN, parameterKeys.get(i));
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
StatementCreatorUtils.setParameterValue(ps, i + 1, SqlTypeValue.TYPE_UNKNOWN, parameters.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameter names that will be pulled from the {@link JobParameters}.
|
||||
* The parameter values that will be set on the PreparedStatement.
|
||||
* It is assumed that their order in the List is the order of the parameters
|
||||
* in the PreparedStatement.
|
||||
*/
|
||||
public void setParameters(List<?> parameterKeys) {
|
||||
this.parameterKeys = parameterKeys;
|
||||
public void setParameters(List<?> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(parameterKeys, "Parameters names must be provided");
|
||||
Assert.notNull(parameters, "Parameters must be provided");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ import org.springframework.util.StringValueResolver;
|
||||
* accessors provided as a convenience for step and job attributes.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered {
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.springframework.batch.core.Step;
|
||||
* access to the underlying instance.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface StepHolder {
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.List;
|
||||
* skipped items are then available through the chunk.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class Chunk<W> implements Iterable<W> {
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.springframework.batch.item.ItemStreamException;
|
||||
* and the wrapped {@link ItemStream}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
class ChunkMonitor implements ItemStream {
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@ package org.springframework.batch.core.step.item;
|
||||
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
|
||||
/**
|
||||
* Interface defined for processing {@link Chunk}s.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface ChunkProcessor<I> {
|
||||
|
||||
void process(StepContribution contribution, Chunk<I> chunk) throws Exception;
|
||||
|
||||
@@ -18,6 +18,13 @@ package org.springframework.batch.core.step.item;
|
||||
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
|
||||
/**
|
||||
* Interface for providing {@link Chunk}s to be processed, used by the
|
||||
* {@link ChunkOrientedTasklet}
|
||||
*
|
||||
* @since 2.0
|
||||
* @see ChunkOrientedTasklet
|
||||
*/
|
||||
public interface ChunkProvider<T> {
|
||||
|
||||
Chunk<T> provide(StepContribution contribution) throws Exception;
|
||||
|
||||
@@ -37,6 +37,11 @@ import org.springframework.batch.retry.RetryContext;
|
||||
import org.springframework.batch.retry.RetryException;
|
||||
import org.springframework.batch.retry.support.DefaultRetryState;
|
||||
|
||||
/**
|
||||
* FaultTolerant implementation of the {@link ChunkProcessor} interface, that
|
||||
* allows for skipping or retry of items that cause exceptions during writing.
|
||||
*
|
||||
*/
|
||||
public class FaultTolerantChunkProcessor<I, O> extends SimpleChunkProcessor<I, O> {
|
||||
|
||||
private SkipPolicy itemProcessSkipPolicy = new LimitCheckingItemSkipPolicy(0);
|
||||
|
||||
@@ -24,6 +24,12 @@ import org.springframework.batch.core.step.skip.SkipPolicy;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.repeat.RepeatOperations;
|
||||
|
||||
/**
|
||||
* FaultTolerant implementation of the {@link ChunkProcessor} interface, that
|
||||
* allows for skipping or retry of items that cause exceptions during reading
|
||||
* or processing.
|
||||
*
|
||||
*/
|
||||
public class FaultTolerantChunkProvider<I> extends SimpleChunkProvider<I> {
|
||||
|
||||
private SkipPolicy skipPolicy = new LimitCheckingItemSkipPolicy(0);
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
package org.springframework.batch.core.step.item;
|
||||
|
||||
/**
|
||||
* Interface for defining keys to uniquely identify items.
|
||||
* this can be useful if the item itself cannot be modified to
|
||||
* properly override equals.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.springframework.batch.item.UnexpectedInputException;
|
||||
|
||||
/**
|
||||
* Convenience wrapper for an ItemReader that keeps track of how many items
|
||||
* successfully processed.
|
||||
* were successfully processed.
|
||||
*/
|
||||
class OffsetItemReader<T> implements ItemReader<T>, ItemStream {
|
||||
|
||||
|
||||
@@ -26,6 +26,12 @@ import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple implementation of the {@link ChunkProcessor} interface that handles basic
|
||||
* item writing and processing. Any exceptions encountered will be rethrown.
|
||||
*
|
||||
* @see ChunkOrientedTasklet
|
||||
*/
|
||||
public class SimpleChunkProcessor<I, O> implements ChunkProcessor<I>, InitializingBean {
|
||||
|
||||
private ItemProcessor<? super I, ? extends O> itemProcessor;
|
||||
|
||||
@@ -30,10 +30,11 @@ import org.springframework.batch.repeat.RepeatOperations;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
|
||||
/**
|
||||
* Simple implementation of the ChunkProvider interface that does basic
|
||||
* chunk providing from an {@link ItemReader}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @param <I> input item type
|
||||
* @see ChunkOrientedTasklet
|
||||
*/
|
||||
public class SimpleChunkProvider<I> implements ChunkProvider<I> {
|
||||
|
||||
|
||||
@@ -230,6 +230,40 @@ public class FaultTolerantStepFactoryBeanTests {
|
||||
.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessFilter() throws Exception {
|
||||
|
||||
reader = new SkipReaderStub(new String[] { "1", "2", "3", "4", "5" }, NO_FAILURES);
|
||||
factory.setItemReader(reader);
|
||||
writer = new SkipWriterStub(NO_FAILURES);
|
||||
factory.setItemWriter(writer);
|
||||
FilterProcessorStub processor = new FilterProcessorStub(Arrays.asList(new String[] { "4" }));
|
||||
factory.setItemProcessor(processor);
|
||||
ItemProcessListenerStub<String, String> listenerStub = new ItemProcessListenerStub<String, String>();
|
||||
factory.setListeners(new StepListener[]{listenerStub});
|
||||
Step step = (Step) factory.getObject();
|
||||
|
||||
step.execute(stepExecution);
|
||||
|
||||
assertEquals(0, stepExecution.getSkipCount());
|
||||
assertEquals(0, stepExecution.getReadSkipCount());
|
||||
assertEquals(5, stepExecution.getReadCount());
|
||||
assertEquals(1, stepExecution.getFilterCount());
|
||||
assertEquals(0, stepExecution.getRollbackCount());
|
||||
assertTrue(listenerStub.isFilterEncountered());
|
||||
|
||||
// writer skips "4"
|
||||
assertTrue(reader.processed.contains("4"));
|
||||
assertFalse(writer.written.contains("4"));
|
||||
|
||||
List<String> expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5"));
|
||||
assertEquals(expectedOutput, writer.written);
|
||||
|
||||
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
|
||||
assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step
|
||||
.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check items causing errors are skipped as expected.
|
||||
*/
|
||||
@@ -683,6 +717,22 @@ public class FaultTolerantStepFactoryBeanTests {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class FilterProcessorStub implements ItemProcessor<String, String> {
|
||||
private final Collection<String> failures;
|
||||
|
||||
public FilterProcessorStub(Collection<String> failures) {
|
||||
this.failures = failures;
|
||||
}
|
||||
|
||||
public String process(String item) throws Exception {
|
||||
if (failures.contains(item)) {
|
||||
return null;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple item reader that supports skip functionality.
|
||||
@@ -725,6 +775,34 @@ public class FaultTolerantStepFactoryBeanTests {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ItemProcessListenerStub<T,S> implements ItemProcessListener<T, S>{
|
||||
|
||||
private boolean errorEncountered = false;
|
||||
private boolean filterEncountered = false;
|
||||
|
||||
public void afterProcess(T item, S result) {
|
||||
if(result == null){
|
||||
filterEncountered = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void beforeProcess(T item) {
|
||||
|
||||
}
|
||||
|
||||
public void onProcessError(T item, Exception e) {
|
||||
errorEncountered = true;
|
||||
}
|
||||
|
||||
public boolean isErrorEncountered() {
|
||||
return errorEncountered;
|
||||
}
|
||||
|
||||
public boolean isFilterEncountered() {
|
||||
return filterEncountered;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple item writer that supports skip functionality.
|
||||
|
||||
Reference in New Issue
Block a user