RESOLVED - BATCH-1026: Rename ExitStatus.FINISHED to ExitStatus.COMPLETED

This commit is contained in:
robokaso
2009-01-27 11:38:26 +00:00
parent 8e1e352be4
commit f4fa341233
31 changed files with 1240 additions and 1240 deletions

View File

@@ -49,7 +49,7 @@ public class ExitStatus implements Serializable, Comparable<ExitStatus> {
/**
* Convenient constant value representing finished processing.
*/
public static final ExitStatus FINISHED = new ExitStatus("COMPLETED");
public static final ExitStatus COMPLETED = new ExitStatus("COMPLETED");
/**
* Convenient constant value representing job that did no processing (e.g.
@@ -153,7 +153,7 @@ public class ExitStatus implements Serializable, Comparable<ExitStatus> {
* @return
*/
private int severity(ExitStatus status) {
if (status.exitCode.startsWith(FINISHED.exitCode)) {
if (status.exitCode.startsWith(COMPLETED.exitCode)) {
return 2;
}
if (status.exitCode.startsWith(NOOP.exitCode)) {

View File

@@ -233,7 +233,7 @@ public abstract class AbstractJob implements Job, BeanNameAware, InitializingBea
// The job was already stopped before we even got this far. Deal
// with it in the same way as any other interruption.
execution.setStatus(BatchStatus.STOPPED);
execution.setExitStatus(ExitStatus.FINISHED);
execution.setExitStatus(ExitStatus.COMPLETED);
}

View File

@@ -41,7 +41,7 @@ public class SimpleJvmExitCodeMapper implements ExitCodeMapper {
public SimpleJvmExitCodeMapper() {
mapping = new HashMap<String, Integer>();
mapping.put(ExitStatus.FINISHED.getExitCode(), JVM_EXITCODE_COMPLETED);
mapping.put(ExitStatus.COMPLETED.getExitCode(), JVM_EXITCODE_COMPLETED);
mapping.put(ExitStatus.FAILED.getExitCode(), JVM_EXITCODE_GENERIC_ERROR);
mapping.put(ExitCodeMapper.JOB_NOT_PROVIDED, JVM_EXITCODE_JOB_ERROR);
mapping.put(ExitCodeMapper.NO_SUCH_JOB, JVM_EXITCODE_JOB_ERROR);

View File

@@ -1,104 +1,104 @@
/*
* 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.core.listener;
import java.util.Collections;
import java.util.List;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.support.util.PatternMatcher;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import com.sun.org.apache.xerces.internal.impl.xpath.XPath.Step;
/**
* This class can be used to automatically promote items from the {@link Step}
* {@link ExecutionContext} to the {@link Job} {@link ExecutionContext} at the
* end of a step. A list of keys should be provided that correspond to the items
* in the {@link Step} {@link ExecutionContext} that should be promoted.
*
* Additionally, an optional list of statuses can be set to indicate for which
* exit status codes the promotion should occur. These statuses will be checked
* using the {@link PatternMatcher}, so wildcards are allowed.
*
* @author Dan Garrette
* @since 2.0
*/
public class ExecutionContextPromotionListener extends StepExecutionListenerSupport implements InitializingBean {
private List<String> keys = null;
private List<String> statuses = Collections.singletonList(ExitStatus.FINISHED.getExitCode());
/*
* (non-Javadoc)
*
* @see org.springframework.batch.core.domain.StepListener#afterStep(StepExecution
* stepExecution)
*/
public ExitStatus afterStep(StepExecution stepExecution) {
if (statuses == null) {
this.performPromotion(stepExecution);
}
else {
String exitCode = stepExecution.getExitStatus().getExitCode();
for (String statusPattern : statuses) {
if (PatternMatcher.match(statusPattern, exitCode)) {
this.performPromotion(stepExecution);
}
}
}
return null;
}
private void performPromotion(StepExecution stepExecution) {
ExecutionContext stepContext = stepExecution.getExecutionContext();
ExecutionContext jobContext = stepExecution.getJobExecution().getExecutionContext();
for (String key : keys) {
jobContext.put(key, stepContext.get(key));
}
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.keys, "The 'keys' property must be provided");
Assert.notEmpty(this.statuses, "The 'keys' property must not be empty");
Assert.notNull(this.statuses, "The 'statuses' property must be provided");
Assert.notEmpty(this.statuses, "The 'statuses' property must not be empty");
}
/**
* @param keys
* A list of keys corresponding to items in the {@link Step}
* {@link ExecutionContext} that must be promoted.
*/
public void setKeys(List<String> keys) {
this.keys = keys;
}
/**
* @param statuses
* A list of statuses for which the promotion should occur.
* Statuses can may contain wildcards recognizable by the
* {@link PatternMatcher} class.
*/
public void setStatuses(List<String> statuses) {
this.statuses = statuses;
}
}
/*
* 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.core.listener;
import java.util.Collections;
import java.util.List;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.support.util.PatternMatcher;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import com.sun.org.apache.xerces.internal.impl.xpath.XPath.Step;
/**
* This class can be used to automatically promote items from the {@link Step}
* {@link ExecutionContext} to the {@link Job} {@link ExecutionContext} at the
* end of a step. A list of keys should be provided that correspond to the items
* in the {@link Step} {@link ExecutionContext} that should be promoted.
*
* Additionally, an optional list of statuses can be set to indicate for which
* exit status codes the promotion should occur. These statuses will be checked
* using the {@link PatternMatcher}, so wildcards are allowed.
*
* @author Dan Garrette
* @since 2.0
*/
public class ExecutionContextPromotionListener extends StepExecutionListenerSupport implements InitializingBean {
private List<String> keys = null;
private List<String> statuses = Collections.singletonList(ExitStatus.COMPLETED.getExitCode());
/*
* (non-Javadoc)
*
* @see org.springframework.batch.core.domain.StepListener#afterStep(StepExecution
* stepExecution)
*/
public ExitStatus afterStep(StepExecution stepExecution) {
if (statuses == null) {
this.performPromotion(stepExecution);
}
else {
String exitCode = stepExecution.getExitStatus().getExitCode();
for (String statusPattern : statuses) {
if (PatternMatcher.match(statusPattern, exitCode)) {
this.performPromotion(stepExecution);
}
}
}
return null;
}
private void performPromotion(StepExecution stepExecution) {
ExecutionContext stepContext = stepExecution.getExecutionContext();
ExecutionContext jobContext = stepExecution.getJobExecution().getExecutionContext();
for (String key : keys) {
jobContext.put(key, stepContext.get(key));
}
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.keys, "The 'keys' property must be provided");
Assert.notEmpty(this.statuses, "The 'keys' property must not be empty");
Assert.notNull(this.statuses, "The 'statuses' property must be provided");
Assert.notEmpty(this.statuses, "The 'statuses' property must not be empty");
}
/**
* @param keys
* A list of keys corresponding to items in the {@link Step}
* {@link ExecutionContext} that must be promoted.
*/
public void setKeys(List<String> keys) {
this.keys = keys;
}
/**
* @param statuses
* A list of statuses for which the promotion should occur.
* Statuses can may contain wildcards recognizable by the
* {@link PatternMatcher} class.
*/
public void setStatuses(List<String> statuses) {
this.statuses = statuses;
}
}

View File

@@ -1,84 +1,84 @@
/*
* Copyright 2006-2009 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.item;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
/**
* A {@link Tasklet} implementing variations on read-process-write item
* handling.
*
* @author Dave Syer
*
* @param <I> input item type
*/
public class ChunkOrientedTasklet<I> implements Tasklet {
private static final String INPUTS_KEY = "INPUTS";
private final ChunkProcessor<I> chunkProcessor;
private final ChunkProvider<I> chunkProvider;
private boolean buffering = true;
public ChunkOrientedTasklet(ChunkProvider<I> chunkProvider, ChunkProcessor<I> chunkProcessor) {
this.chunkProvider = chunkProvider;
this.chunkProcessor = chunkProcessor;
}
/**
* Flag to indicate that items should be buffered once read. Defaults to
* true, which is appropriate for forward-only, non-transactional item
* readers. Main (or only) use case for setting this flag to true is a
* transactional JMS item reader.
*
* @param buffering
*/
public void setBuffering(boolean buffering) {
this.buffering = buffering;
}
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
@SuppressWarnings("unchecked")
Chunk<I> inputs = (Chunk<I>) chunkContext.getAttribute(INPUTS_KEY);
if (inputs == null) {
inputs = chunkProvider.provide(contribution);
if (buffering) {
chunkContext.setAttribute(INPUTS_KEY, inputs);
}
}
chunkProcessor.process(contribution, inputs);
chunkContext.removeAttribute(INPUTS_KEY);
chunkContext.setComplete();
chunkProvider.postProcess(contribution, inputs);
if (inputs.isEnd()) {
contribution.setExitStatus(ExitStatus.FINISHED);
}
return RepeatStatus.continueIf(!inputs.isEnd());
}
}
/*
* Copyright 2006-2009 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.item;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
/**
* A {@link Tasklet} implementing variations on read-process-write item
* handling.
*
* @author Dave Syer
*
* @param <I> input item type
*/
public class ChunkOrientedTasklet<I> implements Tasklet {
private static final String INPUTS_KEY = "INPUTS";
private final ChunkProcessor<I> chunkProcessor;
private final ChunkProvider<I> chunkProvider;
private boolean buffering = true;
public ChunkOrientedTasklet(ChunkProvider<I> chunkProvider, ChunkProcessor<I> chunkProcessor) {
this.chunkProvider = chunkProvider;
this.chunkProcessor = chunkProcessor;
}
/**
* Flag to indicate that items should be buffered once read. Defaults to
* true, which is appropriate for forward-only, non-transactional item
* readers. Main (or only) use case for setting this flag to true is a
* transactional JMS item reader.
*
* @param buffering
*/
public void setBuffering(boolean buffering) {
this.buffering = buffering;
}
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
@SuppressWarnings("unchecked")
Chunk<I> inputs = (Chunk<I>) chunkContext.getAttribute(INPUTS_KEY);
if (inputs == null) {
inputs = chunkProvider.provide(contribution);
if (buffering) {
chunkContext.setAttribute(INPUTS_KEY, inputs);
}
}
chunkProcessor.process(contribution, inputs);
chunkContext.removeAttribute(INPUTS_KEY);
chunkContext.setComplete();
chunkProvider.postProcess(contribution, inputs);
if (inputs.isEnd()) {
contribution.setExitStatus(ExitStatus.COMPLETED);
}
return RepeatStatus.continueIf(!inputs.isEnd());
}
}

View File

@@ -23,7 +23,7 @@ import org.springframework.batch.repeat.RepeatStatus;
/**
* A {@link Tasklet} that wraps a method in a POJO. By default the return
* value is {@link ExitStatus#FINISHED} unless the delegate POJO itself returns
* value is {@link ExitStatus#COMPLETED} unless the delegate POJO itself returns
* an {@link ExitStatus}. The POJO method is usually going to have no arguments,
* but a static argument or array of arguments can be used by setting the
* arguments property.
@@ -49,7 +49,7 @@ public class MethodInvokingTaskletAdapter extends AbstractMethodInvokingDelegato
/**
* If the result is an {@link ExitStatus} already just return that,
* otherwise return {@link ExitStatus#FINISHED}.
* otherwise return {@link ExitStatus#COMPLETED}.
*
* @param result the value returned by the delegate method
* @return an {@link ExitStatus} consistent with the result
@@ -58,7 +58,7 @@ public class MethodInvokingTaskletAdapter extends AbstractMethodInvokingDelegato
if (result instanceof ExitStatus) {
return (ExitStatus) result;
}
return ExitStatus.FINISHED;
return ExitStatus.COMPLETED;
}
}

View File

@@ -1,38 +1,38 @@
/*
* 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.core.step.tasklet;
import org.springframework.batch.core.ExitStatus;
/**
* Simple {@link SystemProcessExitCodeMapper} implementation that performs following mapping:
*
* 0 -> ExitStatus.FINISHED
* else -> ExitStatus.FAILED
*
* @author Robert Kasanicky
*/
public class SimpleSystemProcessExitCodeMapper implements SystemProcessExitCodeMapper {
public ExitStatus getExitStatus(int exitCode) {
if (exitCode == 0) {
return ExitStatus.FINISHED;
} else {
return ExitStatus.FAILED;
}
}
}
/*
* 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.core.step.tasklet;
import org.springframework.batch.core.ExitStatus;
/**
* Simple {@link SystemProcessExitCodeMapper} implementation that performs following mapping:
*
* 0 -> ExitStatus.FINISHED
* else -> ExitStatus.FAILED
*
* @author Robert Kasanicky
*/
public class SimpleSystemProcessExitCodeMapper implements SystemProcessExitCodeMapper {
public ExitStatus getExitStatus(int exitCode) {
if (exitCode == 0) {
return ExitStatus.COMPLETED;
} else {
return ExitStatus.FAILED;
}
}
}

View File

@@ -42,7 +42,7 @@ public class ExitStatusTests {
@Test
public void testExitStatusConstantsFinished() {
ExitStatus status = ExitStatus.FINISHED;
ExitStatus status = ExitStatus.COMPLETED;
assertEquals("COMPLETED", status.getExitCode());
}
@@ -104,7 +104,7 @@ public class ExitStatusTests {
*/
@Test
public void testAndExitStatusWhenFinishedAddedToContinuable() {
assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.EXECUTING.and(ExitStatus.FINISHED).getExitCode());
assertEquals(ExitStatus.COMPLETED.getExitCode(), ExitStatus.EXECUTING.and(ExitStatus.COMPLETED).getExitCode());
}
/**
@@ -114,7 +114,7 @@ public class ExitStatusTests {
*/
@Test
public void testAndExitStatusWhenContinuableAddedToFinished() {
assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.FINISHED.and(ExitStatus.EXECUTING).getExitCode());
assertEquals(ExitStatus.COMPLETED.getExitCode(), ExitStatus.COMPLETED.and(ExitStatus.EXECUTING).getExitCode());
}
/**
@@ -134,7 +134,7 @@ public class ExitStatusTests {
*/
@Test
public void testAndExitStatusWhenCustomCompletedAddedToCompleted() {
assertEquals("COMPLETED_CUSTOM", ExitStatus.FINISHED.and(ExitStatus.EXECUTING.replaceExitCode("COMPLETED_CUSTOM")).getExitCode());
assertEquals("COMPLETED_CUSTOM", ExitStatus.COMPLETED.and(ExitStatus.EXECUTING.replaceExitCode("COMPLETED_CUSTOM")).getExitCode());
}
/**
@@ -144,8 +144,8 @@ public class ExitStatusTests {
*/
@Test
public void testAndExitStatusFailedPlusFinished() {
assertEquals("FAILED", ExitStatus.FINISHED.and(ExitStatus.FAILED).getExitCode());
assertEquals("FAILED", ExitStatus.FAILED.and(ExitStatus.FINISHED).getExitCode());
assertEquals("FAILED", ExitStatus.COMPLETED.and(ExitStatus.FAILED).getExitCode());
assertEquals("FAILED", ExitStatus.FAILED.and(ExitStatus.COMPLETED).getExitCode());
}
/**
@@ -155,7 +155,7 @@ public class ExitStatusTests {
*/
@Test
public void testAndExitStatusWhenCustomContinuableAddedToFinished() {
assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.FINISHED.and(
assertEquals(ExitStatus.COMPLETED.getExitCode(), ExitStatus.COMPLETED.and(
ExitStatus.EXECUTING.replaceExitCode("CUSTOM")).getExitCode());
}

View File

@@ -110,8 +110,8 @@ public class StepExecutionTests {
@Test
public void testGetExitCode() {
assertEquals(ExitStatus.EXECUTING, execution.getExitStatus());
execution.setExitStatus(ExitStatus.FINISHED);
assertEquals(ExitStatus.FINISHED, execution.getExitStatus());
execution.setExitStatus(ExitStatus.COMPLETED);
assertEquals(ExitStatus.COMPLETED, execution.getExitStatus());
}
/**

View File

@@ -11,7 +11,7 @@ public class TestTasklet extends AbstractTestComponent implements Tasklet {
public RepeatStatus execute(StepContribution contribution,
ChunkContext chunkContext) throws Exception {
executed = true;
contribution.setExitStatus(ExitStatus.FINISHED);
contribution.setExitStatus(ExitStatus.COMPLETED);
return RepeatStatus.FINISHED;
}

View File

@@ -228,7 +228,7 @@ public class SimpleJobTests {
step2.setStartLimit(5);
job.execute(jobExecution);
assertEquals(2, list.size());
checkRepository(BatchStatus.COMPLETED, ExitStatus.FINISHED);
checkRepository(BatchStatus.COMPLETED, ExitStatus.COMPLETED);
}
@@ -536,7 +536,7 @@ public class SimpleJobTests {
if (runnable != null) {
runnable.run();
}
stepExecution.setExitStatus(ExitStatus.FINISHED);
stepExecution.setExitStatus(ExitStatus.COMPLETED);
stepExecution.setStatus(BatchStatus.COMPLETED);
jobRepository.update(stepExecution);
jobRepository.updateExecutionContext(stepExecution);

View File

@@ -1,270 +1,270 @@
/*
* 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.core.job.flow;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInterruptedException;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.UnexpectedJobExecutionException;
import org.springframework.batch.core.job.flow.support.SimpleFlow;
import org.springframework.batch.core.job.flow.support.StateTransition;
import org.springframework.batch.core.job.flow.support.state.DecisionState;
import org.springframework.batch.core.job.flow.support.state.EndState;
import org.springframework.batch.core.job.flow.support.state.JobExecutionDecider;
import org.springframework.batch.core.job.flow.support.state.StepState;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.core.step.StepSupport;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
/**
* @author Dave Syer
*
*/
public class FlowJobTests {
private FlowJob job = new FlowJob();
private JobExecution jobExecution;
private JobRepository jobRepository;
@Before
public void setUp() throws Exception {
MapJobRepositoryFactoryBean.clear();
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean();
factory.setTransactionManager(new ResourcelessTransactionManager());
factory.afterPropertiesSet();
jobRepository = (JobRepository) factory.getObject();
job.setJobRepository(jobRepository);
jobExecution = jobRepository.createJobExecution("job", new JobParameters());
}
@Test
public void testTwoSteps() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
StepExecution stepExecution = job.doExecute(jobExecution);
assertEquals(ExitStatus.FINISHED, stepExecution.getExitStatus());
assertEquals(2, jobExecution.getStepExecutions().size());
}
@Test
public void testFailedStep() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StepSupport("step1") {
@Override
public void execute(StepExecution stepExecution) throws JobInterruptedException,
UnexpectedJobExecutionException {
stepExecution.setStatus(BatchStatus.FAILED);
stepExecution.setExitStatus(ExitStatus.FAILED);
}
}), "step2"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
StepExecution stepExecution = job.doExecute(jobExecution);
assertEquals(ExitStatus.FINISHED, stepExecution.getExitStatus());
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(2, jobExecution.getStepExecutions().size());
}
@Test
public void testStoppingStep() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StepSupport("step1") {
@Override
public void execute(StepExecution stepExecution) throws JobInterruptedException,
UnexpectedJobExecutionException {
stepExecution.setStatus(BatchStatus.STOPPED);
}
}), "step2"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
try {
job.doExecute(jobExecution);
fail("Expected JobInterruptedException");
}
catch (JobInterruptedException e) {
// expected
}
assertEquals(1, jobExecution.getStepExecutions().size());
}
@Test
public void testEndStateStopped() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end"));
transitions.add(StateTransition.createStateTransition(new EndState(BatchStatus.STOPPED, "end"), "step2"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
try {
job.doExecute(jobExecution);
fail("Expected JobInterruptedException");
}
catch (JobInterruptedException e) {
// expected
}
assertEquals(1, jobExecution.getStepExecutions().size());
}
public void testEndStateFailed() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end"));
transitions.add(StateTransition.createStateTransition(new EndState(BatchStatus.FAILED, "end"), "step2"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
job.doExecute(jobExecution);
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
assertEquals(1, jobExecution.getStepExecutions().size());
}
@Test
public void testEndStateStoppedWithRestart() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end"));
transitions.add(StateTransition.createStateTransition(new EndState(BatchStatus.STOPPED, "end"), "step2"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
// To test a restart we have to use the AbstractJob.execute()...
job.execute(jobExecution);
assertEquals(BatchStatus.STOPPED, jobExecution.getStatus());
assertEquals(1, jobExecution.getStepExecutions().size());
jobExecution = jobRepository.createJobExecution("job", new JobParameters());
job.execute(jobExecution);
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
assertEquals(1, jobExecution.getStepExecutions().size());
}
@Test
public void testBranching() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "COMPLETED",
"step3"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step3"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
StepExecution stepExecution = job.doExecute(jobExecution);
assertEquals(ExitStatus.FINISHED, stepExecution.getExitStatus());
assertEquals(2, jobExecution.getStepExecutions().size());
assertEquals("step3", stepExecution.getStepName());
}
@Test
public void testBasicFlow() throws Throwable {
SimpleFlow flow = new SimpleFlow("job");
Step step = new StubStep("step");
flow.setStateTransitions(Collections.singleton(StateTransition.createEndStateTransition(new StepState(step),
"*")));
job.setFlow(flow);
job.execute(jobExecution);
if (!jobExecution.getAllFailureExceptions().isEmpty()) {
throw jobExecution.getAllFailureExceptions().get(0);
}
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
}
@Test
public void testDecisionFlow() throws Throwable {
SimpleFlow flow = new SimpleFlow("job");
JobExecutionDecider decider = new JobExecutionDecider() {
public String decide(JobExecution jobExecution, StepExecution stepExecution) {
assertNotNull(stepExecution);
return "SWITCH";
}
};
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "*", "decision"));
transitions.add(StateTransition.createStateTransition(new DecisionState(decider, "decision"), "*", "step2"));
transitions.add(StateTransition
.createStateTransition(new DecisionState(decider, "decision"), "SWITCH", "step3"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2")), "*"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step3")), "*"));
flow.setStateTransitions(transitions);
job.setFlow(flow);
StepExecution stepExecution = job.doExecute(jobExecution);
if (!jobExecution.getAllFailureExceptions().isEmpty()) {
throw jobExecution.getAllFailureExceptions().get(0);
}
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(2, jobExecution.getStepExecutions().size());
assertEquals("step3", stepExecution.getStepName());
}
/**
* @author Dave Syer
*
*/
private class StubStep extends StepSupport {
private StubStep(String name) {
super(name);
}
public void execute(StepExecution stepExecution) throws JobInterruptedException {
stepExecution.setStatus(BatchStatus.COMPLETED);
stepExecution.setExitStatus(ExitStatus.FINISHED);
jobRepository.update(stepExecution);
}
}
}
/*
* 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.core.job.flow;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInterruptedException;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.UnexpectedJobExecutionException;
import org.springframework.batch.core.job.flow.support.SimpleFlow;
import org.springframework.batch.core.job.flow.support.StateTransition;
import org.springframework.batch.core.job.flow.support.state.DecisionState;
import org.springframework.batch.core.job.flow.support.state.EndState;
import org.springframework.batch.core.job.flow.support.state.JobExecutionDecider;
import org.springframework.batch.core.job.flow.support.state.StepState;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.core.step.StepSupport;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
/**
* @author Dave Syer
*
*/
public class FlowJobTests {
private FlowJob job = new FlowJob();
private JobExecution jobExecution;
private JobRepository jobRepository;
@Before
public void setUp() throws Exception {
MapJobRepositoryFactoryBean.clear();
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean();
factory.setTransactionManager(new ResourcelessTransactionManager());
factory.afterPropertiesSet();
jobRepository = (JobRepository) factory.getObject();
job.setJobRepository(jobRepository);
jobExecution = jobRepository.createJobExecution("job", new JobParameters());
}
@Test
public void testTwoSteps() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
StepExecution stepExecution = job.doExecute(jobExecution);
assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus());
assertEquals(2, jobExecution.getStepExecutions().size());
}
@Test
public void testFailedStep() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StepSupport("step1") {
@Override
public void execute(StepExecution stepExecution) throws JobInterruptedException,
UnexpectedJobExecutionException {
stepExecution.setStatus(BatchStatus.FAILED);
stepExecution.setExitStatus(ExitStatus.FAILED);
}
}), "step2"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
StepExecution stepExecution = job.doExecute(jobExecution);
assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus());
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(2, jobExecution.getStepExecutions().size());
}
@Test
public void testStoppingStep() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StepSupport("step1") {
@Override
public void execute(StepExecution stepExecution) throws JobInterruptedException,
UnexpectedJobExecutionException {
stepExecution.setStatus(BatchStatus.STOPPED);
}
}), "step2"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
try {
job.doExecute(jobExecution);
fail("Expected JobInterruptedException");
}
catch (JobInterruptedException e) {
// expected
}
assertEquals(1, jobExecution.getStepExecutions().size());
}
@Test
public void testEndStateStopped() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end"));
transitions.add(StateTransition.createStateTransition(new EndState(BatchStatus.STOPPED, "end"), "step2"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
try {
job.doExecute(jobExecution);
fail("Expected JobInterruptedException");
}
catch (JobInterruptedException e) {
// expected
}
assertEquals(1, jobExecution.getStepExecutions().size());
}
public void testEndStateFailed() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end"));
transitions.add(StateTransition.createStateTransition(new EndState(BatchStatus.FAILED, "end"), "step2"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
job.doExecute(jobExecution);
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
assertEquals(1, jobExecution.getStepExecutions().size());
}
@Test
public void testEndStateStoppedWithRestart() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end"));
transitions.add(StateTransition.createStateTransition(new EndState(BatchStatus.STOPPED, "end"), "step2"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
// To test a restart we have to use the AbstractJob.execute()...
job.execute(jobExecution);
assertEquals(BatchStatus.STOPPED, jobExecution.getStatus());
assertEquals(1, jobExecution.getStepExecutions().size());
jobExecution = jobRepository.createJobExecution("job", new JobParameters());
job.execute(jobExecution);
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
assertEquals(1, jobExecution.getStepExecutions().size());
}
@Test
public void testBranching() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "COMPLETED",
"step3"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2"))));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step3"))));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
StepExecution stepExecution = job.doExecute(jobExecution);
assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus());
assertEquals(2, jobExecution.getStepExecutions().size());
assertEquals("step3", stepExecution.getStepName());
}
@Test
public void testBasicFlow() throws Throwable {
SimpleFlow flow = new SimpleFlow("job");
Step step = new StubStep("step");
flow.setStateTransitions(Collections.singleton(StateTransition.createEndStateTransition(new StepState(step),
"*")));
job.setFlow(flow);
job.execute(jobExecution);
if (!jobExecution.getAllFailureExceptions().isEmpty()) {
throw jobExecution.getAllFailureExceptions().get(0);
}
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
}
@Test
public void testDecisionFlow() throws Throwable {
SimpleFlow flow = new SimpleFlow("job");
JobExecutionDecider decider = new JobExecutionDecider() {
public String decide(JobExecution jobExecution, StepExecution stepExecution) {
assertNotNull(stepExecution);
return "SWITCH";
}
};
Collection<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "*", "decision"));
transitions.add(StateTransition.createStateTransition(new DecisionState(decider, "decision"), "*", "step2"));
transitions.add(StateTransition
.createStateTransition(new DecisionState(decider, "decision"), "SWITCH", "step3"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2")), "*"));
transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step3")), "*"));
flow.setStateTransitions(transitions);
job.setFlow(flow);
StepExecution stepExecution = job.doExecute(jobExecution);
if (!jobExecution.getAllFailureExceptions().isEmpty()) {
throw jobExecution.getAllFailureExceptions().get(0);
}
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(2, jobExecution.getStepExecutions().size());
assertEquals("step3", stepExecution.getStepName());
}
/**
* @author Dave Syer
*
*/
private class StubStep extends StepSupport {
private StubStep(String name) {
super(name);
}
public void execute(StepExecution stepExecution) throws JobInterruptedException {
stepExecution.setStatus(BatchStatus.COMPLETED);
stepExecution.setExitStatus(ExitStatus.COMPLETED);
jobRepository.update(stepExecution);
}
}
}

