OPEN - issue BATCH-324: Step as factory for StepExecutor

http://jira.springframework.org/browse/BATCH-324

First pass - added factory method, resolved conflicts and cycles, got tests working.
This commit is contained in:
dsyer
2008-01-29 15:07:53 +00:00
parent 6ad596421b
commit 4da4c073d5
32 changed files with 325 additions and 577 deletions

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.batch.core.domain;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.tasklet.Tasklet;
/**
@@ -56,5 +57,10 @@ public interface Step {
* identifier.
*/
int getStartLimit();
/**
* @return a {@link StepExecutor} that could be used to execute this step
*/
StepExecutor createStepExecutor();
}

View File

@@ -15,23 +15,28 @@
*/
package org.springframework.batch.core.domain;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.beans.factory.BeanNameAware;
/**
* Basic no-op support implementation for use as base class for
* {@link Step}.
* Basic no-op support implementation for use as base class for {@link Step}.
* Implements {@link BeanNameAware} so that if no name is provided explicitly it
* will be inferred from the bean definition in Spring configuration.
*
* @author Dave Syer
*
*/
public class StepSupport implements Step,
BeanNameAware {
public class StepSupport implements Step, BeanNameAware {
private String name;
private int startLimit = Integer.MAX_VALUE;
private Tasklet tasklet;
private boolean allowStartIfComplete;
private boolean saveRestartData = false;
/**
@@ -68,7 +73,7 @@ public class StepSupport implements Step,
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
*/
public void setBeanName(String name) {
if (this.name==null) {
if (this.name == null) {
this.name = name;
}
}
@@ -95,8 +100,7 @@ public class StepSupport implements Step,
/**
* Public setter for the startLimit.
*
* @param startLimit
* the startLimit to set
* @param startLimit the startLimit to set
*/
public void setStartLimit(int startLimit) {
this.startLimit = startLimit;
@@ -114,8 +118,7 @@ public class StepSupport implements Step,
/**
* Public setter for the tasklet.
*
* @param tasklet
* the tasklet to set
* @param tasklet the tasklet to set
*/
public void setTasklet(Tasklet tasklet) {
this.tasklet = tasklet;
@@ -133,8 +136,7 @@ public class StepSupport implements Step,
/**
* Public setter for the shouldAllowStartIfComplete.
*
* @param allowStartIfComplete
* the shouldAllowStartIfComplete to set
* @param allowStartIfComplete the shouldAllowStartIfComplete to set
*/
public void setAllowStartIfComplete(boolean allowStartIfComplete) {
this.allowStartIfComplete = allowStartIfComplete;
@@ -148,4 +150,15 @@ public class StepSupport implements Step,
return saveRestartData;
}
/**
* Not supported but provided so that tests can easily create a step.
*
* @throws UnsupportedOperationException always
*
* @see org.springframework.batch.core.domain.Step#createStepExecutor()
*/
public StepExecutor createStepExecutor() {
throw new UnsupportedOperationException(
"Cannot create a StepExecutor. Use a smarter subclass of StepSupport like a SimpleStep.");
}
}

View File

@@ -31,7 +31,6 @@ import org.springframework.batch.core.domain.StepInstance;
import org.springframework.batch.core.executor.ExitCodeExceptionClassifier;
import org.springframework.batch.core.executor.JobExecutor;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.executor.StepExecutorFactory;
import org.springframework.batch.core.executor.StepInterruptedException;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.execution.step.simple.SimpleExitCodeExceptionClassifier;
@@ -52,8 +51,6 @@ public class DefaultJobExecutor implements JobExecutor {
private JobRepository jobRepository;
private StepExecutorFactory stepExecutorFactory = DEFAULT_STEP_EXECUTOR_FACTORY;
private ExitCodeExceptionClassifier exceptionClassifier = new SimpleExitCodeExceptionClassifier();
/**
@@ -89,8 +86,7 @@ public class DefaultJobExecutor implements JobExecutor {
if (shouldStart(stepInstance, step)) {
startedCount++;
updateStatus(execution, BatchStatus.STARTED);
StepExecutor stepExecutor = stepExecutorFactory
.getExecutor(step);
StepExecutor stepExecutor = step.createStepExecutor();
StepExecution stepExecution = execution.createStepExecution(stepInstance);
status = stepExecutor.process(step,
stepExecution);
@@ -181,18 +177,6 @@ public class DefaultJobExecutor implements JobExecutor {
DEFAULT_STEP_EXECUTOR_FACTORY.setJobRepository(jobRepository);
}
/**
* Setter for injecting a {@link StepExecutorFactory}. The factory is
* responsible for providing a {@link StepExecutor} to execute each step in
* turn. The values returned from the factory are not cached or re-used by
* this implementation.
*
* @param stepExecutorFactory
*/
public void setStepExecutorFactory(StepExecutorFactory stepExecutorFactory) {
this.stepExecutorFactory = stepExecutorFactory;
}
/**
* Public setter for injecting an {@link ExceptionClassifier} that can
* translate exceptions to {@link ExitStatus}.

View File

@@ -1,69 +0,0 @@
/*
* 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.execution.step;
import org.springframework.batch.core.domain.Step;
import org.springframework.batch.core.domain.StepSupport;
import org.springframework.batch.repeat.exception.handler.ExceptionHandler;
import org.springframework.beans.factory.BeanNameAware;
/**
* A {@link Step} implementation that provides common behaviour to
* subclasses. Implements {@link BeanNameAware} so that if no name is provided
* explicitly it will be inferred from the bean definition in Spring
* configuration.
*
* @author Dave Syer
*
*/
public class AbstractStep extends StepSupport {
private int skipLimit = 0;
private ExceptionHandler exceptionHandler;
/**
* Default constructor.
*/
public AbstractStep() {
super();
}
/**
* Convenient constructor for setting only the name property.
* @param name
*/
public AbstractStep(String name) {
super(name);
}
public ExceptionHandler getExceptionHandler() {
return exceptionHandler;
}
public void setExceptionHandler(ExceptionHandler exceptionHandler) {
this.exceptionHandler = exceptionHandler;
}
public void setSkipLimit(int skipLimit) {
this.skipLimit = skipLimit;
}
public int getSkipLimit() {
return skipLimit;
}
}

View File

@@ -1,135 +0,0 @@
/*
* 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.execution.step;
import org.springframework.batch.core.domain.Step;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.executor.StepExecutorFactory;
import org.springframework.batch.execution.step.simple.SimpleStepExecutor;
import org.springframework.batch.repeat.RepeatOperations;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/**
* A {@link StepExecutorFactory} that uses a prototype bean in the application
* context to satisfy the factory contract. If the prototype bean and
* {@link Step} are of known (simple) type, they can be combined to
* add the commit interval information from the step.<br/>
*
* The nominated bean has to be a prototype because its state may be changed
* before it is used, applying values for things like commit interval from the
* {@link Step}.
*
* @author Dave Syer
*
*/
public class PrototypeBeanStepExecutorFactory implements StepExecutorFactory,
BeanFactoryAware, InitializingBean {
private String stepExecutorName = null;
private BeanFactory beanFactory;
/**
* Setter for injected {@link BeanFactory}.
*
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
*/
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
/**
* Assert that if the step executor name is provided, then it is valid and
* is of prototype scope.
*
* @see InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {
// Make an assertion that the bean exists and is of the correct type
Assert
.notNull(beanFactory.getBean(stepExecutorName,
StepExecutor.class),
"Step executor name must correspond to a StepExecutor instance.");
Assert.state(beanFactory.isPrototype(stepExecutorName),
"StepExecutor must be a prototype. Change the scope of the bean named '"
+ stepExecutorName + "' to prototype.");
}
/**
* Locate a {@link StepExecutor} for this configuration, allowing different
* strategies for configuring the inner loop (chunk operations). Try the
* following in this order, until one succeeds. In each case first obtain
* the {@link StepExecutor} referred to by the {@link #stepExecutorName},
* then:
* <ul>
*
* <li>If the {@link StepExecutor} refers to a {@link SimpleStepExecutor},
* and {@link Step} is an instance of
* {@link RepeatOperationsHolder}, then the {@link RepeatOperations} for
* the chunk will be pulled from there directly. This gives maximum
* flexibility for clients to control the properties of the iteration. For
* simple use cases where clients only need to control a few aspects of the
* execution, like the commit interval, this is not necessary.</li>
*
* <li>If the {@link StepExecutor} is a {@link SimpleStepExecutor} and the
* step is a {@link SimpleStep} then this
* implementation modifies the state of the {@link StepExecutor} to set the
* completion policy of the chunk operations. In this case the chunk
* operations cannot be set by the client of this factory.</li>
*
* <li> Use the {@link StepExecutor} directly. </li>
*
* </ul>
* <br/>
*
* @throws IllegalStateException
* if no {@link StepExecutor} can be located.
*
* @see StepExecutorFactory#getExecutor(Step)
*/
public StepExecutor getExecutor(Step step) {
StepExecutor executor = getStepExecutor();
executor.applyConfiguration(step);
return executor;
}
/**
* Setter for the bean name of the {@link StepExecutor} to use. The
* corresponding bean must be prototype scoped, so that its properties can
* be overridden per execution by the {@link Step}.
*
* @param stepExecutor
* the stepExecutor to set
*/
public void setStepExecutorName(String stepExecutorName) {
this.stepExecutorName = stepExecutorName;
}
/**
* Internal convenience method to get a step executor instance.
*
* @return the step executor instance to use.
*/
private StepExecutor getStepExecutor() {
return (StepExecutor) beanFactory.getBean(stepExecutorName,
StepExecutor.class);
}
}

View File

@@ -0,0 +1,121 @@
/*
* 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.execution.step.simple;
import org.springframework.batch.core.domain.Step;
import org.springframework.batch.core.domain.StepSupport;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.repeat.exception.handler.ExceptionHandler;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.Assert;
/**
* A {@link Step} implementation that provides common behaviour to
* subclasses.
*
* @author Dave Syer
*
*/
public abstract class AbstractStep extends StepSupport {
private int skipLimit = 0;
private ExceptionHandler exceptionHandler;
protected JobRepository jobRepository;
protected PlatformTransactionManager transactionManager;
/**
* Default constructor.
*/
public AbstractStep() {
super();
}
/**
* Convenient constructor for setting only the name property.
* @param name
*/
public AbstractStep(String name) {
super(name);
}
public ExceptionHandler getExceptionHandler() {
return exceptionHandler;
}
public void setExceptionHandler(ExceptionHandler exceptionHandler) {
this.exceptionHandler = exceptionHandler;
}
public void setSkipLimit(int skipLimit) {
this.skipLimit = skipLimit;
}
public int getSkipLimit() {
return skipLimit;
}
/**
* Public setter for {@link JobRepository}.
*
* @param jobRepository
* is a mandatory dependence (no default).
*/
public void setJobRepository(JobRepository jobRepository) {
this.jobRepository = jobRepository;
}
/**
* Public setter for the {@link PlatformTransactionManager}.
* @param transactionManager the transaction manager to set
*/
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
/**
* Assert that all mandatory properties are set (the {@link JobRepository}).
*
* @throws Exception
*/
public void afterPropertiesSet() throws Exception {
assertMandatoryProperties();
}
protected void assertMandatoryProperties() {
Assert.notNull(jobRepository, "JobRepository is mandatory");
Assert.notNull(transactionManager, "TransactionManager is mandatory");
}
/**
* Create a {@link SimpleStepExecutor}.
*
* @see org.springframework.batch.core.domain.Step#createStepExecutor()
*/
public StepExecutor createStepExecutor() {
assertMandatoryProperties();
SimpleStepExecutor executor = new SimpleStepExecutor();
executor.setRepository(jobRepository);
executor.applyConfiguration(this);
executor.setTasklet(getTasklet());
executor.setTransactionManager(transactionManager);
return executor;
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.execution.step;
package org.springframework.batch.execution.step.simple;
import org.springframework.batch.core.domain.Step;
import org.springframework.batch.core.executor.StepExecutor;

View File

@@ -14,14 +14,16 @@
* limitations under the License.
*/
package org.springframework.batch.execution.step;
package org.springframework.batch.execution.step.simple;
import org.springframework.batch.core.domain.Step;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.repeat.RepeatOperations;
import org.springframework.util.Assert;
/**
* {@link Step} implementation that allows full step of
* the {@link RepeatOperations} that will be used in the chunk (inner loop).
* {@link Step} implementation that allows full step of the
* {@link RepeatOperations} that will be used in the chunk (inner loop).
*
* @author Lucas Ward
* @author Dave Syer
@@ -31,6 +33,7 @@ public class RepeatOperationsStep extends AbstractStep implements RepeatOperatio
// default chunkOperations is null
private RepeatOperations chunkOperations;
// default stepOperations is null
private RepeatOperations stepOperations;
@@ -54,7 +57,7 @@ public class RepeatOperationsStep extends AbstractStep implements RepeatOperatio
/**
* Public accessor for the stepOperations property.
*
*
* @return the stepOperations
*/
public RepeatOperations getStepOperations() {
@@ -63,11 +66,28 @@ public class RepeatOperationsStep extends AbstractStep implements RepeatOperatio
/**
* Public setter for the {@link RepeatOperations} property.
*
*
* @param stepOperations the stepOperations to set
*/
public void setStepOperations(RepeatOperations stepOperations) {
this.stepOperations = stepOperations;
}
/**
* Create a new {@link SimpleStepExecutor} with the step and chunk
* operations.
*
* @see org.springframework.batch.core.domain.StepSupport#createStepExecutor()
*/
public StepExecutor createStepExecutor() {
Assert.notNull(jobRepository, "JobRepository is mandatory");
SimpleStepExecutor executor = (SimpleStepExecutor) super.createStepExecutor();
if (stepOperations != null) {
executor.setStepOperations(stepOperations);
}
if (chunkOperations != null) {
executor.setChunkOperations(chunkOperations);
}
return executor;
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.batch.execution.step;
package org.springframework.batch.execution.step.simple;
import org.springframework.batch.core.domain.Step;
import org.springframework.batch.core.tasklet.Tasklet;
@@ -28,10 +28,9 @@ import org.springframework.batch.core.tasklet.Tasklet;
*
*/
public class SimpleStep extends AbstractStep {
// default commit interval is one
private int commitInterval = 1;
public SimpleStep() {
super();
}

View File

@@ -33,8 +33,6 @@ import org.springframework.batch.execution.scope.SimpleStepContext;
import org.springframework.batch.execution.scope.StepContext;
import org.springframework.batch.execution.scope.StepScope;
import org.springframework.batch.execution.scope.StepSynchronizationManager;
import org.springframework.batch.execution.step.RepeatOperationsHolder;
import org.springframework.batch.execution.step.SimpleStep;
import org.springframework.batch.io.Skippable;
import org.springframework.batch.io.exception.BatchCriticalException;
import org.springframework.batch.repeat.ExitStatus;
@@ -96,6 +94,8 @@ public class SimpleStepExecutor implements StepExecutor {
private StatisticsService statisticsService = new SimpleStatisticsService();
private Tasklet tasklet;
/**
* Public setter for the {@link StatisticsService}. This will be used to
* create the {@link StepContext}, and hence any component that is a
@@ -172,8 +172,6 @@ public class SimpleStepExecutor implements StepExecutor {
boolean isRestart = stepInstance.getStepExecutionCount() > 0 ? true : false;
Assert.notNull(stepInstance);
final Tasklet module = step.getTasklet();
ExitStatus status = ExitStatus.FAILED;
StepContext parentStepScopeContext = StepSynchronizationManager.getContext();
@@ -191,7 +189,7 @@ public class SimpleStepExecutor implements StepExecutor {
final boolean saveRestartData = step.isSaveRestartData();
if (saveRestartData && isRestart) {
restoreFromRestartData(module, stepInstance.getRestartData());
restoreFromRestartData(tasklet, stepInstance.getRestartData());
}
status = stepOperations.iterate(new RepeatCallback() {
@@ -232,7 +230,7 @@ public class SimpleStepExecutor implements StepExecutor {
stepExecution.apply(contribution);
if (saveRestartData) {
stepInstance.setRestartData(getRestartData(module));
stepInstance.setRestartData(getRestartData(tasklet));
jobRepository.update(stepInstance);
}
jobRepository.saveOrUpdate(stepExecution);
@@ -338,7 +336,7 @@ public class SimpleStepExecutor implements StepExecutor {
}
// check for interruption before each item as well
interruptionPolicy.checkInterrupted(context);
ExitStatus exitStatus = doTaskletProcessing(step.getTasklet(), contribution);
ExitStatus exitStatus = doTaskletProcessing(tasklet, contribution);
contribution.incrementTaskCount();
// check for interruption after each item as well
interruptionPolicy.checkInterrupted(context);
@@ -447,7 +445,6 @@ public class SimpleStepExecutor implements StepExecutor {
RepeatOperationsHolder holder = (RepeatOperationsHolder) step;
RepeatOperations chunkOperations = holder.getChunkOperations();
RepeatOperations stepOperations = holder.getStepOperations();
Assert.state(chunkOperations != null, "Chunk operations obtained from step must be non-null.");
if (chunkOperations != null) {
setChunkOperations(chunkOperations);
@@ -457,7 +454,7 @@ public class SimpleStepExecutor implements StepExecutor {
}
}
else if (step instanceof SimpleStep) {
else if (step instanceof AbstractStep) {
SimpleStep simpleConfiguation = (SimpleStep) step;
if (this.chunkOperations instanceof RepeatTemplate) {
@@ -481,4 +478,11 @@ public class SimpleStepExecutor implements StepExecutor {
}
}
/**
* @param tasklet a {@link Tasklet} to execute when a step is processed
*/
public void setTasklet(Tasklet tasklet) {
this.tasklet = tasklet;
}
}

View File

@@ -19,7 +19,6 @@ import org.springframework.batch.core.domain.Step;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.executor.StepExecutorFactory;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.execution.step.SimpleStep;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
@@ -51,7 +50,7 @@ public class SimpleStepExecutorFactory implements StepExecutorFactory,
public StepExecutor getExecutor(Step step) {
Assert.notNull(jobRepository, "JobRepository cannot be null");
Assert.state(step instanceof SimpleStep,
Assert.state(step instanceof AbstractStep,
"Step must be instance of SimpleStep - found: ["
+ (step == null ? null : step
.getClass()) + "]");

View File

@@ -29,10 +29,8 @@ import org.springframework.batch.core.domain.JobParameters;
import org.springframework.batch.core.domain.Step;
import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.core.domain.StepInstance;
import org.springframework.batch.core.domain.StepSupport;
import org.springframework.batch.core.executor.ExitCodeExceptionClassifier;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.executor.StepExecutorFactory;
import org.springframework.batch.core.executor.StepInterruptedException;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.tasklet.Tasklet;
@@ -41,7 +39,8 @@ import org.springframework.batch.execution.repository.dao.JobDao;
import org.springframework.batch.execution.repository.dao.MapJobDao;
import org.springframework.batch.execution.repository.dao.MapStepDao;
import org.springframework.batch.execution.repository.dao.StepDao;
import org.springframework.batch.execution.step.SimpleStep;
import org.springframework.batch.execution.step.simple.AbstractStep;
import org.springframework.batch.execution.step.simple.SimpleStep;
import org.springframework.batch.io.exception.BatchCriticalException;
import org.springframework.batch.repeat.ExitStatus;
@@ -91,9 +90,9 @@ public class DefaultJobExecutorTests extends TestCase {
private StepExecution stepExecution2;
private StepSupport stepConfiguration1;
private AbstractStep stepConfiguration1;
private StepSupport stepConfiguration2;
private AbstractStep stepConfiguration2;
private Job jobConfiguration;
@@ -112,14 +111,19 @@ public class DefaultJobExecutorTests extends TestCase {
jobExecutor = new DefaultJobExecutor();
jobExecutor.setJobRepository(jobRepository);
jobExecutor.setStepExecutorFactory(new StepExecutorFactory() {
public StepExecutor getExecutor(Step configuration) {
stepConfiguration1 = new SimpleStep("TestStep1") {
public StepExecutor createStepExecutor() {
return defaultStepLifecycle;
}
});
};
stepConfiguration2 = new SimpleStep("TestStep2") {
public StepExecutor createStepExecutor() {
return defaultStepLifecycle;
}
};
stepConfiguration1.setJobRepository(jobRepository);
stepConfiguration2.setJobRepository(jobRepository);
stepConfiguration1 = new SimpleStep("TestStep1");
stepConfiguration2 = new SimpleStep("TestStep2");
List stepConfigurations = new ArrayList();
stepConfigurations.add(stepConfiguration1);
stepConfigurations.add(stepConfiguration2);
@@ -183,25 +187,6 @@ public class DefaultJobExecutorTests extends TestCase {
assertEquals(step2, stepExecution2.getStep());
}
public void testRunWithNonDefaultExecutor() throws Exception {
jobExecutor.setStepExecutorFactory(new StepExecutorFactory() {
public StepExecutor getExecutor(Step configuration) {
return configuration == stepConfiguration2 ? defaultStepLifecycle
: configurationStepLifecycle;
}
});
stepConfiguration1.setStartLimit(5);
stepConfiguration2.setStartLimit(5);
jobExecutor.run(jobConfiguration, jobExecution);
assertEquals(2, list.size());
assertEquals("special", list.get(0));
assertEquals("default", list.get(1));
checkRepository(BatchStatus.COMPLETED);
}
public void testInterrupted() throws Exception {
stepConfiguration1.setStartLimit(5);
stepConfiguration2.setStartLimit(5);

View File

@@ -27,15 +27,14 @@ import org.springframework.batch.core.domain.Job;
import org.springframework.batch.core.domain.JobExecution;
import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.domain.JobParameters;
import org.springframework.batch.core.domain.Step;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.executor.StepExecutorFactory;
import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.batch.execution.job.DefaultJobExecutor;
import org.springframework.batch.execution.repository.SimpleJobRepository;
import org.springframework.batch.execution.repository.dao.MapJobDao;
import org.springframework.batch.execution.repository.dao.MapStepDao;
import org.springframework.batch.execution.step.SimpleStep;
import org.springframework.batch.execution.step.simple.AbstractStep;
import org.springframework.batch.execution.step.simple.RepeatOperationsStep;
import org.springframework.batch.execution.step.simple.SimpleStep;
import org.springframework.batch.execution.step.simple.SimpleStepExecutor;
import org.springframework.batch.execution.tasklet.ItemOrientedTasklet;
import org.springframework.batch.item.ItemReader;
@@ -47,9 +46,7 @@ import org.springframework.batch.repeat.exception.handler.ExceptionHandler;
import org.springframework.batch.repeat.support.RepeatTemplate;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
import org.springframework.transaction.interceptor.TransactionProxyFactoryBean;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.StringUtils;
public class SimpleJobTests extends TestCase {
@@ -75,11 +72,6 @@ public class SimpleJobTests extends TestCase {
super.setUp();
jobExecutor.setJobRepository(repository);
stepLifecycle.setRepository(repository);
jobExecutor.setStepExecutorFactory(new StepExecutorFactory() {
public StepExecutor getExecutor(Step configuration) {
return stepLifecycle;
}
});
}
private Tasklet getTasklet(String arg) throws Exception {
@@ -111,8 +103,14 @@ public class SimpleJobTests extends TestCase {
public void testSimpleJob() throws Exception {
Job jobConfiguration = new Job();
jobConfiguration.addStep(new SimpleStep(getTasklet("foo", "bar")));
jobConfiguration.addStep(new SimpleStep(getTasklet("spam")));
AbstractStep step = new SimpleStep(getTasklet("foo", "bar"));
step.setJobRepository(repository);
step.setTransactionManager(new ResourcelessTransactionManager());
jobConfiguration.addStep(step);
step = new SimpleStep(getTasklet("spam"));
step.setJobRepository(repository);
step.setTransactionManager(new ResourcelessTransactionManager());
jobConfiguration.addStep(step);
JobInstance job = repository.createJobExecution(jobConfiguration, new JobParameters()).getJobInstance();
@@ -138,15 +136,6 @@ public class SimpleJobTests extends TestCase {
assertEquals("Try again Dummy!", throwable.getMessage());
}
});
stepLifecycle.setChunkOperations(chunkOperations);
TransactionProxyFactoryBean proxyFactoryBean = new TransactionProxyFactoryBean();
proxyFactoryBean.setTransactionManager(new ResourcelessTransactionManager());
proxyFactoryBean.setTarget(stepLifecycle);
proxyFactoryBean.setTransactionAttributes(StringUtils.splitArrayElementsIntoProperties(
new String[] { "processChunk=PROPAGATION_REQUIRED" }, "="));
proxyFactoryBean.setExposeProxy(true);
proxyFactoryBean.afterPropertiesSet();
/*
* Each message fails once and the chunk (size=1) "rolls back"; then it
@@ -154,7 +143,11 @@ public class SimpleJobTests extends TestCase {
* definition above)...
*/
final ItemOrientedTasklet module = getTasklet(new String[] { "foo", "bar", "spam" });
Step step = new SimpleStep(module);
RepeatOperationsStep step = new RepeatOperationsStep();
step.setTasklet(module);
step.setChunkOperations(chunkOperations);
step.setJobRepository(repository);
step.setTransactionManager(new ResourcelessTransactionManager());
module.setItemWriter(new ItemWriter() {
public void write(Object data) throws Exception {
throw new RuntimeException("Try again Dummy!");
@@ -177,7 +170,9 @@ public class SimpleJobTests extends TestCase {
Job jobConfiguration = new Job();
final ItemOrientedTasklet module = getTasklet(new String[] { "foo", "bar", "spam" });
Step step = new SimpleStep(module);
AbstractStep step = new SimpleStep(module);
step.setJobRepository(repository);
step.setTransactionManager(new ResourcelessTransactionManager());
module.setItemWriter(new ItemWriter() {
public void write(Object data) throws Exception {
throw new RuntimeException("Foo");

View File

@@ -1,162 +0,0 @@
/*
* 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.execution.step;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.core.domain.StepSupport;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.execution.step.simple.SimpleStepExecutor;
import org.springframework.batch.repeat.RepeatOperations;
import org.springframework.batch.repeat.support.RepeatTemplate;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.support.StaticApplicationContext;
/**
* @author Dave Syer
*
*/
public class PrototypeBeanStepExecutorFactoryTests extends TestCase {
private PrototypeBeanStepExecutorFactory factory = new PrototypeBeanStepExecutorFactory();
private StaticApplicationContext applicationContext = new StaticApplicationContext();
protected void setUp() throws Exception {
factory.setBeanFactory(applicationContext);
}
public void testMissingStepExecutorName() throws Exception {
try {
factory.afterPropertiesSet();
fail("Expected IllegalArgumentException");
} catch(IllegalArgumentException e) {
// Missing name is illegal
}
}
public void testMissingStepExecutor() throws Exception {
factory.setStepExecutorName("foo");
try {
factory.afterPropertiesSet();
fail("Expected NoSuchBeanDefinitionException");
} catch(NoSuchBeanDefinitionException e) {
// expected
}
}
public void testSingletonStepExecutor() throws Exception {
applicationContext.getDefaultListableBeanFactory().registerBeanDefinition("foo", new RootBeanDefinition(SimpleStepExecutor.class));
factory.setStepExecutorName("foo");
try {
factory.afterPropertiesSet();
fail("Expected IllegalStateException");
} catch(IllegalStateException e) {
// expected
}
}
public void testSuccessfulStepExecutor() throws Exception {
SimpleStepExecutor executor = new SimpleStepExecutor();
applicationContext.getBeanFactory().registerSingleton("foo", executor);
factory.setStepExecutorName("foo");
assertEquals(executor, factory.getExecutor(new SimpleStep()));
}
public void testSuccessfulStepExecutorWithNonSimpleConfigugration() throws Exception {
SimpleStepExecutor executor = new SimpleStepExecutor();
applicationContext.getBeanFactory().registerSingleton("foo", executor);
factory.setStepExecutorName("foo");
assertEquals(executor, factory.getExecutor(new StepSupport()));
}
public void testSuccessfulStepExecutorWithSimpleConfigurationAndNotSimpleExecutor() throws Exception {
StepExecutor executor = new SimpleStepExecutor();
applicationContext.getBeanFactory().registerSingleton("foo", executor);
factory.setStepExecutorName("foo");
assertEquals(executor, factory.getExecutor(new SimpleStep()));
}
public void testSuccessfulStepExecutorHolderStrategy() throws Exception {
SimpleStepExecutor executor = new SimpleStepExecutor();
applicationContext.getBeanFactory().registerSingleton("foo", executor);
factory.setStepExecutorName("foo");
RepeatTemplate repeatTemplate = new RepeatTemplate();
assertEquals(executor, factory.getExecutor(new SimpleHolderStepConfiguration(repeatTemplate)));
}
public void testSuccessfulStepExecutorHolderStrategyWithStepOperations() throws Exception {
final List list = new ArrayList();
SimpleStepExecutor executor = new SimpleStepExecutor() {
public void setChunkOperations(RepeatOperations chunkOperations) {
list.add(chunkOperations);
super.setChunkOperations(chunkOperations);
}
public void setStepOperations(RepeatOperations stepOperations) {
list.add(stepOperations);
super.setStepOperations(stepOperations);
}
};
applicationContext.getBeanFactory().registerSingleton("foo", executor);
factory.setStepExecutorName("foo");
RepeatTemplate chunkTemplate = new RepeatTemplate();
RepeatTemplate stepTemplate = new RepeatTemplate();
SimpleStepExecutor product = (SimpleStepExecutor) factory.getExecutor(new SimpleHolderStepConfiguration(chunkTemplate, stepTemplate));
assertEquals(executor, product);
assertEquals(2, list.size());
assertEquals(chunkTemplate, list.get(0));
assertEquals(stepTemplate, list.get(1));
}
public void testUnsuccessfulStepExecutorHolderStrategy() throws Exception {
SimpleStepExecutor executor = new SimpleStepExecutor();
applicationContext.getBeanFactory().registerSingleton("foo", executor);
factory.setStepExecutorName("foo");
try {
factory.getExecutor(new SimpleHolderStepConfiguration(null));
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
// expected
}
}
/**
* @author Dave Syer
*
*/
public class SimpleHolderStepConfiguration extends SimpleStep implements RepeatOperationsHolder {
private RepeatOperations chunkOperations;
private RepeatOperations stepOperations;
public SimpleHolderStepConfiguration(RepeatOperations executor) {
this.chunkOperations = executor;
}
public SimpleHolderStepConfiguration(RepeatOperations chunkOperations,
RepeatOperations stepOperations) {
this.chunkOperations = chunkOperations;
this.stepOperations = stepOperations;
}
public RepeatOperations getChunkOperations() {
return chunkOperations;
}
public RepeatOperations getStepOperations() {
return stepOperations;
}
}
}

View File

@@ -17,7 +17,6 @@ package org.springframework.batch.execution.step.simple;
import junit.framework.TestCase;
import org.springframework.batch.execution.step.RepeatOperationsStep;
import org.springframework.batch.repeat.support.RepeatTemplate;
/**
@@ -29,7 +28,7 @@ public class RepeatOperationsStepTests extends TestCase {
RepeatOperationsStep configuration = new RepeatOperationsStep();
/**
* Test method for {@link org.springframework.batch.execution.step.RepeatOperationsStep#getChunkOperations()}.
* Test method for {@link org.springframework.batch.execution.step.simple.RepeatOperationsStep#getChunkOperations()}.
*/
public void testSetChunkOperations() {
assertNull(configuration.getChunkOperations());
@@ -40,7 +39,7 @@ public class RepeatOperationsStepTests extends TestCase {
}
/**
* Test method for {@link org.springframework.batch.execution.step.RepeatOperationsStep#getChunkOperations()}.
* Test method for {@link org.springframework.batch.execution.step.simple.RepeatOperationsStep#getChunkOperations()}.
*/
public void testSetStepOperations() {
assertNull(configuration.getChunkOperations());

View File

@@ -18,7 +18,6 @@ package org.springframework.batch.execution.step.simple;
import junit.framework.TestCase;
import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.batch.execution.step.SimpleStep;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.exception.handler.DefaultExceptionHandler;
@@ -31,7 +30,7 @@ public class SimpleStepConfigurationTests extends TestCase {
SimpleStep configuration = new SimpleStep("foo");
/**
* Test method for {@link org.springframework.batch.execution.step.SimpleStep#SimpleStepConfiguration()}.
* Test method for {@link org.springframework.batch.execution.step.simple.SimpleStep#SimpleStepConfiguration()}.
*/
public void testSimpleStepConfiguration() {
assertNotNull(configuration.getName());
@@ -40,7 +39,7 @@ public class SimpleStepConfigurationTests extends TestCase {
}
/**
* Test method for {@link org.springframework.batch.execution.step.SimpleStep#SimpleStepConfiguration(org.springframework.batch.core.tasklet.Tasklet)}.
* Test method for {@link org.springframework.batch.execution.step.simple.SimpleStep#SimpleStepConfiguration(org.springframework.batch.core.tasklet.Tasklet)}.
*/
public void testSimpleStepConfigurationTasklet() {
Tasklet tasklet = new Tasklet() {
@@ -53,7 +52,7 @@ public class SimpleStepConfigurationTests extends TestCase {
}
/**
* Test method for {@link org.springframework.batch.execution.step.SimpleStep#getCommitInterval()}.
* Test method for {@link org.springframework.batch.execution.step.simple.SimpleStep#getCommitInterval()}.
*/
public void testGetCommitInterval() {
assertEquals(1, configuration.getCommitInterval());
@@ -62,7 +61,7 @@ public class SimpleStepConfigurationTests extends TestCase {
}
/**
* Test method for {@link org.springframework.batch.execution.step.AbstractStep#getExceptionHandler()}.
* Test method for {@link org.springframework.batch.execution.step.simple.AbstractStep#getExceptionHandler()}.
*/
public void testGetExceptionHandler() {
assertNull(configuration.getExceptionHandler());
@@ -71,7 +70,7 @@ public class SimpleStepConfigurationTests extends TestCase {
}
/**
* Test method for {@link org.springframework.batch.execution.step.AbstractStep#getExceptionHandler()}.
* Test method for {@link org.springframework.batch.execution.step.simple.AbstractStep#getExceptionHandler()}.
*/
public void testSkipLimit() {
assertEquals(0, configuration.getSkipLimit());
@@ -80,7 +79,7 @@ public class SimpleStepConfigurationTests extends TestCase {
}
/**
* Test method for {@link org.springframework.batch.execution.step.AbstractStep#getSkipLimit()}.
* Test method for {@link org.springframework.batch.execution.step.simple.AbstractStep#getSkipLimit()}.
*/
public void testGetSkipLimit() {
assertEquals(0, configuration.getSkipLimit());
@@ -89,7 +88,7 @@ public class SimpleStepConfigurationTests extends TestCase {
}
/**
* Test method for {@link org.springframework.batch.execution.step.AbstractStep#isSaveRestartData()}.
* Test method for {@link org.springframework.batch.execution.step.simple.AbstractStep#isSaveRestartData()}.
*/
public void testIsSaveRestartData() {
assertEquals(false, configuration.isSaveRestartData());

View File

@@ -27,8 +27,6 @@ import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.core.domain.StepInstance;
import org.springframework.batch.core.domain.StepSupport;
import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.batch.execution.step.RepeatOperationsHolder;
import org.springframework.batch.execution.step.SimpleStep;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.RepeatOperations;
@@ -36,6 +34,7 @@ import org.springframework.batch.repeat.exception.handler.ExceptionHandler;
import org.springframework.batch.repeat.interceptor.RepeatInterceptorAdapter;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.batch.repeat.support.RepeatTemplate;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
/**
* @author Dave Syer
@@ -43,18 +42,17 @@ import org.springframework.batch.repeat.support.RepeatTemplate;
*/
public class SimpleStepExecutorFactoryTests extends TestCase {
private SimpleStepExecutorFactory factory = new SimpleStepExecutorFactory();
protected void setUp() throws Exception {
factory.setJobRepository(new JobRepositorySupport());
}
public void testSuccessfulStepExecutor() throws Exception {
assertNotNull(factory.getExecutor(new SimpleStep()));
AbstractStep step = new SimpleStep();
step.setJobRepository(new JobRepositorySupport());
step.setTransactionManager(new ResourcelessTransactionManager());
assertNotNull(step.createStepExecutor());
}
public void testSuccessfulExceptionHandler() throws Exception {
SimpleStep configuration = new SimpleStep();
AbstractStep configuration = new SimpleStep("foo");
configuration.setJobRepository(new JobRepositorySupport());
configuration.setTransactionManager(new ResourcelessTransactionManager());
final List list = new ArrayList();
configuration.setExceptionHandler(new ExceptionHandler() {
public void handleException(RepeatContext context,
@@ -63,8 +61,8 @@ public class SimpleStepExecutorFactoryTests extends TestCase {
throw new RuntimeException("Oops");
}
});
SimpleStepExecutor executor = (SimpleStepExecutor) factory
.getExecutor(configuration);
SimpleStepExecutor executor = (SimpleStepExecutor) configuration
.createStepExecutor();
StepExecution stepExecution = new StepExecution(new StepInstance(
new Long(11)), new JobExecution(new JobInstance(new Long(0L), new JobParameters()),
new Long(12)));
@@ -90,8 +88,10 @@ public class SimpleStepExecutorFactoryTests extends TestCase {
repeatTemplate.setCompletionPolicy(new SimpleCompletionPolicy(2));
SimpleHolderStepConfiguration configuration = new SimpleHolderStepConfiguration(
repeatTemplate);
SimpleStepExecutor executor = (SimpleStepExecutor) factory
.getExecutor(configuration);
configuration.setJobRepository(new JobRepositorySupport());
configuration.setTransactionManager(new ResourcelessTransactionManager());
SimpleStepExecutor executor = (SimpleStepExecutor) configuration
.createStepExecutor();
StepExecution stepExecution = new StepExecution(new StepInstance(
new Long(11)), new JobExecution(new JobInstance(new Long(0L), new JobParameters()),
new Long(12)));
@@ -123,13 +123,15 @@ public class SimpleStepExecutorFactoryTests extends TestCase {
stepTemplate.setCompletionPolicy(new SimpleCompletionPolicy(1));
SimpleHolderStepConfiguration configuration = new SimpleHolderStepConfiguration(
chunkTemplate, stepTemplate);
configuration.setJobRepository(new JobRepositorySupport());
configuration.setTransactionManager(new ResourcelessTransactionManager());
configuration.setTasklet(new Tasklet() {
public ExitStatus execute() throws Exception {
return ExitStatus.CONTINUABLE;
}
});
SimpleStepExecutor executor = (SimpleStepExecutor) factory
.getExecutor(configuration);
SimpleStepExecutor executor = (SimpleStepExecutor) configuration
.createStepExecutor();
StepExecution stepExecution = new StepExecution(new StepInstance(
new Long(11)), new JobExecution(new JobInstance(new Long(0L), new JobParameters()),
new Long(12)));
@@ -140,9 +142,9 @@ public class SimpleStepExecutorFactoryTests extends TestCase {
public void testUnsuccessfulWrongConfiguration() throws Exception {
try {
factory.getExecutor(new StepSupport());
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
new StepSupport().createStepExecutor();
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// expected
assertTrue(
"Error message does not contain SimpleStep: "
@@ -153,8 +155,7 @@ public class SimpleStepExecutorFactoryTests extends TestCase {
public void testUnsuccessfulNoJobRepository() throws Exception {
try {
factory = new SimpleStepExecutorFactory();
factory.getExecutor(new SimpleStep());
new SimpleStep().createStepExecutor();
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected
@@ -165,9 +166,8 @@ public class SimpleStepExecutorFactoryTests extends TestCase {
}
public void testMandatoryProperties() throws Exception {
factory = new SimpleStepExecutorFactory();
try {
factory.afterPropertiesSet();
new SimpleStep().afterPropertiesSet();
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected

View File

@@ -32,14 +32,12 @@ import org.springframework.batch.core.domain.JobParameters;
import org.springframework.batch.core.domain.StepContribution;
import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.core.domain.StepInstance;
import org.springframework.batch.core.domain.StepSupport;
import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.batch.execution.repository.SimpleJobRepository;
import org.springframework.batch.execution.repository.dao.MapJobDao;
import org.springframework.batch.execution.repository.dao.MapStepDao;
import org.springframework.batch.execution.scope.StepScope;
import org.springframework.batch.execution.scope.StepSynchronizationManager;
import org.springframework.batch.execution.step.SimpleStep;
import org.springframework.batch.execution.tasklet.ItemOrientedTasklet;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
@@ -56,6 +54,7 @@ import org.springframework.batch.restart.Restartable;
import org.springframework.batch.statistics.StatisticsProvider;
import org.springframework.batch.statistics.StatisticsService;
import org.springframework.batch.support.PropertiesConverter;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
public class SimpleStepExecutorTests extends TestCase {
@@ -69,7 +68,7 @@ public class SimpleStepExecutorTests extends TestCase {
private SimpleStepExecutor stepExecutor;
private StepSupport stepConfiguration;
private AbstractStep stepConfiguration;
private RepeatTemplate template;
@@ -99,10 +98,11 @@ public class SimpleStepExecutorTests extends TestCase {
*/
protected void setUp() throws Exception {
super.setUp();
stepExecutor = new SimpleStepExecutor();
stepExecutor.setRepository(new JobRepositorySupport());
stepConfiguration = new SimpleStep();
stepConfiguration.setTasklet(getTasklet(new String[] { "foo", "bar", "spam" }));
stepConfiguration.setJobRepository(new JobRepositorySupport());
stepConfiguration.setTransactionManager(new ResourcelessTransactionManager());
stepExecutor = (SimpleStepExecutor) stepConfiguration.createStepExecutor();
template = new RepeatTemplate();
template.setCompletionPolicy(new SimpleCompletionPolicy(1));
stepExecutor.setStepOperations(template);
@@ -287,7 +287,7 @@ public class SimpleStepExecutorTests extends TestCase {
public void testNonRestartedJob() {
StepInstance step = new StepInstance(new Long(1));
MockRestartableTasklet tasklet = new MockRestartableTasklet();
stepConfiguration.setTasklet(tasklet);
stepExecutor.setTasklet(tasklet);
stepConfiguration.setSaveRestartData(true);
JobExecution jobExecutionContext = new JobExecution(jobInstance);
StepExecution stepExecution = new StepExecution(step,
@@ -312,7 +312,7 @@ public class SimpleStepExecutorTests extends TestCase {
StepInstance step = new StepInstance(new Long(1));
step.setStepExecutionCount(1);
MockRestartableTasklet tasklet = new MockRestartableTasklet();
stepConfiguration.setTasklet(tasklet);
stepExecutor.setTasklet(tasklet);
stepConfiguration.setSaveRestartData(true);
JobExecution jobExecutionContext = new JobExecution(jobInstance);
StepExecution stepExecution = new StepExecution(step,
@@ -379,7 +379,7 @@ public class SimpleStepExecutorTests extends TestCase {
}
public void testApplyConfigurationWithExceptionHandler() throws Exception {
SimpleStep stepConfiguration = new SimpleStep("foo");
AbstractStep stepConfiguration = new SimpleStep("foo");
final List list = new ArrayList();
stepExecutor.setStepOperations(new RepeatTemplate() {
public void setExceptionHandler(ExceptionHandler exceptionHandler) {
@@ -392,7 +392,7 @@ public class SimpleStepExecutorTests extends TestCase {
}
public void testApplyConfigurationWithZeroSkipLimit() throws Exception {
SimpleStep stepConfiguration = new SimpleStep("foo");
AbstractStep stepConfiguration = new SimpleStep("foo");
stepConfiguration.setSkipLimit(0);
final List list = new ArrayList();
stepExecutor.setStepOperations(new RepeatTemplate() {
@@ -405,7 +405,7 @@ public class SimpleStepExecutorTests extends TestCase {
}
public void testApplyConfigurationWithNonZeroSkipLimit() throws Exception {
SimpleStep stepConfiguration = new SimpleStep("foo");
AbstractStep stepConfiguration = new SimpleStep("foo");
stepConfiguration.setSkipLimit(1);
final List list = new ArrayList();
stepExecutor.setStepOperations(new RepeatTemplate() {

View File

@@ -27,7 +27,7 @@ import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.domain.JobParameters;
import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.core.domain.StepInstance;
import org.springframework.batch.core.domain.StepSupport;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.executor.StepInterruptedException;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.tasklet.Tasklet;
@@ -36,10 +36,10 @@ import org.springframework.batch.execution.repository.dao.JobDao;
import org.springframework.batch.execution.repository.dao.MapJobDao;
import org.springframework.batch.execution.repository.dao.MapStepDao;
import org.springframework.batch.execution.repository.dao.StepDao;
import org.springframework.batch.execution.step.SimpleStep;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.batch.repeat.support.RepeatTemplate;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
public class StepExecutorInterruptionTests extends TestCase {
@@ -51,26 +51,25 @@ public class StepExecutorInterruptionTests extends TestCase {
private JobInstance job;
private StepSupport stepConfiguration;
private RepeatOperationsStep stepConfiguration;
private SimpleStepExecutor executor;
private StepExecutor executor;
public void setUp() throws Exception {
jobRepository = new SimpleJobRepository(jobDao, stepDao);
Job jobConfiguration = new Job();
stepConfiguration = new SimpleStep();
stepConfiguration = new RepeatOperationsStep();
jobConfiguration.addStep(stepConfiguration);
jobConfiguration.setBeanName("testJob");
job = jobRepository.createJobExecution(jobConfiguration, new JobParameters()).getJobInstance();
executor = new SimpleStepExecutor();
stepConfiguration.setJobRepository(jobRepository);
stepConfiguration.setTransactionManager(new ResourcelessTransactionManager());
}
public void testInterruptChunk() throws Exception {
executor.setRepository(jobRepository);
List steps = job.getStepInstances();
final StepInstance step = (StepInstance) steps.get(0);
JobExecution jobExecutionContext = new JobExecution(new JobInstance(new Long(0L), new JobParameters()));
@@ -86,6 +85,7 @@ public class StepExecutorInterruptionTests extends TestCase {
return new ExitStatus(foo != 1);
}
});
executor = stepConfiguration.createStepExecutor();
Thread processingThread = new Thread() {
public void run() {
@@ -118,7 +118,7 @@ public class StepExecutorInterruptionTests extends TestCase {
RepeatTemplate template = new RepeatTemplate();
// N.B, If we don't set the completion policy it might run forever
template.setCompletionPolicy(new SimpleCompletionPolicy(2));
executor.setChunkOperations(template);
stepConfiguration.setChunkOperations(template);
testInterruptChunk();
}

View File

@@ -13,7 +13,7 @@
<bean id="test-job" class="org.springframework.batch.core.domain.Job">
<property name="steps">
<bean id="step1" class="org.springframework.batch.execution.step.SimpleStep">
<bean id="step1" class="org.springframework.batch.execution.step.simple.SimpleStep">
<constructor-arg>
<bean
class="org.springframework.batch.execution.tasklet.ItemOrientedTasklet">

View File

@@ -9,7 +9,7 @@
<bean id="test-job" class="org.springframework.batch.core.domain.Job">
<property name="steps">
<bean id="step1" class="org.springframework.batch.execution.step.SimpleStep">
<bean id="step1" class="org.springframework.batch.execution.step.simple.SimpleStep">
<constructor-arg>
<bean
class="org.springframework.batch.execution.tasklet.ItemOrientedTasklet">

View File

@@ -15,7 +15,7 @@
<bean id="test-job" class="org.springframework.batch.core.domain.Job">
<property name="steps">
<bean id="step1" class="org.springframework.batch.execution.step.SimpleStep">
<bean id="step1" class="org.springframework.batch.execution.step.simple.SimpleStep">
<constructor-arg>
<bean
class="org.springframework.batch.execution.tasklet.ItemOrientedTasklet">

View File

@@ -21,12 +21,6 @@
<bean id="jobLifecycle"
class="org.springframework.batch.execution.job.DefaultJobExecutor">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="stepExecutorFactory">
<bean
class="org.springframework.batch.execution.step.PrototypeBeanStepExecutorFactory">
<property name="stepExecutorName" value="stepLifecycle" />
</bean>
</property>
</bean>
<bean id="simpleJob"
@@ -35,7 +29,7 @@
</bean>
<bean id="simpleStep"
class="org.springframework.batch.execution.step.SimpleStep"
class="org.springframework.batch.execution.step.simple.SimpleStep"
abstract="true">
<property name="allowStartIfComplete" value="true" />
<property name="saveRestartData" value="false" />

View File

@@ -41,7 +41,7 @@ public class ExceptionRestartableTasklet extends RestartableItemOrientedTasklet
counter++;
if (counter == throwExceptionOnRecordNumber) {
throw new BatchCriticalException();
throw new BatchCriticalException("Planned failure on count="+counter);
}
return super.execute();

View File

@@ -107,18 +107,8 @@
<bean id="jobLauncher"
class="org.springframework.batch.execution.launch.SimpleJobLauncher">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="jobExecutor">
<bean parent="jobExecutor">
<property name="stepExecutorFactory">
<bean
class="org.springframework.batch.execution.step.PrototypeBeanStepExecutorFactory">
<property name="stepExecutorName"
value="notifyingStepExecutor" />
</bean>
</property>
</bean>
</property>
<property name="jobRepository" ref="jobRepository" />
<property name="jobExecutor" ref="jobExecutor"/>
<property name="taskExecutor">
<bean
class="org.springframework.core.task.SimpleAsyncTaskExecutor" />

View File

@@ -18,8 +18,7 @@
<property name="startLimit" value="100" />
<property name="steps">
<list>
<bean id="playerload"
class="org.springframework.batch.execution.step.SimpleStep">
<bean id="playerload" parent="simpleStep">
<property name="commitInterval" value="1"></property>
<property name="startLimit" value="100" />
<property name="saveRestartData" value="true" />
@@ -44,8 +43,7 @@
</bean>
</property>
</bean>
<bean id="gameLoad"
class="org.springframework.batch.execution.step.SimpleStep">
<bean id="gameLoad" parent="simpleStep">
<property name="commitInterval" value="1" />
<property name="startLimit" value="100" />
<property name="saveRestartData" value="true" />
@@ -64,8 +62,7 @@
</bean>
</property>
</bean>
<bean id="playerSummarization"
class="org.springframework.batch.execution.step.SimpleStep">
<bean id="playerSummarization" parent="simpleStep">
<property name="commitInterval" value="1" />
<property name="startLimit" value="100" />
<property name="saveRestartData" value="true" />

View File

@@ -18,8 +18,7 @@
<!-- set restartable=false so that this job can be used by more than one test -->
<property name="restartable" value="false" />
<property name="steps">
<bean id="step1"
class="org.springframework.batch.execution.step.RepeatOperationsStep">
<bean id="step1" parent="repeatOperationsStep">
<property name="tasklet">
<bean
class="org.springframework.batch.execution.tasklet.RestartableItemOrientedTasklet">

View File

@@ -14,7 +14,7 @@
<bean id="jobLauncher" class="org.springframework.batch.execution.launch.SimpleJobLauncher">
<property name="jobExecutor" ref="jobExecutor" />
<property name="jobRepository" ref="simpleJobRepository" />
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>
</property>

View File

@@ -46,13 +46,12 @@
</property>
</bean>
</property>
<property name="commitInterval" value="2"/>
<property name="commitInterval" value="2" />
<property name="startLimit" value="100" />
<property name="saveRestartData" value="true" />
<property name="allowStartIfComplete" value="false" />
</bean>
<bean id="loading"
class="org.springframework.batch.execution.step.RepeatOperationsStep">
<bean id="loading" parent="repeatOperationsStep">
<property name="tasklet">
<bean
class="org.springframework.batch.execution.tasklet.ItemOrientedTasklet">
@@ -68,8 +67,7 @@
<property name="itemWriter">
<bean
class="org.springframework.batch.sample.item.writer.TradeWriter">
<property name="dao"
ref="tradeDao" />
<property name="dao" ref="tradeDao" />
</bean>
</property>
</bean>

View File

@@ -17,9 +17,8 @@
<bean id="tradeJob" parent="simpleJob">
<property name="steps">
<list>
<bean id="step1"
class="org.springframework.batch.execution.step.RepeatOperationsStep">
<property name="chunkOperations">
<bean id="step1" parent="repeatOperationsStep">
<property name="chunkOperations">
<bean
class="org.springframework.batch.repeat.support.RepeatTemplate">
<property name="completionPolicy">
@@ -37,7 +36,7 @@
<property name="exceptionHandler">
<bean
class="org.springframework.batch.repeat.exception.handler.SimpleLimitExceptionHandler"
p:limit="5" p:type="java.lang.Exception"/>
p:limit="5" p:type="java.lang.Exception" />
</property>
</bean>
</property>
@@ -56,18 +55,21 @@
<property name="itemWriter">
<bean
class="org.springframework.batch.sample.item.writer.TradeWriter"
p:dao-ref="tradeDao" p:failure="3"/>
p:dao-ref="tradeDao" p:failure="3" />
</property>
</bean>
</property>
<property name="jobRepository" ref="jobRepository" />
</bean>
<bean id="step2" parent="simpleStep">
<property name="tasklet">
<bean
class="org.springframework.batch.execution.tasklet.RestartableItemOrientedTasklet">
<property name="itemReader" ref="tradeSqlItemReader" />
<property name="itemReader"
ref="tradeSqlItemReader" />
<property name="itemWriter">
<bean class="org.springframework.batch.sample.item.writer.DummyItemWriter" />
<bean
class="org.springframework.batch.sample.item.writer.DummyItemWriter" />
</property>
</bean>
</property>

View File

@@ -23,7 +23,7 @@
<bean id="jobLauncher"
class="org.springframework.batch.execution.launch.SimpleJobLauncher">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="jobRepository" ref="jobRepository" />
<property name="jobExecutor" ref="jobExecutor" />
</bean>
@@ -45,23 +45,17 @@
<bean id="jobExecutor"
class="org.springframework.batch.execution.job.DefaultJobExecutor">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="stepExecutorFactory">
<bean
class="org.springframework.batch.execution.step.PrototypeBeanStepExecutorFactory">
<property name="stepExecutorName" value="stepExecutor" />
</bean>
</property>
<property name="jobRepository" ref="jobRepository" />
</bean>
<bean id="stepExecutor"
class="org.springframework.batch.execution.step.simple.SimpleStepExecutor"
scope="prototype">
<property name="transactionManager" ref="transactionManager" />
<property name="repository" ref="simpleJobRepository" />
<property name="repository" ref="jobRepository" />
</bean>
<bean id="simpleJobRepository"
<bean id="jobRepository"
class="org.springframework.batch.execution.repository.SimpleJobRepository">
<constructor-arg ref="jobDao" />
<constructor-arg ref="stepDao" />
@@ -102,10 +96,12 @@
</bean>
<bean id="simpleStep"
class="org.springframework.batch.execution.step.SimpleStep"
class="org.springframework.batch.execution.step.simple.SimpleStep"
abstract="true">
<property name="allowStartIfComplete" value="true" />
<property name="saveRestartData" value="false" />
<property name="saveRestartData" value="false" />
<property name="jobRepository" ref="jobRepository"/>
<property name="transactionManager" ref="transactionManager"/>
<property name="exceptionHandler">
<bean
class="org.springframework.batch.repeat.exception.handler.SimpleLimitExceptionHandler">
@@ -116,6 +112,15 @@
<property name="commitInterval" value="1" />
</bean>
<bean id="repeatOperationsStep"
class="org.springframework.batch.execution.step.simple.RepeatOperationsStep"
abstract="true">
<property name="allowStartIfComplete" value="true" />
<property name="saveRestartData" value="false" />
<property name="jobRepository" ref="jobRepository"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>
<bean id="customEditorConfigurer"
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">

View File

@@ -17,6 +17,7 @@
package org.springframework.batch.sample;
import org.springframework.batch.core.domain.JobParameters;
import org.springframework.batch.io.exception.BatchCriticalException;
import org.springframework.jdbc.core.JdbcOperations;
/**
@@ -68,10 +69,14 @@ public class RestartFunctionalTests extends AbstractBatchLauncherTests {
runJob();
fail("First run of the job is expected to fail.");
}
catch (Exception expected) {
catch (BatchCriticalException expected) {
//expected
assertTrue("Not planned exception: "+expected.getMessage(), expected.getMessage().toLowerCase().indexOf("planned")>=0);
}
int medium = jdbcTemplate.queryForInt("SELECT COUNT(*) FROM TRADE");
System.err.println(medium);
runJob();
int after = jdbcTemplate.queryForInt("SELECT COUNT(*) FROM TRADE");