BATCH-1913: add javadocs and some more convenience methods
This commit is contained in:
@@ -391,7 +391,7 @@ class StepParserStepFactoryBean<I, O> implements FactoryBean, BeanNameAware {
|
||||
builder.reader(itemReader);
|
||||
builder.writer(itemWriter);
|
||||
builder.processor(itemProcessor);
|
||||
builder.completionPolicy(chunkCompletionPolicy);
|
||||
builder.chunk(chunkCompletionPolicy);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.core.step.builder;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.batch.core.ChunkListener;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
import org.springframework.batch.core.step.tasklet.TaskletStep;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
@@ -16,6 +32,16 @@ import org.springframework.core.task.SyncTaskExecutor;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
|
||||
/**
|
||||
* Base class for step builders that want to build a {@link TaskletStep}. Handles common concerns across all tasklet
|
||||
* step variants, which are mostly to do with the type of tasklet they carry.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @param <B> the type of builder represented
|
||||
*/
|
||||
public abstract class AbstractTaskletStepBuilder<B extends AbstractTaskletStepBuilder<B>> extends
|
||||
StepBuilderHelper<AbstractTaskletStepBuilder<B>> {
|
||||
|
||||
@@ -39,6 +65,12 @@ public abstract class AbstractTaskletStepBuilder<B extends AbstractTaskletStepBu
|
||||
|
||||
protected abstract Tasklet createTasklet();
|
||||
|
||||
/**
|
||||
* Build the step from the components collected by the fluent setters. Delegates first to {@link #enhance(Step)} and
|
||||
* then to {@link #createTasklet()} in subclasses to create the actual tasklet.
|
||||
*
|
||||
* @return a tasklet step fully configured and read to execute
|
||||
*/
|
||||
public TaskletStep build() {
|
||||
|
||||
TaskletStep step = new TaskletStep(getName());
|
||||
@@ -68,66 +100,124 @@ public abstract class AbstractTaskletStepBuilder<B extends AbstractTaskletStepBu
|
||||
step.setStepOperations(stepOperations);
|
||||
step.setTasklet(createTasklet());
|
||||
|
||||
step.setStreams(getStreams());
|
||||
|
||||
step.setStreams(streams.toArray(new ItemStream[0]));
|
||||
|
||||
try {
|
||||
step.afterPropertiesSet();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
throw new StepBuilderException(e);
|
||||
}
|
||||
|
||||
return step;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a chunk listener.
|
||||
*
|
||||
* @param listener the listener to register
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public AbstractTaskletStepBuilder<B> listener(ChunkListener listener) {
|
||||
listeners.add(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a stream for callbacks that manage restart data.
|
||||
*
|
||||
* @param stream the stream to register
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public AbstractTaskletStepBuilder<B> stream(ItemStream stream) {
|
||||
streams.add(stream);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a task executor to use when executing the tasklet. Default is to use a single-threaded (synchronous)
|
||||
* executor.
|
||||
*
|
||||
* @param taskExecutor the task executor to register
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public AbstractTaskletStepBuilder<B> taskExecutor(TaskExecutor taskExecutor) {
|
||||
this.taskExecutor = taskExecutor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* In the case of an asynchronous {@link #taskExecutor(TaskExecutor)} the number of concurrent tasklet executions
|
||||
* can be throttled (beyond any throttling provided by a thread pool). The throttle limit should be less than the
|
||||
* data source pool size used in the job repository for this step.
|
||||
*
|
||||
* @param throttleLimit maximium number of concurrent tasklet executions allowed
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public AbstractTaskletStepBuilder<B> throttleLimit(int throttleLimit) {
|
||||
this.throttleLimit = throttleLimit;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the exception handler to use in the case of tasklet failures. Default is to rethrow everything.
|
||||
*
|
||||
* @param exceptionHandler the exception handler
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public AbstractTaskletStepBuilder<B> exceptionHandler(ExceptionHandler exceptionHandler) {
|
||||
this.exceptionHandler = exceptionHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the repeat template used for iterating the tasklet execution. By default it will terminate only when the
|
||||
* tasklet returns FINISHED (or null).
|
||||
*
|
||||
* @param repeatTemplate a repeat template with rules for iterating
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public AbstractTaskletStepBuilder<B> stepOperations(RepeatOperations repeatTemplate) {
|
||||
this.stepOperations = repeatTemplate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transaction attributes for the tasklet execution. Defaults to the default values for the transaction
|
||||
* manager, but can be manipulated to provide longer timeouts for instance.
|
||||
*
|
||||
* @param transactionAttribute a transaction attribute set
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public AbstractTaskletStepBuilder<B> transactionAttribute(TransactionAttribute transactionAttribute) {
|
||||
this.transactionAttribute = transactionAttribute;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected ItemStream[] getStreams() {
|
||||
return streams.toArray(new ItemStream[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for subclasses to access the step operations that were injected by user.
|
||||
*
|
||||
* @return the repeat operations used to iterate the tasklet executions
|
||||
*/
|
||||
protected RepeatOperations getStepOperations() {
|
||||
return stepOperations;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method for subclasses to access the exception handler that was injected by user.
|
||||
*
|
||||
* @return the exception handler
|
||||
*/
|
||||
protected ExceptionHandler getExceptionHandler() {
|
||||
return exceptionHandler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method for subclasses to determine if the step is concurrent.
|
||||
*
|
||||
* @return true if the tasklet is going to be run in multiple threads
|
||||
*/
|
||||
protected boolean concurrent() {
|
||||
boolean concurrent = taskExecutor != null && !(taskExecutor instanceof SyncTaskExecutor);
|
||||
return concurrent;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2011 the original author or authors.
|
||||
* Copyright 2006-2012 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.
|
||||
@@ -71,8 +71,12 @@ import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A step builder for fully fault tolerant chunk-oriented item processing steps. Extends {@link SimpleStepBuilder} with
|
||||
* additional properties for retry and skip of failed items.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class FaultTolerantStepBuilder<I, O> extends SimpleStepBuilder<I, O> {
|
||||
|
||||
@@ -110,10 +114,29 @@ public class FaultTolerantStepBuilder<I, O> extends SimpleStepBuilder<I, O> {
|
||||
|
||||
private boolean processorTransactional = true;
|
||||
|
||||
/**
|
||||
* Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
|
||||
*
|
||||
* @param parent a parent helper containing common step properties
|
||||
*/
|
||||
public FaultTolerantStepBuilder(StepBuilderHelper<?> parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
|
||||
*
|
||||
* @param parent a parent helper containing common step properties
|
||||
*/
|
||||
protected FaultTolerantStepBuilder(SimpleStepBuilder<I, O> parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new chunk oriented tasklet with reader, writer and processor as provided.
|
||||
*
|
||||
* @see org.springframework.batch.core.step.builder.SimpleStepBuilder#createTasklet()
|
||||
*/
|
||||
@Override
|
||||
protected Tasklet createTasklet() {
|
||||
Assert.state(getReader() != null, "ItemReader must be provided");
|
||||
@@ -127,6 +150,12 @@ public class FaultTolerantStepBuilder<I, O> extends SimpleStepBuilder<I, O> {
|
||||
return tasklet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a skip listener.
|
||||
*
|
||||
* @param listener the listener to register
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> listener(SkipListener<? super I, ? super O> listener) {
|
||||
skipListeners.add(listener);
|
||||
return this;
|
||||
@@ -137,78 +166,177 @@ public class FaultTolerantStepBuilder<I, O> extends SimpleStepBuilder<I, O> {
|
||||
super.listener(new TerminateOnExceptionChunkListenerDelegate(listener));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractTaskletStepBuilder<SimpleStepBuilder<I, O>> transactionAttribute(
|
||||
TransactionAttribute transactionAttribute) {
|
||||
return super.transactionAttribute(getTransactionAttribute(transactionAttribute));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register a retry listener.
|
||||
*
|
||||
* @param listener the listener to register
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> listener(RetryListener listener) {
|
||||
retryListeners.add(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key generator for identifying retried items. Retry across transaction boundaries requires items to be
|
||||
* identified when they are encountered again. The default strategy is to use the items themselves, relying on their
|
||||
* own implementation to ensure that they can be identified. Often a key generator is not necessary as long as the
|
||||
* items have reliable hash code and equals implementations, or the reader is not transactional (the default) and
|
||||
* the item processor either is itself not transactional (not the default) or does not create new items.
|
||||
*
|
||||
* @param keyGenerator a key generator for the stateful retry
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> keyGenerator(KeyGenerator keyGenerator) {
|
||||
this.keyGenerator = keyGenerator;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The maximum number of times to try a failed item. Zero and one both translate to try only once and do not retry.
|
||||
* Ignored if an explicit {@link #retryPolicy} is set.
|
||||
*
|
||||
* @param retryLimit the retry limit (default 0)
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> retryLimit(int retryLimit) {
|
||||
this.retryLimit = retryLimit;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provide an explicit retry policy instead of using the {@link #retryLimit(int)} and retryable exceptions provided
|
||||
* elsewhere. Can be used to retry different exceptions a different number of times, for instance.
|
||||
*
|
||||
* @param retryPolicy a retry policy
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> retryPolicy(RetryPolicy retryPolicy) {
|
||||
this.retryPolicy = retryPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provide a backoff policy to prevent items being retried immediately (e.g. in case the failure was caused by a
|
||||
* remote resource failure that might take some time to be resolved). Ignored if an explicit {@link #retryPolicy} is
|
||||
* set.
|
||||
*
|
||||
* @param backOffPolicy the back off policy to use (default no backoff)
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> backOffPolicy(BackOffPolicy backOffPolicy) {
|
||||
this.backOffPolicy = backOffPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provide an explicit retry context cache. Retry is stateful across transactions in the case of failures in item
|
||||
* processing or writing, so some information about the context for subsequent retries has to be stored.
|
||||
*
|
||||
* @param retryContextCache cache for retry contexts in between transactions (default to standard in-memory
|
||||
* implementation)
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> retryContextCache(RetryContextCache retryContextCache) {
|
||||
this.retryContextCache = retryContextCache;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the maximium number of failed items to skip before the step fails. Ignored if an explicit
|
||||
* {@link #skipPolicy(SkipPolicy)} is provided.
|
||||
*
|
||||
* @param skipLimit the skip limit to set
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> skipLimit(int skipLimit) {
|
||||
this.skipLimit = skipLimit;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FaultTolerantStepBuilder<I, O> skipPolicy(SkipPolicy skipPolicy) {
|
||||
this.skipPolicy = skipPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FaultTolerantStepBuilder<I, O> noRollback(Class<? extends Throwable> type) {
|
||||
noRollbackExceptionClasses.add(type);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FaultTolerantStepBuilder<I, O> noRetry(Class<? extends Throwable> type) {
|
||||
retryableExceptionClasses.put(type, false);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FaultTolerantStepBuilder<I, O> retry(Class<? extends Throwable> type) {
|
||||
retryableExceptionClasses.put(type, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly prevent certain exceptions (and subclasses) from being skipped.
|
||||
*
|
||||
* @param type the non-skippable exception
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> noSkip(Class<? extends Throwable> type) {
|
||||
skippableExceptionClasses.put(type, false);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly request certain exceptions (and subclasses) to be skipped.
|
||||
*
|
||||
* @param type
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> skip(Class<? extends Throwable> type) {
|
||||
skippableExceptionClasses.put(type, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provide an explicit policy for managing skips. A skip policy determines which exceptions are skippable and how
|
||||
* many times.
|
||||
*
|
||||
* @param skipPolicy the skip policy
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> skipPolicy(SkipPolicy skipPolicy) {
|
||||
this.skipPolicy = skipPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this exception as ignorable during item read or processing operations. Processing continues with no
|
||||
* additional callbacks (use skips instead if you need to be notified). Ignored during write because there is no
|
||||
* guarantee of skip and retry without rollback.
|
||||
*
|
||||
* @param type the exception to mark as no rollback
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> noRollback(Class<? extends Throwable> type) {
|
||||
noRollbackExceptionClasses.add(type);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly ask for an exception (and subclasses) to be excluded from retry.
|
||||
*
|
||||
* @param type the exception to exclude from retry
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> noRetry(Class<? extends Throwable> type) {
|
||||
retryableExceptionClasses.put(type, false);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly ask for an exception (and subclasses) to be retried.
|
||||
*
|
||||
* @param type the exception to retry
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> retry(Class<? extends Throwable> type) {
|
||||
retryableExceptionClasses.put(type, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the item processor as non-transactional (default is the opposite). If this flag is set the results of item
|
||||
* processing are cached across transactions in between retries and during skip processing, otherwise the processor
|
||||
* will be called in every transaction.
|
||||
*
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FaultTolerantStepBuilder<I, O> processorNonTransactional() {
|
||||
this.processorTransactional = false;
|
||||
return this;
|
||||
@@ -224,8 +352,9 @@ public class FaultTolerantStepBuilder<I, O> extends SimpleStepBuilder<I, O> {
|
||||
// In cases where multiple nested item readers are registered,
|
||||
// they all want to get the open() and close() callbacks.
|
||||
chunkMonitor.registerItemStream(stream);
|
||||
} else {
|
||||
super.stream(stream);
|
||||
}
|
||||
else {
|
||||
super.stream(stream);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -263,7 +392,7 @@ public class FaultTolerantStepBuilder<I, O> extends SimpleStepBuilder<I, O> {
|
||||
chunkProcessor.setRollbackClassifier(getRollbackClassifier());
|
||||
chunkProcessor.setKeyGenerator(keyGenerator);
|
||||
detectStreamInReader();
|
||||
|
||||
|
||||
ArrayList<StepListener> listeners = new ArrayList<StepListener>(getItemListeners());
|
||||
listeners.addAll(skipListeners);
|
||||
chunkProcessor.setListeners(listeners);
|
||||
@@ -367,7 +496,7 @@ public class FaultTolerantStepBuilder<I, O> extends SimpleStepBuilder<I, O> {
|
||||
Map<Class<? extends Throwable>, Boolean> map = new HashMap<Class<? extends Throwable>, Boolean>(
|
||||
skippableExceptionClasses);
|
||||
map.put(ForceRollbackForWriteSkipException.class, true);
|
||||
LimitCheckingItemSkipPolicy limitCheckingItemSkipPolicy = new LimitCheckingItemSkipPolicy(skipLimit , map);
|
||||
LimitCheckingItemSkipPolicy limitCheckingItemSkipPolicy = new LimitCheckingItemSkipPolicy(skipLimit, map);
|
||||
if (skipPolicy == null) {
|
||||
Assert.state(!(skippableExceptionClasses.isEmpty() && skipLimit > 0),
|
||||
"If a skip limit is provided then skippable exceptions must also be specified");
|
||||
|
||||
@@ -20,22 +20,43 @@ import org.springframework.batch.core.job.flow.Flow;
|
||||
import org.springframework.batch.core.job.flow.FlowStep;
|
||||
|
||||
/**
|
||||
* A step builder for {@link FlowStep} instances. A flow step delegates processing to a nested flow composed of other
|
||||
* steps.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class FlowStepBuilder extends StepBuilderHelper<FlowStepBuilder> {
|
||||
|
||||
private Flow flow;
|
||||
|
||||
/**
|
||||
* Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
|
||||
*
|
||||
* @param parent a parent helper containing common step properties
|
||||
*/
|
||||
public FlowStepBuilder(StepBuilderHelper<?> parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a flow to execute during the step.
|
||||
*
|
||||
* @param flow the flow to execute
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public FlowStepBuilder flow(Flow flow) {
|
||||
this.flow = flow;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a step that executes the flow provided, normally composed of other steps. The flow is not executed in a
|
||||
* transaction because the individual steps are supposed to manage their own transaction state.
|
||||
*
|
||||
* @return a flow step
|
||||
*/
|
||||
public Step build() {
|
||||
FlowStep step = new FlowStep();
|
||||
step.setName(getName());
|
||||
@@ -45,7 +66,7 @@ public class FlowStepBuilder extends StepBuilderHelper<FlowStepBuilder> {
|
||||
step.afterPropertiesSet();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
throw new StepBuilderException(e);
|
||||
}
|
||||
return step;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,12 @@ import org.springframework.batch.core.step.job.JobParametersExtractor;
|
||||
import org.springframework.batch.core.step.job.JobStep;
|
||||
|
||||
/**
|
||||
* A step builder for {@link JobStep} instances. A job step executes a nested {@link Job} with parameters taken from the
|
||||
* parent job or from the step execution.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class JobStepBuilder extends StepBuilderHelper<JobStepBuilder> {
|
||||
|
||||
@@ -34,25 +38,54 @@ public class JobStepBuilder extends StepBuilderHelper<JobStepBuilder> {
|
||||
|
||||
private JobParametersExtractor jobParametersExtractor;
|
||||
|
||||
/**
|
||||
* Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
|
||||
*
|
||||
* @param parent a parent helper containing common step properties
|
||||
*/
|
||||
public JobStepBuilder(StepBuilderHelper<?> parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a job to execute during the step.
|
||||
*
|
||||
* @param job the job to execute
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public JobStepBuilder job(Job job) {
|
||||
this.job = job;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a job launcher. Defaults to a simple job launcher.
|
||||
*
|
||||
* @param jobLauncher the job launcher to use
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public JobStepBuilder launcher(JobLauncher jobLauncher) {
|
||||
this.jobLauncher = jobLauncher;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a job parameters extractor. Useful for extracting job parameters from the parent step execution context
|
||||
* or job parameters.
|
||||
*
|
||||
* @param jobParametersExtractor the job parameters extractor to use
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public JobStepBuilder parametersExtractor(JobParametersExtractor jobParametersExtractor) {
|
||||
this.jobParametersExtractor = jobParametersExtractor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a step from the job provided.
|
||||
*
|
||||
* @return a new job step
|
||||
*/
|
||||
public Step build() {
|
||||
|
||||
JobStep step = new JobStep();
|
||||
@@ -80,7 +113,7 @@ public class JobStepBuilder extends StepBuilderHelper<JobStepBuilder> {
|
||||
step.afterPropertiesSet();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
throw new StepBuilderException(e);
|
||||
}
|
||||
return step;
|
||||
|
||||
|
||||
@@ -27,8 +27,12 @@ import org.springframework.core.task.SyncTaskExecutor;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
|
||||
/**
|
||||
* Step builder for {@link PartitionStep} instances. A partition step executes the same step (possibly remotely)
|
||||
* multiple times with different input parameters (in the form of execution context). Useful for parallelization.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class PartitionStepBuilder extends StepBuilderHelper<PartitionStepBuilder> {
|
||||
|
||||
@@ -50,36 +54,107 @@ public class PartitionStepBuilder extends StepBuilderHelper<PartitionStepBuilder
|
||||
|
||||
private String stepName;
|
||||
|
||||
/**
|
||||
* Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
|
||||
*
|
||||
* @param parent a parent helper containing common step properties
|
||||
*/
|
||||
public PartitionStepBuilder(StepBuilderHelper<?> parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a partitioner which can be used to create a {@link StepExecutionSplitter}. Use either this or an explicit
|
||||
* {@link #splitter(StepExecutionSplitter)} but not both.
|
||||
*
|
||||
* @param slaveStepName the name of the slave step (used to construct step execution names)
|
||||
* @param partitioner a partitioner to use
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public PartitionStepBuilder partitioner(String slaveStepName, Partitioner partitioner) {
|
||||
this.stepName = slaveStepName;
|
||||
this.partitioner = partitioner;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an actual step instance to execute in parallel. If an explicit
|
||||
* {@link #partitionHandler(PartitionHandler)} is provided, the step is optional and is only used to extract
|
||||
* configuration data (name and other basic properties of a step).
|
||||
*
|
||||
* @param step a step to execute in parallel
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public PartitionStepBuilder step(Step step) {
|
||||
this.step = step;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a task executor to use when constructing a {@link PartitionHandler} from the {@link #step(Step)}. Mainly
|
||||
* used for running a step locally in parallel, but can be used to execute remotely if the step is remote. Not used
|
||||
* if an explicit {@link #partitionHandler(PartitionHandler)} is provided.
|
||||
*
|
||||
* @param taskExecutor a task executor to use when executing steps in parallel
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public PartitionStepBuilder taskExecutor(TaskExecutor taskExecutor) {
|
||||
this.taskExecutor = taskExecutor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an explicit partition handler that will carry out the work of the partition step. The partition handler
|
||||
* is the main SPI for adapting a partition step to a specific distributed computation environment. Optional if you
|
||||
* only need local or remote processing through the Step interface.
|
||||
*
|
||||
* @see #step(Step) for setting up a default handler that works with a local or remote Step
|
||||
*
|
||||
* @param partitionHandler a partition handler
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public PartitionStepBuilder partitionHandler(PartitionHandler partitionHandler) {
|
||||
this.partitionHandler = partitionHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A hint to the {@link #splitter(StepExecutionSplitter)} about how many step executions are required. If running
|
||||
* locally or remotely through a {@link #taskExecutor(TaskExecutor)} determines precisely the number of step
|
||||
* execution sin the first attempt at a partition step execution.
|
||||
*
|
||||
* @param gridSize the grid size
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public PartitionStepBuilder gridSize(int gridSize) {
|
||||
this.gridSize = gridSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an explicit {@link StepExecutionSplitter} instead of having one build from the
|
||||
* {@link #partitioner(String, Partitioner)}. USeful if you need more control over the splitting.
|
||||
*
|
||||
* @param splitter a step execution splitter
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public PartitionStepBuilder splitter(StepExecutionSplitter splitter) {
|
||||
this.splitter = splitter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a step execution aggregator for aggregating partitioned step executions into a single result for the
|
||||
* {@link PartitionStep} itself. Default is a simple implementation that works in most cases.
|
||||
*
|
||||
* @param aggregator a step execution aggregator
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public PartitionStepBuilder aggregator(StepExecutionAggregator aggregator) {
|
||||
this.aggregator = aggregator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Step build() {
|
||||
|
||||
PartitionStep step = new PartitionStep();
|
||||
@@ -100,9 +175,10 @@ public class PartitionStepBuilder extends StepBuilderHelper<PartitionStepBuilder
|
||||
step.setPartitionHandler(partitionHandler);
|
||||
}
|
||||
|
||||
if (splitter!=null) {
|
||||
if (splitter != null) {
|
||||
step.setStepExecutionSplitter(splitter);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
|
||||
boolean allowStartIfComplete = isAllowStartIfComplete();
|
||||
String name = stepName;
|
||||
@@ -126,7 +202,7 @@ public class PartitionStepBuilder extends StepBuilderHelper<PartitionStepBuilder
|
||||
|
||||
}
|
||||
|
||||
if (aggregator!=null) {
|
||||
if (aggregator != null) {
|
||||
step.setStepExecutionAggregator(aggregator);
|
||||
}
|
||||
|
||||
@@ -134,21 +210,11 @@ public class PartitionStepBuilder extends StepBuilderHelper<PartitionStepBuilder
|
||||
step.afterPropertiesSet();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
throw new StepBuilderException(e);
|
||||
}
|
||||
|
||||
return step;
|
||||
|
||||
}
|
||||
|
||||
public PartitionStepBuilder splitter(StepExecutionSplitter splitter) {
|
||||
this.splitter = splitter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PartitionStepBuilder aggregator(StepExecutionAggregator aggregator) {
|
||||
this.aggregator = aggregator;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,8 +42,15 @@ import org.springframework.batch.repeat.support.RepeatTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Step builder for simple item processing (chunk oriented) steps. Items are read and cached in chunks, and then
|
||||
* processed (transformed) and written (optionally either the processor or the writer can be omitted) all in the same
|
||||
* transaction.
|
||||
*
|
||||
* @see FaultTolerantStepBuilder for a step that handles retry and skip of failed items
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class SimpleStepBuilder<I, O> extends AbstractTaskletStepBuilder<SimpleStepBuilder<I, O>> {
|
||||
|
||||
@@ -65,10 +72,42 @@ public class SimpleStepBuilder<I, O> extends AbstractTaskletStepBuilder<SimpleSt
|
||||
|
||||
private boolean readerTransactionalQueue = false;
|
||||
|
||||
/**
|
||||
* Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
|
||||
*
|
||||
* @param parent a parent helper containing common step properties
|
||||
*/
|
||||
public SimpleStepBuilder(StepBuilderHelper<?> parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
|
||||
*
|
||||
* @param parent a parent helper containing common step properties
|
||||
*/
|
||||
protected SimpleStepBuilder(SimpleStepBuilder<I, O> parent) {
|
||||
super(parent);
|
||||
this.chunkSize = parent.chunkSize;
|
||||
this.completionPolicy = parent.completionPolicy;
|
||||
this.chunkOperations = parent.chunkOperations;
|
||||
this.reader = parent.reader;
|
||||
this.writer = parent.writer;
|
||||
this.processor = parent.processor;
|
||||
this.itemListeners = parent.itemListeners;
|
||||
this.readerTransactionalQueue = parent.readerTransactionalQueue;
|
||||
}
|
||||
|
||||
public FaultTolerantStepBuilder<I, O> faultTolerant() {
|
||||
FaultTolerantStepBuilder<I, O> builder = new FaultTolerantStepBuilder<I, O>(this);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a step with the reader, writer, processor as provided.
|
||||
*
|
||||
* @see org.springframework.batch.core.step.builder.AbstractTaskletStepBuilder#build()
|
||||
*/
|
||||
@Override
|
||||
public TaskletStep build() {
|
||||
registerAsStreamsAndListeners(reader, processor, writer);
|
||||
@@ -89,38 +128,14 @@ public class SimpleStepBuilder<I, O> extends AbstractTaskletStepBuilder<SimpleSt
|
||||
return tasklet;
|
||||
}
|
||||
|
||||
public SimpleStepBuilder<I, O> readerIsTransactionalQueue() {
|
||||
this.readerTransactionalQueue = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleStepBuilder<I, O> listener(ItemReadListener<? super I> listener) {
|
||||
itemListeners.add(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleStepBuilder<I, O> listener(ItemWriteListener<? super O> listener) {
|
||||
itemListeners.add(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleStepBuilder<I, O> listener(ItemProcessListener<? super I, ? super O> listener) {
|
||||
itemListeners.add(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleStepBuilder<I, O> chunkOperations(RepeatOperations repeatTemplate) {
|
||||
this.chunkOperations = repeatTemplate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleStepBuilder<I, O> completionPolicy(CompletionPolicy completionPolicy) {
|
||||
Assert.state(chunkSize == 0 || completionPolicy == null,
|
||||
"You must specify either a chunkCompletionPolicy or a commitInterval but not both.");
|
||||
this.completionPolicy = completionPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the chunk size or commit interval for this step. This is the maximum number of items that will be read
|
||||
* before processing starts in a single transaction. Not compatible with {@link #completionPolicy(CompletionPolicy)}
|
||||
* .
|
||||
*
|
||||
* @param chunkSize the chunk size (a.k.a commit interval)
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public SimpleStepBuilder<I, O> chunk(int chunkSize) {
|
||||
Assert.state(completionPolicy == null || chunkSize == 0,
|
||||
"You must specify either a chunkCompletionPolicy or a commitInterval but not both.");
|
||||
@@ -128,26 +143,114 @@ public class SimpleStepBuilder<I, O> extends AbstractTaskletStepBuilder<SimpleSt
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a completion policy for the chunk processing. Items are read until this policy determines that a chunk is
|
||||
* complete, giving more control than with just the {@link #chunk(int) chunk size} (or commit interval).
|
||||
*
|
||||
* @param completionPolicy a completion policy for the chunk
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public SimpleStepBuilder<I, O> chunk(CompletionPolicy completionPolicy) {
|
||||
Assert.state(chunkSize == 0 || completionPolicy == null,
|
||||
"You must specify either a chunkCompletionPolicy or a commitInterval but not both.");
|
||||
this.completionPolicy = completionPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* An item reader that provides a stream of items. Will be automatically registered as a {@link #stream(ItemStream)}
|
||||
* or listener if it implements the corresponding interface. By default assumed to be non-transactional.
|
||||
*
|
||||
* @see #readerTransactionalQueue
|
||||
* @param reader an item reader
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public SimpleStepBuilder<I, O> reader(ItemReader<? extends I> reader) {
|
||||
this.reader = reader;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* An item writer that writes a chunk of items. Will be automatically registered as a {@link #stream(ItemStream)} or
|
||||
* listener if it implements the corresponding interface.
|
||||
*
|
||||
* @param writer an item writer
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public SimpleStepBuilder<I, O> writer(ItemWriter<? super O> writer) {
|
||||
this.writer = writer;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* An item processor that processes or transforms a stream of items. Will be automatically registered as a
|
||||
* {@link #stream(ItemStream)} or listener if it implements the corresponding interface.
|
||||
*
|
||||
* @param processor an item processor
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public SimpleStepBuilder<I, O> processor(ItemProcessor<? super I, ? extends O> processor) {
|
||||
this.processor = processor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a flag to say that the reader is transactional (usually a queue), which is to say that failed items might be
|
||||
* rolled back and re-presented in a subsequent transaction. Default is false, meaning that the items are read
|
||||
* outside a transaction and possibly cached.
|
||||
*
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public SimpleStepBuilder<I, O> readerIsTransactionalQueue() {
|
||||
this.readerTransactionalQueue = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an item reader listener.
|
||||
*
|
||||
* @param listener the listener to register
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public SimpleStepBuilder<I, O> listener(ItemReadListener<? super I> listener) {
|
||||
itemListeners.add(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an item writer listener.
|
||||
*
|
||||
* @param listener the listener to register
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public SimpleStepBuilder<I, O> listener(ItemWriteListener<? super O> listener) {
|
||||
itemListeners.add(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an item processor listener.
|
||||
*
|
||||
* @param listener the listener to register
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public SimpleStepBuilder<I, O> listener(ItemProcessListener<? super I, ? super O> listener) {
|
||||
itemListeners.add(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instead of a {@link #chunk(int) chunk size} or {@link #chunk(CompletionPolicy) completion policy} you can provide
|
||||
* a complete repeat operations instance that handles the iteration over the item reader.
|
||||
*
|
||||
* @param repeatTemplate a cmplete repeat template for the chunk
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public SimpleStepBuilder<I, O> chunkOperations(RepeatOperations repeatTemplate) {
|
||||
this.chunkOperations = repeatTemplate;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected RepeatOperations createChunkOperations() {
|
||||
RepeatOperations repeatOperations = chunkOperations;
|
||||
if (repeatOperations == null) {
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.batch.core.step.builder;
|
||||
|
||||
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.job.flow.Flow;
|
||||
@@ -24,39 +23,93 @@ import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
import org.springframework.batch.repeat.CompletionPolicy;
|
||||
|
||||
/**
|
||||
* Convenient entry point for building all kinds of steps. Use this as a factory for fluent builders of any step.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class StepBuilder extends StepBuilderHelper<StepBuilder> {
|
||||
|
||||
/**
|
||||
* Initialize a step builder for a step with the given name.
|
||||
*
|
||||
* @param name the name of the step
|
||||
*/
|
||||
public StepBuilder(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a step with a custom tasklet, not necessarily item processing.
|
||||
*
|
||||
* @param tasklet a tasklet
|
||||
* @return a {@link TaskletStepBuilder}
|
||||
*/
|
||||
public TaskletStepBuilder tasklet(Tasklet tasklet) {
|
||||
return new TaskletStepBuilder(this).tasklet(tasklet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a step that processes items in chunks with the size provided. To extend the step to being fault tolerant,
|
||||
* call the {@link SimpleStepBuilder#faultTolerant()} method on the builder.
|
||||
*
|
||||
* @param chunkSize the chunk size (commit interval)
|
||||
* @return a {@link SimpleStepBuilder}
|
||||
*/
|
||||
public <I, O> SimpleStepBuilder<I, O> chunk(int chunkSize) {
|
||||
return new SimpleStepBuilder<I, O>(this).chunk(chunkSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a step that processes items in chunks with the completion policy provided. To extend the step to being
|
||||
* fault tolerant, call the {@link SimpleStepBuilder#faultTolerant()} method on the builder.
|
||||
*
|
||||
* @param completionPolicy the completion policy to use to control chunk processing
|
||||
* @return a {@link SimpleStepBuilder}
|
||||
*/
|
||||
public <I, O> SimpleStepBuilder<I, O> chunk(CompletionPolicy completionPolicy) {
|
||||
return new SimpleStepBuilder<I, O>(this).completionPolicy(completionPolicy);
|
||||
return new SimpleStepBuilder<I, O>(this).chunk(completionPolicy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a partition step builder for a remote (or local) step.
|
||||
*
|
||||
* @param stepName the name of the remote or delegate step
|
||||
* @param partitioner a partitioner to be used to construct new step executions
|
||||
* @return a {@link PartitionStepBuilder}
|
||||
*/
|
||||
public PartitionStepBuilder partitioner(String stepName, Partitioner partitioner) {
|
||||
return new PartitionStepBuilder(this).partitioner(stepName, partitioner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a partition step builder for a remote (or local) step.
|
||||
*
|
||||
* @param step the step to execute in parallel
|
||||
* @param partitioner a partitioner to be used to construct new step executions
|
||||
* @return a PartitionStepBuilder
|
||||
*/
|
||||
public PartitionStepBuilder partitioner(Step step) {
|
||||
return new PartitionStepBuilder(this).step(step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new step builder that will execute a job.
|
||||
*
|
||||
* @param job a job to execute
|
||||
* @return a {@link JobStepBuilder}
|
||||
*/
|
||||
public JobStepBuilder job(Job job) {
|
||||
return new JobStepBuilder(this).job(job);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new step builder that will execute a flow.
|
||||
*
|
||||
* @param flow a flow to execute
|
||||
* @return a {@link FlowStepBuilder}
|
||||
*/
|
||||
public FlowStepBuilder flow(Flow flow) {
|
||||
return new FlowStepBuilder(this).flow(flow);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,13 @@
|
||||
*/
|
||||
package org.springframework.batch.core.step.builder;
|
||||
|
||||
/**
|
||||
* Utility exception thrown by builders when they encounter unexpected checked exceptions.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class StepBuilderException extends RuntimeException {
|
||||
|
||||
public StepBuilderException(Exception e) {
|
||||
|
||||
@@ -28,8 +28,12 @@ import org.springframework.batch.core.step.tasklet.TaskletStep;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* A base class and utility for other step builders providing access to common properties like job repository and
|
||||
* transaction manager.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public abstract class StepBuilderHelper<B extends StepBuilderHelper<B>> {
|
||||
|
||||
@@ -42,8 +46,13 @@ public abstract class StepBuilderHelper<B extends StepBuilderHelper<B>> {
|
||||
properties.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
|
||||
*
|
||||
* @param parent a parent helper containing common step properties
|
||||
*/
|
||||
protected StepBuilderHelper(StepBuilderHelper<?> parent) {
|
||||
this.properties = parent.properties;
|
||||
this.properties = new CommonStepProperties(parent.properties);
|
||||
}
|
||||
|
||||
public StepBuilderHelper<B> repository(JobRepository jobRepository) {
|
||||
@@ -127,6 +136,17 @@ public abstract class StepBuilderHelper<B extends StepBuilderHelper<B>> {
|
||||
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
public CommonStepProperties() {
|
||||
}
|
||||
|
||||
public CommonStepProperties(CommonStepProperties properties) {
|
||||
this.name = properties.name;
|
||||
this.startLimit = properties.startLimit;
|
||||
this.allowStartIfComplete = properties.allowStartIfComplete;
|
||||
this.jobRepository = properties.jobRepository;
|
||||
this.transactionManager = properties.transactionManager;
|
||||
}
|
||||
|
||||
public JobRepository getJobRepository() {
|
||||
return jobRepository;
|
||||
}
|
||||
|
||||
@@ -18,17 +18,29 @@ package org.springframework.batch.core.step.builder;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
|
||||
/**
|
||||
* Builder for tasklet step based on a custom tasklet (not item oriented).
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class TaskletStepBuilder extends AbstractTaskletStepBuilder<TaskletStepBuilder> {
|
||||
|
||||
private Tasklet tasklet;
|
||||
|
||||
/**
|
||||
* Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
|
||||
*
|
||||
* @param parent a parent helper containing common step properties
|
||||
*/
|
||||
public TaskletStepBuilder(StepBuilderHelper<?> parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tasklet tehe tasklet to use
|
||||
* @return this for fluent chaining
|
||||
*/
|
||||
public TaskletStepBuilder tasklet(Tasklet tasklet) {
|
||||
this.tasklet = tasklet;
|
||||
return this;
|
||||
|
||||
@@ -473,7 +473,7 @@ public class SimpleStepFactoryBean<T, S> implements FactoryBean, BeanNameAware {
|
||||
builder.startLimit(startLimit);
|
||||
builder.allowStartIfComplete(allowStartIfComplete);
|
||||
builder.chunk(commitInterval);
|
||||
builder.completionPolicy(chunkCompletionPolicy);
|
||||
builder.chunk(chunkCompletionPolicy);
|
||||
builder.chunkOperations(chunkOperations);
|
||||
builder.stepOperations(stepOperations);
|
||||
builder.taskExecutor(taskExecutor);
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.batch.core.partition.support.SimplePartitioner;
|
||||
import org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler;
|
||||
import org.springframework.batch.core.step.JobRepositorySupport;
|
||||
import org.springframework.batch.core.step.StepSupport;
|
||||
import org.springframework.batch.core.step.builder.StepBuilderException;
|
||||
import org.springframework.batch.core.step.item.ChunkOrientedTasklet;
|
||||
import org.springframework.batch.core.step.tasklet.TaskletStep;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
@@ -55,7 +56,7 @@ import org.springframework.transaction.annotation.Propagation;
|
||||
*/
|
||||
public class StepParserStepFactoryBeanTests {
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
@Test(expected = StepBuilderException.class)
|
||||
public void testNothingSet() throws Exception {
|
||||
StepParserStepFactoryBean<Object, Object> fb = new StepParserStepFactoryBean<Object, Object>();
|
||||
fb.getObject();
|
||||
@@ -88,7 +89,7 @@ public class StepParserStepFactoryBeanTests {
|
||||
assertTrue(stepOperations instanceof TaskExecutorRepeatTemplate);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
@Test(expected = StepBuilderException.class)
|
||||
public void testSkipLimitSet() throws Exception {
|
||||
StepParserStepFactoryBean<Object, Object> fb = new StepParserStepFactoryBean<Object, Object>();
|
||||
fb.setName("step");
|
||||
|
||||
Reference in New Issue
Block a user