View File

@@ -52,7 +52,7 @@ public class SimpleJobLauncherTests {
private Job job = new JobSupport("foo") {
@Override
public void execute(JobExecution execution) {
execution.setExitStatus(ExitStatus.FINISHED);
execution.setExitStatus(ExitStatus.COMPLETED);
return;
}
};
@@ -81,7 +81,7 @@ public class SimpleJobLauncherTests {
jobLauncher.afterPropertiesSet();
jobLauncher.run(job, jobParameters);
assertEquals(ExitStatus.FINISHED, jobExecution.getExitStatus());
assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
verify(jobRepository);
}
@@ -100,7 +100,7 @@ public class SimpleJobLauncherTests {
@Override
public void execute(JobExecution execution) {
execution.setExitStatus(ExitStatus.FINISHED);
execution.setExitStatus(ExitStatus.COMPLETED);
return;
}
};

View File

@@ -59,7 +59,7 @@ public class CommandLineJobRunnerTests {
@Before
public void setUp() throws Exception {
JobExecution jobExecution = new JobExecution(null, new Long(1));
ExitStatus exitStatus = ExitStatus.FINISHED;
ExitStatus exitStatus = ExitStatus.COMPLETED;
jobExecution.setExitStatus(exitStatus);
StubJobLauncher.jobExecution = jobExecution;
}

View File

@@ -38,7 +38,7 @@ public class SimpleJvmExitCodeMapperTests extends TestCase {
ecm2 = new SimpleJvmExitCodeMapper();
Map<String, Integer> ecm2Map = new HashMap<String, Integer>();
ecm2Map.put(ExitStatus.FINISHED.getExitCode(), new Integer(-1));
ecm2Map.put(ExitStatus.COMPLETED.getExitCode(), new Integer(-1));
ecm2Map.put(ExitStatus.FAILED.getExitCode(), new Integer(-2));
ecm2Map.put(ExitCodeMapper.JOB_NOT_PROVIDED, new Integer(-3));
ecm2Map.put(ExitCodeMapper.NO_SUCH_JOB, new Integer(-3));
@@ -51,7 +51,7 @@ public class SimpleJvmExitCodeMapperTests extends TestCase {
public void testGetExitCodeWithpPredefinedCodes() {
assertEquals(
ecm.intValue(ExitStatus.FINISHED.getExitCode()),
ecm.intValue(ExitStatus.COMPLETED.getExitCode()),
ExitCodeMapper.JVM_EXITCODE_COMPLETED);
assertEquals(
ecm.intValue(ExitStatus.FAILED.getExitCode()),
@@ -65,9 +65,9 @@ public class SimpleJvmExitCodeMapperTests extends TestCase {
}
public void testGetExitCodeWithPredefinedCodesOverridden() {
System.out.println(ecm2.intValue(ExitStatus.FINISHED.getExitCode()));
System.out.println(ecm2.intValue(ExitStatus.COMPLETED.getExitCode()));
assertEquals(
ecm2.intValue(ExitStatus.FINISHED.getExitCode()), -1);
ecm2.intValue(ExitStatus.COMPLETED.getExitCode()), -1);
assertEquals(
ecm2.intValue(ExitStatus.FAILED.getExitCode()), -2);
assertEquals(

View File

@@ -1,154 +1,154 @@
package org.springframework.batch.core.listener;
import static org.junit.Assert.*;
import java.util.Collections;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.util.Assert;
/**
* Tests for {@link ExecutionContextPromotionListener}.
*/
public class ExecutionContextPromotionListenerTests {
private static final String key = "testKey";
private static final String value = "testValue";
private static final String key2 = "testKey2";
private static final String value2 = "testValue2";
private static final String status = "COMPLETED WITH SKIPS";
private static final String status2 = "FAILURE";
private static final String statusWildcard = "COMPL*SKIPS";
/**
* CONDITION: keys = {key1, key2}. statuses is not set (defaults to
* {COMPLETED}).
*
* EXPECTED: key is promoted. key2 is not.
*/
@Test
public void promoteEntry_nullStatuses() throws Exception {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
JobExecution jobExecution = new JobExecution(1L);
StepExecution stepExecution = jobExecution.createStepExecution("step1");
stepExecution.setExitStatus(ExitStatus.FINISHED);
Assert.state(jobExecution.getExecutionContext().isEmpty());
Assert.state(stepExecution.getExecutionContext().isEmpty());
stepExecution.getExecutionContext().putString(key, value);
stepExecution.getExecutionContext().putString(key2, value2);
listener.setKeys(Collections.singletonList(key));
listener.afterPropertiesSet();
listener.afterStep(stepExecution);
assertEquals(value, jobExecution.getExecutionContext().getString(key));
assertFalse(jobExecution.getExecutionContext().containsKey(key2));
}
/**
* CONDITION: keys = {key1, key2}. statuses = {status}. ExitStatus = status
*
* EXPECTED: key is promoted. key2 is not.
*/
@Test
public void promoteEntry_statusFound() throws Exception {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
JobExecution jobExecution = new JobExecution(1L);
StepExecution stepExecution = jobExecution.createStepExecution("step1");
stepExecution.setExitStatus(new ExitStatus(status));
Assert.state(jobExecution.getExecutionContext().isEmpty());
Assert.state(stepExecution.getExecutionContext().isEmpty());
stepExecution.getExecutionContext().putString(key, value);
stepExecution.getExecutionContext().putString(key2, value2);
listener.setKeys(Collections.singletonList(key));
listener.setStatuses(Collections.singletonList(status));
listener.afterPropertiesSet();
listener.afterStep(stepExecution);
assertEquals(value, jobExecution.getExecutionContext().getString(key));
assertFalse(jobExecution.getExecutionContext().containsKey(key2));
}
/**
* CONDITION: keys = {key1, key2}. statuses = {status}. ExitStatus = status2
*
* EXPECTED: no promotions.
*/
@Test
public void promoteEntry_statusNotFound() throws Exception {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
JobExecution jobExecution = new JobExecution(1L);
StepExecution stepExecution = jobExecution.createStepExecution("step1");
stepExecution.setExitStatus(new ExitStatus(status2));
Assert.state(jobExecution.getExecutionContext().isEmpty());
Assert.state(stepExecution.getExecutionContext().isEmpty());
stepExecution.getExecutionContext().putString(key, value);
stepExecution.getExecutionContext().putString(key2, value2);
listener.setKeys(Collections.singletonList(key));
listener.setStatuses(Collections.singletonList(status));
listener.afterPropertiesSet();
listener.afterStep(stepExecution);
assertFalse(jobExecution.getExecutionContext().containsKey(key));
assertFalse(jobExecution.getExecutionContext().containsKey(key2));
}
/**
* CONDITION: keys = {key1, key2}. statuses = {statusWildcard}. ExitStatus =
* status
*
* EXPECTED: key is promoted. key2 is not.
*/
@Test
public void promoteEntry_statusWildcardFound() throws Exception {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
JobExecution jobExecution = new JobExecution(1L);
StepExecution stepExecution = jobExecution.createStepExecution("step1");
stepExecution.setExitStatus(new ExitStatus(status));
Assert.state(jobExecution.getExecutionContext().isEmpty());
Assert.state(stepExecution.getExecutionContext().isEmpty());
stepExecution.getExecutionContext().putString(key, value);
stepExecution.getExecutionContext().putString(key2, value2);
listener.setKeys(Collections.singletonList(key));
listener.setStatuses(Collections.singletonList(statusWildcard));
listener.afterPropertiesSet();
listener.afterStep(stepExecution);
assertEquals(value, jobExecution.getExecutionContext().getString(key));
assertFalse(jobExecution.getExecutionContext().containsKey(key2));
}
/**
* CONDITION: keys = NULL
*
* EXPECTED: IllegalArgumentException
*/
@Test(expected = IllegalArgumentException.class)
public void keysMustBeSet() throws Exception {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
// didn't set the keys, same as listener.setKeys(null);
listener.afterPropertiesSet();
}
}
package org.springframework.batch.core.listener;
import static org.junit.Assert.*;
import java.util.Collections;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.util.Assert;
/**
* Tests for {@link ExecutionContextPromotionListener}.
*/
public class ExecutionContextPromotionListenerTests {
private static final String key = "testKey";
private static final String value = "testValue";
private static final String key2 = "testKey2";
private static final String value2 = "testValue2";
private static final String status = "COMPLETED WITH SKIPS";
private static final String status2 = "FAILURE";
private static final String statusWildcard = "COMPL*SKIPS";
/**
* CONDITION: keys = {key1, key2}. statuses is not set (defaults to
* {COMPLETED}).
*
* EXPECTED: key is promoted. key2 is not.
*/
@Test
public void promoteEntry_nullStatuses() throws Exception {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
JobExecution jobExecution = new JobExecution(1L);
StepExecution stepExecution = jobExecution.createStepExecution("step1");
stepExecution.setExitStatus(ExitStatus.COMPLETED);
Assert.state(jobExecution.getExecutionContext().isEmpty());
Assert.state(stepExecution.getExecutionContext().isEmpty());
stepExecution.getExecutionContext().putString(key, value);
stepExecution.getExecutionContext().putString(key2, value2);
listener.setKeys(Collections.singletonList(key));
listener.afterPropertiesSet();
listener.afterStep(stepExecution);
assertEquals(value, jobExecution.getExecutionContext().getString(key));
assertFalse(jobExecution.getExecutionContext().containsKey(key2));
}
/**
* CONDITION: keys = {key1, key2}. statuses = {status}. ExitStatus = status
*
* EXPECTED: key is promoted. key2 is not.
*/
@Test
public void promoteEntry_statusFound() throws Exception {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
JobExecution jobExecution = new JobExecution(1L);
StepExecution stepExecution = jobExecution.createStepExecution("step1");
stepExecution.setExitStatus(new ExitStatus(status));
Assert.state(jobExecution.getExecutionContext().isEmpty());
Assert.state(stepExecution.getExecutionContext().isEmpty());
stepExecution.getExecutionContext().putString(key, value);
stepExecution.getExecutionContext().putString(key2, value2);
listener.setKeys(Collections.singletonList(key));
listener.setStatuses(Collections.singletonList(status));
listener.afterPropertiesSet();
listener.afterStep(stepExecution);
assertEquals(value, jobExecution.getExecutionContext().getString(key));
assertFalse(jobExecution.getExecutionContext().containsKey(key2));
}
/**
* CONDITION: keys = {key1, key2}. statuses = {status}. ExitStatus = status2
*
* EXPECTED: no promotions.
*/
@Test
public void promoteEntry_statusNotFound() throws Exception {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
JobExecution jobExecution = new JobExecution(1L);
StepExecution stepExecution = jobExecution.createStepExecution("step1");
stepExecution.setExitStatus(new ExitStatus(status2));
Assert.state(jobExecution.getExecutionContext().isEmpty());
Assert.state(stepExecution.getExecutionContext().isEmpty());
stepExecution.getExecutionContext().putString(key, value);
stepExecution.getExecutionContext().putString(key2, value2);
listener.setKeys(Collections.singletonList(key));
listener.setStatuses(Collections.singletonList(status));
listener.afterPropertiesSet();
listener.afterStep(stepExecution);
assertFalse(jobExecution.getExecutionContext().containsKey(key));
assertFalse(jobExecution.getExecutionContext().containsKey(key2));
}
/**
* CONDITION: keys = {key1, key2}. statuses = {statusWildcard}. ExitStatus =
* status
*
* EXPECTED: key is promoted. key2 is not.
*/
@Test
public void promoteEntry_statusWildcardFound() throws Exception {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
JobExecution jobExecution = new JobExecution(1L);
StepExecution stepExecution = jobExecution.createStepExecution("step1");
stepExecution.setExitStatus(new ExitStatus(status));
Assert.state(jobExecution.getExecutionContext().isEmpty());
Assert.state(stepExecution.getExecutionContext().isEmpty());
stepExecution.getExecutionContext().putString(key, value);
stepExecution.getExecutionContext().putString(key2, value2);
listener.setKeys(Collections.singletonList(key));
listener.setStatuses(Collections.singletonList(statusWildcard));
listener.afterPropertiesSet();
listener.afterStep(stepExecution);
assertEquals(value, jobExecution.getExecutionContext().getString(key));
assertFalse(jobExecution.getExecutionContext().containsKey(key2));
}
/**
* CONDITION: keys = NULL
*
* EXPECTED: IllegalArgumentException
*/
@Test(expected = IllegalArgumentException.class)
public void keysMustBeSet() throws Exception {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
// didn't set the keys, same as listener.setKeys(null);
listener.afterPropertiesSet();
}
}

View File

@@ -1,125 +1,125 @@
package org.springframework.batch.core.listener;
import static org.junit.Assert.assertEquals;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.configuration.util.MethodInvoker;
import org.springframework.batch.core.configuration.util.MethodInvokerUtils;
import org.springframework.batch.core.configuration.util.SimpleMethodInvoker;
public class StepListenerMethodInterceptorTests {
MethodInvokerMethodInterceptor interceptor;
TestClass testClass;
@Before
public void setUp(){
testClass = new TestClass();
}
@Test
public void testNormalCase() throws Throwable{
Map<String, Set<MethodInvoker>> invokerMap = new HashMap<String, Set<MethodInvoker>>();
for(Method method : TestClass.class.getMethods()){
invokerMap.put(method.getName(), asSet( new SimpleMethodInvoker(testClass, method)));
}
interceptor = new MethodInvokerMethodInterceptor(invokerMap);
interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method1")));
assertEquals(1, testClass.method1Count);
interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method2")));
assertEquals(1, testClass.method2Count);
}
@Test
public void testMultipleInvokersPerName() throws Throwable{
Map<String, Set<MethodInvoker>> invokerMap = new HashMap<String, Set<MethodInvoker>>();
Set<MethodInvoker> invokers = asSet(MethodInvokerUtils.createMethodInvokerByName(testClass, "method1", false));
invokers.add(MethodInvokerUtils.createMethodInvokerByName(testClass, "method2", false));
invokerMap.put("method1", invokers);
interceptor = new MethodInvokerMethodInterceptor(invokerMap);
interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method1")));
assertEquals(1, testClass.method1Count);
interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method2")));
assertEquals(1, testClass.method2Count);
}
@Test
public void testExitStatusReturn() throws Throwable{
Map<String, Set<MethodInvoker>> invokerMap = new HashMap<String, Set<MethodInvoker>>();
Set<MethodInvoker> invokers = asSet(MethodInvokerUtils.createMethodInvokerByName(testClass, "method3", false));
invokers.add(MethodInvokerUtils.createMethodInvokerByName(testClass, "method3", false));
invokerMap.put("method3", invokers);
interceptor = new MethodInvokerMethodInterceptor(invokerMap);
assertEquals(ExitStatus.FINISHED, interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method3"))));
}
public Set<MethodInvoker> asSet(MethodInvoker methodInvoker){
Set<MethodInvoker> invokerSet = new HashSet<MethodInvoker>();
invokerSet.add(methodInvoker);
return invokerSet;
}
private class TestClass{
int method1Count = 0;
int method2Count = 0;
int method3Count = 0;
public void method1(){
method1Count++;
}
public void method2(){
method2Count++;
}
public ExitStatus method3(){
method3Count++;
return ExitStatus.FINISHED;
}
}
private class StubMethodInvocation implements MethodInvocation{
Method method;
Object[] args;
public StubMethodInvocation(Method method, Object... args) {
this.method = method;
this.args = args;
}
public Method getMethod() {
return method;
}
public Object[] getArguments() {
return null;
}
public AccessibleObject getStaticPart() {
return null;
}
public Object getThis() {
return null;
}
public Object proceed() throws Throwable {
return null;
}
}
package org.springframework.batch.core.listener;
import static org.junit.Assert.assertEquals;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.configuration.util.MethodInvoker;
import org.springframework.batch.core.configuration.util.MethodInvokerUtils;
import org.springframework.batch.core.configuration.util.SimpleMethodInvoker;
public class StepListenerMethodInterceptorTests {
MethodInvokerMethodInterceptor interceptor;
TestClass testClass;
@Before
public void setUp(){
testClass = new TestClass();
}
@Test
public void testNormalCase() throws Throwable{
Map<String, Set<MethodInvoker>> invokerMap = new HashMap<String, Set<MethodInvoker>>();
for(Method method : TestClass.class.getMethods()){
invokerMap.put(method.getName(), asSet( new SimpleMethodInvoker(testClass, method)));
}
interceptor = new MethodInvokerMethodInterceptor(invokerMap);
interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method1")));
assertEquals(1, testClass.method1Count);
interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method2")));
assertEquals(1, testClass.method2Count);
}
@Test
public void testMultipleInvokersPerName() throws Throwable{
Map<String, Set<MethodInvoker>> invokerMap = new HashMap<String, Set<MethodInvoker>>();
Set<MethodInvoker> invokers = asSet(MethodInvokerUtils.createMethodInvokerByName(testClass, "method1", false));
invokers.add(MethodInvokerUtils.createMethodInvokerByName(testClass, "method2", false));
invokerMap.put("method1", invokers);
interceptor = new MethodInvokerMethodInterceptor(invokerMap);
interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method1")));
assertEquals(1, testClass.method1Count);
interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method2")));
assertEquals(1, testClass.method2Count);
}
@Test
public void testExitStatusReturn() throws Throwable{
Map<String, Set<MethodInvoker>> invokerMap = new HashMap<String, Set<MethodInvoker>>();
Set<MethodInvoker> invokers = asSet(MethodInvokerUtils.createMethodInvokerByName(testClass, "method3", false));
invokers.add(MethodInvokerUtils.createMethodInvokerByName(testClass, "method3", false));
invokerMap.put("method3", invokers);
interceptor = new MethodInvokerMethodInterceptor(invokerMap);
assertEquals(ExitStatus.COMPLETED, interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method3"))));
}
public Set<MethodInvoker> asSet(MethodInvoker methodInvoker){
Set<MethodInvoker> invokerSet = new HashSet<MethodInvoker>();
invokerSet.add(methodInvoker);
return invokerSet;
}
private class TestClass{
int method1Count = 0;
int method2Count = 0;
int method3Count = 0;
public void method1(){
method1Count++;
}
public void method2(){
method2Count++;
}
public ExitStatus method3(){
method3Count++;
return ExitStatus.COMPLETED;
}
}
private class StubMethodInvocation implements MethodInvocation{
Method method;
Object[] args;
public StubMethodInvocation(Method method, Object... args) {
this.method = method;
this.args = args;
}
public Method getMethod() {
return method;
}
public Object[] getArguments() {
return null;
}
public AccessibleObject getStaticPart() {
return null;
}
public Object getThis() {
return null;
}
public Object proceed() throws Throwable {
return null;
}
}
}

View File

@@ -1,107 +1,107 @@
/*
* 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.core.partition.support;
import static org.junit.Assert.assertEquals;
import java.util.Collection;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.partition.PartitionHandler;
import org.springframework.batch.core.partition.StepExecutionSplitter;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.core.step.StepSupport;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
/**
* @author Dave Syer
*
*/
public class PartitionStepTests {
private PartitionStep step = new PartitionStep();
private Step remote = new StepSupport("remote");
private JobRepository jobRepository;
@Before
public void setUp() throws Exception {
MapJobRepositoryFactoryBean.clear();
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean();
factory.setTransactionManager(new ResourcelessTransactionManager());
jobRepository = (JobRepository) factory.getObject();
step.setJobRepository(jobRepository);
}
@Test
public void testVanillaStepExecution() throws Exception {
step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, remote));
step.setPartitionHandler(new PartitionHandler() {
public Collection<StepExecution> handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution)
throws Exception {
Set<StepExecution> executions = stepSplitter.split(stepExecution, 2);
for (StepExecution execution : executions) {
execution.setStatus(BatchStatus.COMPLETED);
execution.setExitStatus(ExitStatus.FINISHED);
}
return executions;
}
});
step.afterPropertiesSet();
JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters());
StepExecution stepExecution = jobExecution.createStepExecution("foo");
jobRepository.add(stepExecution);
step.execute(stepExecution);
// one master and two workers
assertEquals(3, stepExecution.getJobExecution().getStepExecutions().size());
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
}
@Test
public void testFailedStepExecution() throws Exception {
step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, remote));
step.setPartitionHandler(new PartitionHandler() {
public Collection<StepExecution> handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution)
throws Exception {
Set<StepExecution> executions = stepSplitter.split(stepExecution, 2);
for (StepExecution execution : executions) {
execution.setStatus(BatchStatus.FAILED);
execution.setExitStatus(ExitStatus.FAILED);
}
return executions;
}
});
step.afterPropertiesSet();
JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters());
StepExecution stepExecution = jobExecution.createStepExecution("foo");
jobRepository.add(stepExecution);
step.execute(stepExecution);
// one master and two workers
assertEquals(3, stepExecution.getJobExecution().getStepExecutions().size());
assertEquals(BatchStatus.FAILED, stepExecution.getStatus());
}
}
/*
* 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.core.partition.support;
import static org.junit.Assert.assertEquals;
import java.util.Collection;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.partition.PartitionHandler;
import org.springframework.batch.core.partition.StepExecutionSplitter;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.core.step.StepSupport;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
/**
* @author Dave Syer
*
*/
public class PartitionStepTests {
private PartitionStep step = new PartitionStep();
private Step remote = new StepSupport("remote");
private JobRepository jobRepository;
@Before
public void setUp() throws Exception {
MapJobRepositoryFactoryBean.clear();
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean();
factory.setTransactionManager(new ResourcelessTransactionManager());
jobRepository = (JobRepository) factory.getObject();
step.setJobRepository(jobRepository);
}
@Test
public void testVanillaStepExecution() throws Exception {
step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, remote));
step.setPartitionHandler(new PartitionHandler() {
public Collection<StepExecution> handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution)
throws Exception {
Set<StepExecution> executions = stepSplitter.split(stepExecution, 2);
for (StepExecution execution : executions) {
execution.setStatus(BatchStatus.COMPLETED);
execution.setExitStatus(ExitStatus.COMPLETED);
}
return executions;
}
});
step.afterPropertiesSet();
JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters());
StepExecution stepExecution = jobExecution.createStepExecution("foo");
jobRepository.add(stepExecution);
step.execute(stepExecution);
// one master and two workers
assertEquals(3, stepExecution.getJobExecution().getStepExecutions().size());
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
}
@Test
public void testFailedStepExecution() throws Exception {
step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, remote));
step.setPartitionHandler(new PartitionHandler() {
public Collection<StepExecution> handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution)
throws Exception {
Set<StepExecution> executions = stepSplitter.split(stepExecution, 2);
for (StepExecution execution : executions) {
execution.setStatus(BatchStatus.FAILED);
execution.setExitStatus(ExitStatus.FAILED);
}
return executions;
}
});
step.afterPropertiesSet();
JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters());
StepExecution stepExecution = jobExecution.createStepExecution("foo");
jobRepository.add(stepExecution);
step.execute(stepExecution);
// one master and two workers
assertEquals(3, stepExecution.getJobExecution().getStepExecutions().size());
assertEquals(BatchStatus.FAILED, stepExecution.getStatus());
}
}

View File

@@ -167,7 +167,7 @@ public abstract class AbstractJobDaoTests {
public void testUpdateJobExecution() {
jobExecution.setStatus(BatchStatus.COMPLETED);
jobExecution.setExitStatus(ExitStatus.FINISHED);
jobExecution.setExitStatus(ExitStatus.COMPLETED);
jobExecution.setEndTime(new Date(System.currentTimeMillis()));
jobExecutionDao.updateJobExecution(jobExecution);

View File

@@ -30,7 +30,7 @@ public class JdbcJobDaoTests extends AbstractJobDaoTests {
assertTrue(LONG_STRING.length() > 250);
((JdbcJobExecutionDao) jobExecutionDao).setExitMessageLength(250);
jobExecution.setExitStatus(ExitStatus.FINISHED
jobExecution.setExitStatus(ExitStatus.COMPLETED
.addExitDescription(LONG_STRING));
jobExecutionDao.updateJobExecution(jobExecution);

View File

@@ -59,7 +59,7 @@ public class AbstractStepTests {
protected void doExecute(StepExecution context) throws Exception {
assertSame(execution, context);
events.add("doExecute");
context.setExitStatus(ExitStatus.FINISHED);
context.setExitStatus(ExitStatus.COMPLETED);
}
protected void close(ExecutionContext ctx) throws Exception {
@@ -180,7 +180,7 @@ public class AbstractStepTests {
assertEquals("close", events.get(i++));
assertEquals(7, events.size());
assertEquals(ExitStatus.FINISHED, execution.getExitStatus());
assertEquals(ExitStatus.COMPLETED, execution.getExitStatus());
assertTrue("Execution context modifications made by listener should be persisted", repository.saved
.containsKey("beforeStep"));

View File

@@ -1,107 +1,107 @@
/*
* Copyright 2006-2009 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.item;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.scope.context.ChunkContext;
/**
* @author Dave Syer
*
*/
public class ChunkOrientedTaskletTests {
private ChunkContext context = new ChunkContext(null);
@Test
public void testHandle() throws Exception {
ChunkOrientedTasklet<String> handler = new ChunkOrientedTasklet<String>(new ChunkProvider<String>() {
public Chunk<String> provide(StepContribution contribution) throws Exception {
contribution.incrementReadCount();
Chunk<String> chunk = new Chunk<String>();
chunk.add("foo");
return chunk;
}
public void postProcess(StepContribution contribution, Chunk<String> chunk) {};
}, new ChunkProcessor<String>() {
public void process(StepContribution contribution, Chunk<String> chunk) {
contribution.incrementWriteCount(1);
}
});
StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution(new JobInstance(
123L, new JobParameters(), "job"))));
handler.execute(contribution, context);
assertEquals(1, contribution.getReadCount());
assertEquals(1, contribution.getWriteCount());
assertEquals(0, context.attributeNames().length);
}
@Test
public void testFail() throws Exception {
ChunkOrientedTasklet<String> handler = new ChunkOrientedTasklet<String>(new ChunkProvider<String>() {
public Chunk<String> provide(StepContribution contribution) throws Exception {
throw new RuntimeException("Foo!");
}
public void postProcess(StepContribution contribution, Chunk<String> chunk) {};
}, new ChunkProcessor<String>() {
public void process(StepContribution contribution, Chunk<String> chunk) {
fail("Not expecting to get this far");
}
});
StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution(new JobInstance(
123L, new JobParameters(), "job"))));
try {
handler.execute(contribution, context);
fail("Expected RuntimeException");
}
catch (RuntimeException e) {
assertEquals("Foo!", e.getMessage());
}
assertEquals(0, contribution.getReadCount());
}
@Test
public void testExitCode() throws Exception {
ChunkOrientedTasklet<String> handler = new ChunkOrientedTasklet<String>(new ChunkProvider<String>() {
public Chunk<String> provide(StepContribution contribution) throws Exception {
contribution.incrementReadCount();
Chunk<String> chunk = new Chunk<String>();
chunk.add("foo");
chunk.setEnd();
return chunk;
}
public void postProcess(StepContribution contribution, Chunk<String> chunk) {};
}, new ChunkProcessor<String>() {
public void process(StepContribution contribution, Chunk<String> chunk) {
contribution.incrementWriteCount(1);
}
});
StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution(new JobInstance(
123L, new JobParameters(), "job"))));
handler.execute(contribution, context);
assertEquals(ExitStatus.FINISHED.getExitCode(), contribution.getExitStatus().getExitCode());
}
}
/*
* Copyright 2006-2009 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.item;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.scope.context.ChunkContext;
/**
* @author Dave Syer
*
*/
public class ChunkOrientedTaskletTests {
private ChunkContext context = new ChunkContext(null);
@Test
public void testHandle() throws Exception {
ChunkOrientedTasklet<String> handler = new ChunkOrientedTasklet<String>(new ChunkProvider<String>() {
public Chunk<String> provide(StepContribution contribution) throws Exception {
contribution.incrementReadCount();
Chunk<String> chunk = new Chunk<String>();
chunk.add("foo");
return chunk;
}
public void postProcess(StepContribution contribution, Chunk<String> chunk) {};
}, new ChunkProcessor<String>() {
public void process(StepContribution contribution, Chunk<String> chunk) {
contribution.incrementWriteCount(1);
}
});
StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution(new JobInstance(
123L, new JobParameters(), "job"))));
handler.execute(contribution, context);
assertEquals(1, contribution.getReadCount());
assertEquals(1, contribution.getWriteCount());
assertEquals(0, context.attributeNames().length);
}
@Test
public void testFail() throws Exception {
ChunkOrientedTasklet<String> handler = new ChunkOrientedTasklet<String>(new ChunkProvider<String>() {
public Chunk<String> provide(StepContribution contribution) throws Exception {
throw new RuntimeException("Foo!");
}
public void postProcess(StepContribution contribution, Chunk<String> chunk) {};
}, new ChunkProcessor<String>() {
public void process(StepContribution contribution, Chunk<String> chunk) {
fail("Not expecting to get this far");
}
});
StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution(new JobInstance(
123L, new JobParameters(), "job"))));
try {
handler.execute(contribution, context);
fail("Expected RuntimeException");
}
catch (RuntimeException e) {
assertEquals("Foo!", e.getMessage());
}
assertEquals(0, contribution.getReadCount());
}
@Test
public void testExitCode() throws Exception {
ChunkOrientedTasklet<String> handler = new ChunkOrientedTasklet<String>(new ChunkProvider<String>() {
public Chunk<String> provide(StepContribution contribution) throws Exception {
contribution.incrementReadCount();
Chunk<String> chunk = new Chunk<String>();
chunk.add("foo");
chunk.setEnd();
return chunk;
}
public void postProcess(StepContribution contribution, Chunk<String> chunk) {};
}, new ChunkProcessor<String>() {
public void process(StepContribution contribution, Chunk<String> chunk) {
contribution.incrementWriteCount(1);
}
});
StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution(new JobInstance(
123L, new JobParameters(), "job"))));
handler.execute(contribution, context);
assertEquals(ExitStatus.COMPLETED.getExitCode(), contribution.getExitStatus().getExitCode());
}
}

View File

@@ -25,7 +25,7 @@ public class ConfigurableSystemProcessExitCodeMapperTests {
public void testMapping() {
Map<Object, ExitStatus> mappings = new HashMap<Object, ExitStatus>() {
{
put(0, ExitStatus.FINISHED);
put(0, ExitStatus.COMPLETED);
put(1, ExitStatus.FAILED);
put(2, ExitStatus.EXECUTING);
put(3, ExitStatus.NOOP);

View File

@@ -19,7 +19,7 @@ public class SimpleSystemProcessExitCodeMapperTests {
*/
@Test
public void testMapping() {
assertEquals(ExitStatus.FINISHED, mapper.getExitStatus(0));
assertEquals(ExitStatus.COMPLETED, mapper.getExitStatus(0));
assertEquals(ExitStatus.FAILED, mapper.getExitStatus(1));
assertEquals(ExitStatus.FAILED, mapper.getExitStatus(-1));
}

View File

@@ -65,7 +65,7 @@ public class StepHandlerAdapterTests {
tasklet.setTargetMethod("process");
StepContribution contribution = stepExecution.createStepContribution();
tasklet.execute(contribution,null);
assertEquals(ExitStatus.FINISHED, contribution.getExitStatus());
assertEquals(ExitStatus.COMPLETED, contribution.getExitStatus());
}
@Test
@@ -74,7 +74,7 @@ public class StepHandlerAdapterTests {
this.result = "foo";
StepContribution contribution = stepExecution.createStepContribution();
tasklet.execute(contribution,null);
assertEquals(ExitStatus.FINISHED, contribution.getExitStatus());
assertEquals(ExitStatus.COMPLETED, contribution.getExitStatus());
}
}

View File

@@ -224,7 +224,7 @@ public class SystemCommandTaskletIntegrationTests {
public ExitStatus getExitStatus(int exitCode) {
if (exitCode == 0) {
return ExitStatus.FINISHED;
return ExitStatus.COMPLETED;
}
else {
return ExitStatus.FAILED;

View File

@@ -231,7 +231,7 @@ public class TaskletStepTests {
}
catch (Exception ex) {
ExitStatus status = stepExecution.getExitStatus();
assertEquals(ExitStatus.FINISHED, status);
assertEquals(ExitStatus.COMPLETED, status);
}
}

View File

@@ -1,195 +1,195 @@
/*
* 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.integration.chunk;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.listener.StepExecutionListenerSupport;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemWriter;
import org.springframework.integration.gateway.MessagingGateway;
import org.springframework.util.Assert;
public class ChunkMessageChannelItemWriter<T> extends StepExecutionListenerSupport implements ItemWriter<T>, ItemStream {
private static final Log logger = LogFactory.getLog(ChunkMessageChannelItemWriter.class);
static final String ACTUAL = ChunkMessageChannelItemWriter.class.getName() + ".ACTUAL";
static final String EXPECTED = ChunkMessageChannelItemWriter.class.getName() + ".EXPECTED";
private static final long DEFAULT_THROTTLE_LIMIT = 6;
private MessagingGateway messagingGateway;
private LocalState localState = new LocalState();
private long throttleLimit = DEFAULT_THROTTLE_LIMIT;
/**
* Public setter for the throttle limit. This limits the number of pending
* requests for chunk processing to avoid overwhelming the receivers.
* @param throttleLimit the throttle limit to set
*/
public void setThrottleLimit(long throttleLimit) {
this.throttleLimit = throttleLimit;
}
public void setMessagingGateway(MessagingGateway messagingGateway) {
this.messagingGateway = messagingGateway;
}
public void write(List<? extends T> items) throws Exception {
// Block until expecting <= throttle limit
while (localState.getExpecting() > throttleLimit) {
getNextResult();
}
if (!items.isEmpty()) {
logger.debug("Dispatching chunk: " + items);
ChunkRequest<T> request = new ChunkRequest<T>(items, localState.getJobId(), localState
.createStepContribution());
messagingGateway.send(request);
localState.expected++;
}
}
@Override
public void beforeStep(StepExecution stepExecution) {
localState.setStepExecution(stepExecution);
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
if (!(stepExecution.getStatus() == BatchStatus.COMPLETED)) {
return ExitStatus.EXECUTING;
}
long expecting = localState.getExpecting();
boolean timedOut;
try {
logger.debug("Waiting for results in step listener...");
timedOut = !waitForResults();
logger.debug("Finished waiting for results in step listener.");
}
catch (RuntimeException e) {
logger.debug("Detected failure waiting for results in step listener.", e);
stepExecution.setStatus(BatchStatus.FAILED);
return ExitStatus.FAILED.addExitDescription(e.getClass().getName() + ": " + e.getMessage());
}
if (timedOut) {
stepExecution.setStatus(BatchStatus.FAILED);
throw new ItemStreamException("Timed out waiting for back log at end of step");
}
return ExitStatus.FINISHED.addExitDescription("Waited for " + expecting + " results.");
}
public void close() throws ItemStreamException {
localState.reset();
}
public void open(ExecutionContext executionContext) throws ItemStreamException {
if (executionContext.containsKey(EXPECTED)) {
localState.expected = executionContext.getLong(EXPECTED);
localState.actual = executionContext.getLong(ACTUAL);
if (!waitForResults()) {
throw new ItemStreamException("Timed out waiting for back log on open");
}
}
}
public void update(ExecutionContext executionContext) throws ItemStreamException {
executionContext.putLong(EXPECTED, localState.expected);
executionContext.putLong(ACTUAL, localState.actual);
}
/**
* Wait until all the results that are in the pipeline come back to the
* reply channel.
*
* @return true if successfully received a result, false if timed out
*/
private boolean waitForResults() {
// TODO: cumulative timeout, or throw an exception?
int count = 0;
int maxCount = 40;
while (localState.getExpecting() > 0 && count++ < maxCount) {
getNextResult();
}
return count < maxCount;
}
/**
* Get the next result if it is available within the timeout specified,
* otherwise return null.
*/
private void getNextResult() {
ChunkResponse payload = (ChunkResponse) messagingGateway.receive();
if (payload != null) {
Long jobInstanceId = payload.getJobId();
Assert.state(jobInstanceId != null, "Message did not contain job instance id.");
Assert.state(jobInstanceId.equals(localState.getJobId()), "Message contained wrong job instance id ["
+ jobInstanceId + "] should have been [" + localState.getJobId() + "].");
localState.actual++;
// TODO: apply the skip count
if (!payload.isSuccessful()) {
throw new AsynchronousFailureException("Failure or interrupt detected in handler: "
+ payload.getMessage());
}
}
}
private static class LocalState {
private long actual;
private long expected;
private StepExecution stepExecution;
public long getExpecting() {
return expected - actual;
}
public StepContribution createStepContribution() {
return stepExecution.createStepContribution();
}
public Long getJobId() {
return stepExecution.getJobExecution().getJobId();
}
public void setStepExecution(StepExecution stepExecution) {
this.stepExecution = stepExecution;
}
public void reset() {
expected = actual = 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.integration.chunk;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.listener.StepExecutionListenerSupport;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemWriter;
import org.springframework.integration.gateway.MessagingGateway;
import org.springframework.util.Assert;
public class ChunkMessageChannelItemWriter<T> extends StepExecutionListenerSupport implements ItemWriter<T>, ItemStream {
private static final Log logger = LogFactory.getLog(ChunkMessageChannelItemWriter.class);
static final String ACTUAL = ChunkMessageChannelItemWriter.class.getName() + ".ACTUAL";
static final String EXPECTED = ChunkMessageChannelItemWriter.class.getName() + ".EXPECTED";
private static final long DEFAULT_THROTTLE_LIMIT = 6;
private MessagingGateway messagingGateway;
private LocalState localState = new LocalState();
private long throttleLimit = DEFAULT_THROTTLE_LIMIT;
/**
* Public setter for the throttle limit. This limits the number of pending
* requests for chunk processing to avoid overwhelming the receivers.
* @param throttleLimit the throttle limit to set
*/
public void setThrottleLimit(long throttleLimit) {
this.throttleLimit = throttleLimit;
}
public void setMessagingGateway(MessagingGateway messagingGateway) {
this.messagingGateway = messagingGateway;
}
public void write(List<? extends T> items) throws Exception {
// Block until expecting <= throttle limit
while (localState.getExpecting() > throttleLimit) {
getNextResult();
}
if (!items.isEmpty()) {
logger.debug("Dispatching chunk: " + items);
ChunkRequest<T> request = new ChunkRequest<T>(items, localState.getJobId(), localState
.createStepContribution());
messagingGateway.send(request);
localState.expected++;
}
}
@Override
public void beforeStep(StepExecution stepExecution) {
localState.setStepExecution(stepExecution);
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
if (!(stepExecution.getStatus() == BatchStatus.COMPLETED)) {
return ExitStatus.EXECUTING;
}
long expecting = localState.getExpecting();
boolean timedOut;
try {
logger.debug("Waiting for results in step listener...");
timedOut = !waitForResults();
logger.debug("Finished waiting for results in step listener.");
}
catch (RuntimeException e) {
logger.debug("Detected failure waiting for results in step listener.", e);
stepExecution.setStatus(BatchStatus.FAILED);
return ExitStatus.FAILED.addExitDescription(e.getClass().getName() + ": " + e.getMessage());
}
if (timedOut) {
stepExecution.setStatus(BatchStatus.FAILED);
throw new ItemStreamException("Timed out waiting for back log at end of step");
}
return ExitStatus.COMPLETED.addExitDescription("Waited for " + expecting + " results.");
}
public void close() throws ItemStreamException {
localState.reset();
}
public void open(ExecutionContext executionContext) throws ItemStreamException {
if (executionContext.containsKey(EXPECTED)) {
localState.expected = executionContext.getLong(EXPECTED);
localState.actual = executionContext.getLong(ACTUAL);
if (!waitForResults()) {
throw new ItemStreamException("Timed out waiting for back log on open");
}
}
}
public void update(ExecutionContext executionContext) throws ItemStreamException {
executionContext.putLong(EXPECTED, localState.expected);
executionContext.putLong(ACTUAL, localState.actual);
}
/**
* Wait until all the results that are in the pipeline come back to the
* reply channel.
*
* @return true if successfully received a result, false if timed out
*/
private boolean waitForResults() {
// TODO: cumulative timeout, or throw an exception?
int count = 0;
int maxCount = 40;
while (localState.getExpecting() > 0 && count++ < maxCount) {
getNextResult();
}
return count < maxCount;
}
/**
* Get the next result if it is available within the timeout specified,
* otherwise return null.
*/
private void getNextResult() {
ChunkResponse payload = (ChunkResponse) messagingGateway.receive();
if (payload != null) {
Long jobInstanceId = payload.getJobId();
Assert.state(jobInstanceId != null, "Message did not contain job instance id.");
Assert.state(jobInstanceId.equals(localState.getJobId()), "Message contained wrong job instance id ["
+ jobInstanceId + "] should have been [" + localState.getJobId() + "].");
localState.actual++;
// TODO: apply the skip count
if (!payload.isSuccessful()) {
throw new AsynchronousFailureException("Failure or interrupt detected in handler: "
+ payload.getMessage());
}
}
}
private static class LocalState {
private long actual;
private long expected;
private StepExecution stepExecution;
public long getExpecting() {
return expected - actual;
}
public StepContribution createStepContribution() {
return stepExecution.createStepContribution();
}
public Long getJobId() {
return stepExecution.getJobExecution().getJobId();
}
public void setStepExecution(StepExecution stepExecution) {
this.stepExecution = stepExecution;
}
public void reset() {
expected = actual = 0;
}
}
}

View File

@@ -116,7 +116,7 @@ public class MessageOrientedStep extends AbstractStep {
waitForReply(request.getJobId());
}
stepExecution.setExitStatus(ExitStatus.FINISHED);
stepExecution.setExitStatus(ExitStatus.COMPLETED);
}

View File

@@ -32,7 +32,7 @@ public class TestTasklet implements Tasklet {
*
*/
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
contribution.setExitStatus(ExitStatus.FINISHED);
contribution.setExitStatus(ExitStatus.COMPLETED);
return RepeatStatus.FINISHED;
}

View File

@@ -1,19 +1,19 @@
package org.springframework.batch.sample.common;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.support.state.JobExecutionDecider;
public class SkipCheckingDecider implements JobExecutionDecider {
public String decide(JobExecution jobExecution, StepExecution stepExecution) {
if (!stepExecution.getExitStatus().getExitCode().equals(
ExitStatus.FAILED.getExitCode())
&& stepExecution.getSkipCount() > 0) {
return "COMPLETED WITH SKIPS";
} else {
return ExitStatus.FINISHED.getExitCode();
}
}
package org.springframework.batch.sample.common;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.support.state.JobExecutionDecider;
public class SkipCheckingDecider implements JobExecutionDecider {
public String decide(JobExecution jobExecution, StepExecution stepExecution) {
if (!stepExecution.getExitStatus().getExitCode().equals(
ExitStatus.FAILED.getExitCode())
&& stepExecution.getSkipCount() > 0) {
return "COMPLETED WITH SKIPS";
} else {
return ExitStatus.COMPLETED.getExitCode();
}
}
}