diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParser.java index 6be487047..df97303dd 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParser.java @@ -100,13 +100,15 @@ public class StepParser { } /** - * @param parserContext - * @param stateDef - * @param element - * @return a collection of {@link org.springframework.batch.core.job.flow.support.StateTransition} references + * @param parserContext the parser context for the bean factory + * @param stateDef The bean definition for the current state + * @param element the <step/gt; element to parse + * @return a collection of + * {@link org.springframework.batch.core.job.flow.support.StateTransition} + * references */ - public static Collection getNextElements(ParserContext parserContext, - BeanDefinition stateDef, Element element) { + protected static Collection getNextElements(ParserContext parserContext, BeanDefinition stateDef, + Element element) { Collection list = new ArrayList(); @@ -116,94 +118,139 @@ public class StepParser { list.add(getStateTransitionReference(parserContext, stateDef, null, shortNextAttribute)); } - boolean transitionExists = false; - for(String transitionName : new String[]{NEXT, PAUSE, END, FAIL}) - { + boolean transitionElementExists = false; + List patterns = new ArrayList(); + for (String transitionName : new String[] { NEXT, PAUSE, END, FAIL }) { @SuppressWarnings("unchecked") - List transitionElements = (List) DomUtils.getChildElementsByTagName(element, transitionName); + List transitionElements = (List) DomUtils.getChildElementsByTagName(element, + transitionName); for (Element transitionElement : transitionElements) { - parseTransitionElement(parserContext, stateDef, element, list, hasNextAttribute, transitionElement); - transitionExists = true; + verifyUniquePattern(element, parserContext, hasNextAttribute, transitionElement, patterns); + list.addAll(parseTransitionElement(transitionElement, stateDef, parserContext)); + transitionElementExists = true; } } - if(hasNextAttribute && !transitionExists) - { - list.add(getStateTransitionReference(parserContext, stateDef, ExitStatus.FAILED.getExitCode(), null)); - } - - if (list.isEmpty() && !hasNextAttribute) { - list.add(getStateTransitionReference(parserContext, stateDef, null, null)); + if (!transitionElementExists) { + list.addAll(createTransition(BatchStatus.FAILED, ExitStatus.FAILED.getExitCode(), null, null, stateDef, + parserContext)); + if (!hasNextAttribute) { + list.addAll(createTransition(BatchStatus.COMPLETED, null, null, null, stateDef, parserContext)); + } } return list; } /** - * @param parserContext - * @param stateDef * @param element - * @param list + * @param parserContext the parser context for the bean factory * @param hasNextAttribute - * @param transitionElement + * @param transitionElement The element to parse + * @param patterns a list of patterns on state transitions for this element */ - private static void parseTransitionElement(ParserContext parserContext, BeanDefinition stateDef, Element element, - Collection list, boolean hasNextAttribute, Element transitionElement) { + private static void verifyUniquePattern(Element element, ParserContext parserContext, boolean hasNextAttribute, + Element transitionElement, List patterns) { String onAttribute = transitionElement.getAttribute("on"); - String nextAttribute = transitionElement.getAttribute("to"); if (hasNextAttribute && onAttribute.equals("*")) { - parserContext.getReaderContext().error("Duplicate transition pattern found for '*' " - + "(only specify one of next= attribute at step level and next element with on='*')", + parserContext.getReaderContext().error( + "Duplicate transition pattern found. " + + "Specify one of next= attribute at step level and next element with on='*'", element); + } + if (patterns.contains(onAttribute)) { + parserContext.getReaderContext().error("Duplicate transition pattern found for '" + onAttribute + "'", element); } - - RuntimeBeanReference endState = null; - - String name = transitionElement.getNodeName(); - if (PAUSE.equals(name) || END.equals(name) || FAIL.equals(name)) { - - BatchStatus batchStatus = getBatchStatusFromEndTransitionName(name); - BeanDefinitionBuilder endBuilder = - BeanDefinitionBuilder.genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.EndState"); - endBuilder.addConstructorArgValue(batchStatus); - - String statusName = transitionElement.getAttribute("status"); - String exitStatus = StringUtils.hasText(statusName) ? statusName : batchStatus.toString(); - endBuilder.addConstructorArgValue(new ExitStatus(exitStatus)); - - String endName = "end" + (endCounter++); - endBuilder.addConstructorArgValue(endName); - - String nextOnEnd = StringUtils.hasText(statusName) ? null : nextAttribute; - endState = getStateTransitionReference(parserContext, endBuilder.getBeanDefinition(), "*", nextOnEnd); - nextAttribute = endName; - - } - list.add(getStateTransitionReference(parserContext, stateDef, onAttribute, nextAttribute)); - if(endState != null) - { - // - // Must be added after the state to ensure that the state is the first in the list - // - list.add(endState); - } + patterns.add(onAttribute); } /** - * @param name An end transition name + * @param transitionElement The element to parse + * @param stateDef The bean definition for the current state + * @param parserContext the parser context for the bean factory + * @param a collection of + * {@link org.springframework.batch.core.job.flow.support.StateTransition} + * references + */ + private static Collection parseTransitionElement(Element transitionElement, + BeanDefinition stateDef, ParserContext parserContext) { + + BatchStatus batchStatus = getBatchStatusFromEndTransitionName(transitionElement.getNodeName()); + String onAttribute = transitionElement.getAttribute("on"); + String nextAttribute = transitionElement.getAttribute("to"); + String statusAttribute = transitionElement.getAttribute("status"); + + return createTransition(batchStatus, onAttribute, nextAttribute, statusAttribute, stateDef, parserContext); + } + + /** + * @param batchStatus The batch status that this transition will set. Use + * BatchStatus.UNKNOWN if not applicable. + * @param on The pattern that this transition should match. Use null for + * "no restriction" (same as "*"). + * @param next The state to which this transition should go. Use null if not + * applicable. + * @param exitCode The exit code that this transition will set. Use null to + * default to batchStatus. + * @param stateDef The bean definition for the current state + * @param parserContext the parser context for the bean factory + * @param a collection of + * {@link org.springframework.batch.core.job.flow.support.StateTransition} + * references + */ + private static Collection createTransition(BatchStatus batchStatus, String on, String next, + String exitCode, BeanDefinition stateDef, ParserContext parserContext) { + + RuntimeBeanReference endState = null; + + if (batchStatus == BatchStatus.STOPPED || batchStatus == BatchStatus.COMPLETED + || batchStatus == BatchStatus.FAILED) { + + BeanDefinitionBuilder endBuilder = BeanDefinitionBuilder + .genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.EndState"); + endBuilder.addConstructorArgValue(batchStatus); + + boolean exitCodeExists = StringUtils.hasText(exitCode); + endBuilder.addConstructorArgValue(new ExitStatus(exitCodeExists ? exitCode : batchStatus.toString())); + + String endName = "end" + (endCounter++); + endBuilder.addConstructorArgValue(endName); + + String nextOnEnd = exitCodeExists ? null : next; + endState = getStateTransitionReference(parserContext, endBuilder.getBeanDefinition(), null, nextOnEnd); + next = endName; + + } + + Collection list = new ArrayList(); + list.add(getStateTransitionReference(parserContext, stateDef, on, next)); + if (endState != null) { + // + // Must be added after the state to ensure that the state is the + // first in the list + // + list.add(endState); + } + return list; + } + + /** + * @param elementName An end transition element name * @return the BatchStatus corresponding to the transition name */ - private static BatchStatus getBatchStatusFromEndTransitionName(String name) { - if(PAUSE.equals(name)){ + private static BatchStatus getBatchStatusFromEndTransitionName(String elementName) { + if (PAUSE.equals(elementName)) { return BatchStatus.STOPPED; } - else if(END.equals(name)){ + else if (END.equals(elementName)) { return BatchStatus.COMPLETED; } - else if(FAIL.equals(name)){ + else if (FAIL.equals(elementName)) { return BatchStatus.FAILED; } - throw new IllegalStateException("No BatchStatus defined for transition: [" + name + "]"); + else { + return BatchStatus.UNKNOWN; + } } /** diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java index 330617bf3..79f2f8c53 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java @@ -209,13 +209,11 @@ public abstract class AbstractJob implements Job, BeanNameAware, InitializingBea * processing to {@link #handleStep(Step, JobExecution)}. * * @param execution the current {@link JobExecution} - * @return the last {@link StepExecution} (used to compute the final status - * of the {@link JobExecution}) * * @throws JobExecutionException to signal a fatal batch framework error * (not a business or validation exception) */ - abstract protected StepExecution doExecute(JobExecution execution) throws JobExecutionException; + abstract protected void doExecute(JobExecution execution) throws JobExecutionException; /** * Run the specified job, handling all listener and repository calls, and @@ -236,12 +234,7 @@ public abstract class AbstractJob implements Job, BeanNameAware, InitializingBea listener.beforeJob(execution); - StepExecution lastStepExecution = doExecute(execution); - - if (lastStepExecution != null) { - execution.upgradeStatus(lastStepExecution.getStatus()); - execution.setExitStatus(lastStepExecution.getExitStatus()); - } + doExecute(execution); } else { @@ -322,7 +315,7 @@ public abstract class AbstractJob implements Job, BeanNameAware, InitializingBea currentStepExecution = execution.createStepExecution(step.getName()); boolean isRestart = (lastStepExecution != null && !lastStepExecution.getStatus().equals( - BatchStatus.COMPLETED)) ? true : false; + BatchStatus.COMPLETED)); if (isRestart) { currentStepExecution.setExecutionContext(lastStepExecution.getExecutionContext()); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java index 0afbac13d..a977e30e2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java @@ -80,22 +80,30 @@ public class SimpleJob extends AbstractJob { * successfully processed if it exists, and null if none were processed. * * @param execution the current {@link JobExecution} - * @return the last successful {@link StepExecution} * * @see AbstractJob#handleStep(Step, JobExecution) */ - protected StepExecution doExecute(JobExecution execution) throws JobInterruptedException, JobRestartException, + protected void doExecute(JobExecution execution) throws JobInterruptedException, JobRestartException, StartLimitExceededException { StepExecution stepExecution = null; for (Step step : steps) { stepExecution = handleStep(step, execution); if (stepExecution.getStatus() != BatchStatus.COMPLETED) { - return stepExecution; + // + // Terminate the job if a step fails + // + break; } } - return stepExecution; + // + // Update the job status to be the same as the last step + // + if(stepExecution != null) { + execution.upgradeStatus(stepExecution.getStatus()); + execution.setExitStatus(stepExecution.getExitStatus()); + } } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java index 945dafdf8..feda8ff0b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java @@ -26,7 +26,6 @@ import org.springframework.batch.core.job.AbstractJob; import org.springframework.batch.core.job.flow.support.State; import org.springframework.batch.core.job.flow.support.state.StepState; import org.springframework.batch.core.repository.JobRestartException; -import org.springframework.util.Assert; /** @@ -75,10 +74,9 @@ public class FlowJob extends AbstractJob { * @see AbstractJob#doExecute(JobExecution) */ @Override - protected StepExecution doExecute(final JobExecution execution) throws JobExecutionException { + protected void doExecute(final JobExecution execution) throws JobExecutionException { try { - FlowExecution result = flow.start(new JobFlowExecutor(execution)); - return getLastStepExecution(execution, result); + flow.start(new JobFlowExecutor(execution)); } catch (FlowExecutionException e) { if (e.getCause() instanceof JobExecutionException) { @@ -88,50 +86,6 @@ public class FlowJob extends AbstractJob { } } - /** - * @param execution the current {@link JobExecution} - * @param result the result of the flow execution - * @return a {@link StepExecution} with matching properties to the result - */ - private StepExecution getLastStepExecution(JobExecution execution, FlowExecution result) { - StepExecution value = null; - StepExecution backup = null; - for (StepExecution stepExecution : execution.getStepExecutions()) { - if (stepExecution.getStepName().equals(result.getName()) - && stepExecution.getExitStatus().getExitCode().equals(result.getStatus())) { - value = stepExecution; - } - if (isLater(stepExecution, backup)) { - backup = stepExecution; - } - } - if (value==null) { - value = backup; - } - Assert.state(value != null, String.format( - "Could not locate step execution matching expected properties: flowExecution=%s, stepExecutions=%s", - result, execution.getStepExecutions())); - return value; - } - - /** - * @param first - * @param second - * @return true if the first is deemed to be executed after the second - */ - private boolean isLater(StepExecution first, StepExecution second) { - if (second==null) { - return true; - } - if (first.getEndTime()==null) { - return first.getStartTime().after(second.getStartTime()); - } - if (second.getEndTime()==null) { - return false; - } - return first.getEndTime().after(second.getEndTime()); - } - /** * @author Dave Syer * diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/EndState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/EndState.java index 448e5d80b..2e58379b0 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/EndState.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/EndState.java @@ -36,14 +36,19 @@ public class EndState extends AbstractState { private final ExitStatus exitStatus; /** - * @param name + * ExitStatus will be defaulted to the given BatchStatus + * + * @param status The BatchStatus to end with + * @param name The name of the state */ public EndState(BatchStatus status, String name) { this(status, new ExitStatus(status.toString()), name); } /** - * @param name + * @param status The BatchStatus to end with + * @param exitStatus The ExitStatus to end with + * @param name The name of the state */ public EndState(BatchStatus status, ExitStatus exitStatus, String name) { super(name); @@ -65,8 +70,17 @@ public class EndState extends AbstractState { // restart synchronized (jobExecution) { if (!jobExecution.getStepExecutions().isEmpty()) { + BatchStatus beforeStatus = jobExecution.getStatus(); + jobExecution.upgradeStatus(status); - jobExecution.setExitStatus(exitStatus); + + // + // If the status was changed or the target status is the same as the old + // + if(beforeStatus != jobExecution.getStatus() || beforeStatus == status) + { + jobExecution.setExitStatus(exitStatus); + } } return FlowExecution.COMPLETED; } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AbstractJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AbstractJobParserTests.java new file mode 100644 index 000000000..dd87f88b8 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AbstractJobParserTests.java @@ -0,0 +1,78 @@ +/* + * 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.configuration.xml; + +import static org.junit.Assert.fail; + +import java.util.ArrayList; + +import org.junit.Before; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.JobRestartException; +import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @author Dan Garrette + * @since 2.0 + */ +public abstract class AbstractJobParserTests { + + @Autowired + protected Job job; + + @Autowired + private JobRepository jobRepository; + + @Autowired + protected ArrayList stepNamesList = new ArrayList(); + + @Before + public void setUp() { + MapJobRepositoryFactoryBean.clear(); + stepNamesList.clear(); + } + + /** + * @return JobExecution + */ + protected JobExecution createJobExecution() throws JobInstanceAlreadyCompleteException, JobRestartException, + JobExecutionAlreadyRunningException { + return jobRepository.createJobExecution(job.getName(), new JobParameters()); + } + + /** + * @param jobExecution + * @param stepName + * @return the StepExecution corresponding to the specified step + */ + protected StepExecution getStepExecution(JobExecution jobExecution, String stepName) { + for (StepExecution stepExecution : jobExecution.getStepExecutions()) { + if (stepExecution.getStepName().equals(stepName)) { + return stepExecution; + } + } + fail("No stepExecution found with name: [" + stepName + "]"); + return null; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultFailureJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultFailureJobParserTests.java new file mode 100644 index 000000000..f19fb04a1 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultFailureJobParserTests.java @@ -0,0 +1,60 @@ +/* + * 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.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class DefaultFailureJobParserTests extends AbstractJobParserTests { + + @Test + public void testDefaultFailure() throws Exception { + + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(2, stepNamesList.size()); + assertTrue(stepNamesList.contains("step1")); + assertTrue(stepNamesList.contains("failingStep")); + + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "step1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "failingStep"); + assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultSuccessJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultSuccessJobParserTests.java new file mode 100644 index 000000000..ef8487768 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultSuccessJobParserTests.java @@ -0,0 +1,60 @@ +/* + * 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.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class DefaultSuccessJobParserTests extends AbstractJobParserTests { + + @Test + public void testDefaultSuccess() throws Exception { + + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(2, stepNamesList.size()); + assertTrue(stepNamesList.contains("step1")); + assertTrue(stepNamesList.contains("step2")); + + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "step1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "step2"); + assertEquals(BatchStatus.COMPLETED, stepExecution2.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution2.getExitStatus()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DuplicateTransitionJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DuplicateTransitionJobParserTests.java new file mode 100644 index 000000000..7ba6a1b27 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DuplicateTransitionJobParserTests.java @@ -0,0 +1,44 @@ +/* + * 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.configuration.xml; + +import org.junit.Test; +import org.junit.internal.runners.JUnit4ClassRunner; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.BeanDefinitionStoreException; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.util.ClassUtils; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@RunWith(JUnit4ClassRunner.class) +public class DuplicateTransitionJobParserTests extends AbstractJobParserTests { + + @Test(expected = BeanDefinitionStoreException.class) + public void testNextAttributeWithNestedElement() throws Exception { + new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath(getClass(), + "NextAttributeMultipleFinalJobParserTests-context.xml")); + } + + @Test(expected = BeanDefinitionStoreException.class) + public void testDuplicateTransition() throws Exception { + new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath(getClass(), + "DuplicateTransitionJobParserTests-context.xml")); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionDefaultStatusJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionDefaultStatusJobParserTests.java index 5f006ecff..33d7b1425 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionDefaultStatusJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionDefaultStatusJobParserTests.java @@ -16,20 +16,14 @@ package org.springframework.batch.core.configuration.xml; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import java.util.ArrayList; - -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.batch.core.Job; +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.repository.JobRepository; -import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.batch.core.StepExecution; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -39,33 +33,22 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class EndTransitionDefaultStatusJobParserTests { - - @Autowired - private Job job; - - @Autowired - private JobRepository jobRepository; - - @Autowired - private ArrayList stepNamesList; - - @Before - public void setUp() { - MapJobRepositoryFactoryBean.clear(); - } +public class EndTransitionDefaultStatusJobParserTests extends AbstractJobParserTests { @Test public void testEndTransitionDefaultStatus() throws Exception { - assertNotNull(job); - JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters()); + JobExecution jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(1, stepNamesList.size()); assertTrue(stepNamesList.contains("failingStep")); - // TODO: BATCH-1011 - // assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - // assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "failingStep"); + assertEquals(BatchStatus.FAILED, stepExecution1.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution1.getExitStatus().getExitCode()); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionJobParserTests.java index 8ad02d338..c1a2b881c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionJobParserTests.java @@ -16,21 +16,16 @@ package org.springframework.batch.core.configuration.xml; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; -import java.util.ArrayList; - -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.batch.core.Job; +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.StepExecution; import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -40,51 +35,43 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class EndTransitionJobParserTests { - - @Autowired - private Job job; - - @Autowired - private JobRepository jobRepository; - - @Autowired - private ArrayList stepNamesList; - - @Before - public void setUp() { - MapJobRepositoryFactoryBean.clear(); - } +public class EndTransitionJobParserTests extends AbstractJobParserTests { @Test public void testEndTransition() throws Exception { - + // // First Launch // - assertNotNull(job); - JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters()); + JobExecution jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(2, stepNamesList.size()); assertTrue(stepNamesList.contains("step1")); assertTrue(stepNamesList.contains("failingStep")); - // TODO: BATCH-1011 - // assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - // assertEquals("EARLY TERMINATION (FAIL)", jobExecution.getExitStatus().getExitCode()); + + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals("EARLY TERMINATION (FAIL)", jobExecution.getExitStatus().getExitCode()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "step1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "failingStep"); + assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); // // Second Launch // stepNamesList.clear(); - try{ - jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters()); - // TODO: BATCH-1011 - //fail("JobInstanceAlreadyCompleteException expected"); + try { + jobExecution = createJobExecution(); + fail("JobInstanceAlreadyCompleteException expected"); + } catch (JobInstanceAlreadyCompleteException e) { + // + // Expected + // } - catch(JobInstanceAlreadyCompleteException e) - { - - } - + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionDefaultStatusJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionDefaultStatusJobParserTests.java index ff20631d3..80d7c9444 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionDefaultStatusJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionDefaultStatusJobParserTests.java @@ -16,21 +16,14 @@ package org.springframework.batch.core.configuration.xml; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import java.util.ArrayList; - -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.batch.core.StepExecution; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -40,33 +33,22 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class FailTransitionDefaultStatusJobParserTests { - - @Autowired - private Job job; - - @Autowired - private JobRepository jobRepository; - - @Autowired - private ArrayList stepNamesList; - - @Before - public void setUp() { - MapJobRepositoryFactoryBean.clear(); - } +public class FailTransitionDefaultStatusJobParserTests extends AbstractJobParserTests { @Test public void testFailTransitionDefaultStatus() throws Exception { - assertNotNull(job); - JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters()); + JobExecution jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(1, stepNamesList.size()); assertTrue(stepNamesList.contains("step1")); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - // TODO: BATCH-1011 - // assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); + assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "step1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionJobParserTests.java index a2e33f9bc..1383c7611 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionJobParserTests.java @@ -16,21 +16,14 @@ package org.springframework.batch.core.configuration.xml; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import java.util.ArrayList; - -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.batch.core.StepExecution; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -40,49 +33,46 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class FailTransitionJobParserTests { - - @Autowired - private Job job; - - @Autowired - private JobRepository jobRepository; - - @Autowired - private ArrayList stepNamesList; - - @Before - public void setUp() { - MapJobRepositoryFactoryBean.clear(); - } +public class FailTransitionJobParserTests extends AbstractJobParserTests { @Test public void testFailTransition() throws Exception { - + // // First Launch // - assertNotNull(job); - JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters()); + JobExecution jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(2, stepNamesList.size()); assertTrue(stepNamesList.contains("step1")); assertTrue(stepNamesList.contains("failingStep")); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - // TODO: BATCH-1011 - // assertEquals("EARLY TERMINATION (FAIL)", jobExecution.getExitStatus().getExitCode()); + assertEquals("EARLY TERMINATION (FAIL)", jobExecution.getExitStatus().getExitCode()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "step1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "failingStep"); + assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); // // Second Launch // stepNamesList.clear(); - jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters()); + jobExecution = createJobExecution(); job.execute(jobExecution); - assertEquals(1, stepNamesList.size()); //step1 is not executed + assertEquals(1, stepNamesList.size()); // step1 is not executed assertTrue(stepNamesList.contains("failingStep")); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - // TODO: BATCH-1011 - // assertEquals("EARLY TERMINATION (FAIL)", jobExecution.getExitStatus().getExitCode()); + assertEquals("EARLY TERMINATION (FAIL)", jobExecution.getExitStatus().getExitCode()); + + StepExecution stepExecution3 = getStepExecution(jobExecution, "failingStep"); + assertEquals(BatchStatus.FAILED, stepExecution3.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution3.getExitStatus().getExitCode()); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NextAttributeJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NextAttributeJobParserTests.java index f8b5591ed..4117f72c3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NextAttributeJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NextAttributeJobParserTests.java @@ -17,8 +17,6 @@ package org.springframework.batch.core.configuration.xml; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import org.junit.Before; import org.junit.Test; @@ -29,12 +27,9 @@ import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; -import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.util.ClassUtils; /** * @author Dave Syer @@ -64,18 +59,4 @@ public class NextAttributeJobParserTests { assertEquals(2, jobExecution.getStepExecutions().size()); } - @Test - public void testNextAttributeWithNestedElement() throws Exception { - try { - new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath(getClass(), - "NextAttributeMultipleFinalJobParserTests-context.xml")); - fail("Expected BeanCreationException"); - } - catch (BeanDefinitionStoreException e) { - // expected - String message = e.getMessage(); - assertTrue("Wrong message; " + message, message.contains("Duplicate transition pattern")); - } - } - } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailFirstJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailFirstJobParserTests.java new file mode 100644 index 000000000..2b81fa0b1 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailFirstJobParserTests.java @@ -0,0 +1,60 @@ +/* + * 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.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class SplitDifferentResultsFailFirstJobParserTests extends AbstractJobParserTests { + + @Test + public void testSplitDifferentResultsFailFirst() throws Exception { + + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(2, stepNamesList.size()); + assertTrue(stepNamesList.contains("step1")); + assertTrue(stepNamesList.contains("failingStep")); + + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "step1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "failingStep"); + assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests.java new file mode 100644 index 000000000..e66b1d1ed --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests.java @@ -0,0 +1,60 @@ +/* + * 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.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class SplitDifferentResultsFailSecondJobParserTests extends AbstractJobParserTests { + + @Test + public void testSplitDifferentResultsFailSecond() throws Exception { + + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(2, stepNamesList.size()); + assertTrue(stepNamesList.contains("step1")); + assertTrue(stepNamesList.contains("failingStep")); + + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "step1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "failingStep"); + assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopJobParserTests.java index ab7e4c111..92c0ef7a0 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopJobParserTests.java @@ -16,25 +16,15 @@ package org.springframework.batch.core.configuration.xml; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import java.util.ArrayList; - -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.job.flow.JobExecutionDecider; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -44,50 +34,42 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class StopJobParserTests { - - @Autowired - @Qualifier("job") - private Job job; - - @Autowired - private JobRepository jobRepository; - - @Autowired - private ArrayList stepNamesList; - - @Before - public void setUp() { - MapJobRepositoryFactoryBean.clear(); - } +public class StopJobParserTests extends AbstractJobParserTests { @Test public void testStopState() throws Exception { - assertNotNull(job); - + // // First Launch // - JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters()); + JobExecution jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(1, stepNamesList.size()); assertTrue(stepNamesList.contains("step1")); assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); - // TODO: BATCH-1011 - //assertEquals(BatchStatus.STOPPED.toString(), jobExecution.getExitStatus().getExitCode()); + assertEquals(ExitStatus.FAILED.getExitCode(), jobExecution.getExitStatus().getExitCode()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "step1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); - // // Second Launch // stepNamesList.clear(); - jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters()); + jobExecution = createJobExecution(); job.execute(jobExecution); - assertEquals(1, stepNamesList.size()); //step1 is not executed + assertEquals(1, stepNamesList.size()); // step1 is not executed assertTrue(stepNamesList.contains("step2")); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "step2"); + assertEquals(BatchStatus.COMPLETED, stepExecution2.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution2.getExitStatus()); + } public static class TestDecider implements JobExecutionDecider { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/AbstractJobTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/AbstractJobTests.java index 1aa86e9c1..2926dd582 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/AbstractJobTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/AbstractJobTests.java @@ -167,8 +167,7 @@ public class AbstractJobTests { } @Override - protected StepExecution doExecute(JobExecution execution) throws JobExecutionException { - return null; + protected void doExecute(JobExecution execution) throws JobExecutionException { } @Override diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobTests.java index 674be81e4..b017ddedd 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobTests.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import org.junit.Before; @@ -78,7 +77,8 @@ public class FlowJobTests { flow.setStateTransitions(transitions); job.setFlow(flow); job.afterPropertiesSet(); - StepExecution stepExecution = job.doExecute(jobExecution); + job.doExecute(jobExecution); + StepExecution stepExecution = getStepExecution(jobExecution, "step2"); assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); assertEquals(2, jobExecution.getStepExecutions().size()); } @@ -99,7 +99,8 @@ public class FlowJobTests { flow.setStateTransitions(transitions); job.setFlow(flow); job.afterPropertiesSet(); - StepExecution stepExecution = job.doExecute(jobExecution); + job.doExecute(jobExecution); + StepExecution stepExecution = getStepExecution(jobExecution, "step2"); assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals(2, jobExecution.getStepExecutions().size()); @@ -118,7 +119,7 @@ public class FlowJobTests { jobRepository.update(stepExecution); } }), "step2")); - transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2") { + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2") { @Override public void execute(StepExecution stepExecution) throws JobInterruptedException, UnexpectedJobExecutionException { @@ -130,7 +131,22 @@ public class FlowJobTests { super.execute(stepExecution); } } - }))); + }), ExitStatus.COMPLETED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2") { + @Override + public void execute(StepExecution stepExecution) throws JobInterruptedException, + UnexpectedJobExecutionException { + if (fail) { + stepExecution.setStatus(BatchStatus.FAILED); + stepExecution.setExitStatus(ExitStatus.FAILED); + jobRepository.update(stepExecution); + } else { + super.execute(stepExecution); + } + } + }), ExitStatus.FAILED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(BatchStatus.COMPLETED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(BatchStatus.FAILED, "end1"))); flow.setStateTransitions(transitions); job.setFlow(flow); job.afterPropertiesSet(); @@ -211,7 +227,10 @@ public class FlowJobTests { List transitions = new ArrayList(); 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")))); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), ExitStatus.COMPLETED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), ExitStatus.FAILED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(BatchStatus.COMPLETED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(BatchStatus.FAILED, "end1"))); flow.setStateTransitions(transitions); job.setFlow(flow); job.afterPropertiesSet(); @@ -240,18 +259,20 @@ public class FlowJobTests { flow.setStateTransitions(transitions); job.setFlow(flow); job.afterPropertiesSet(); - StepExecution stepExecution = job.doExecute(jobExecution); + job.doExecute(jobExecution); + StepExecution stepExecution = getStepExecution(jobExecution, "step3"); 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.singletonList(StateTransition.createEndStateTransition( - new StepState(step), "*"))); + List transitions = new ArrayList(); + transitions.add(StateTransition.createStateTransition(new StepState(step), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(BatchStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); job.setFlow(flow); job.execute(jobExecution); if (!jobExecution.getAllFailureExceptions().isEmpty()) { @@ -281,14 +302,14 @@ public class FlowJobTests { flow.setStateTransitions(transitions); job.setFlow(flow); - StepExecution stepExecution = job.doExecute(jobExecution); + job.doExecute(jobExecution); + StepExecution stepExecution = getStepExecution(jobExecution, "step3"); if (!jobExecution.getAllFailureExceptions().isEmpty()) { throw jobExecution.getAllFailureExceptions().get(0); } assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals(2, jobExecution.getStepExecutions().size()); - assertEquals("step3", stepExecution.getStepName()); } @@ -360,4 +381,20 @@ public class FlowJobTests { } + /** + * @param jobExecution + * @param stepName + * @return the StepExecution corresponding to the specified step + */ + private StepExecution getStepExecution(JobExecution jobExecution, String stepName) + { + for(StepExecution stepExecution : jobExecution.getStepExecutions()) { + if(stepExecution.getStepName().equals(stepName)) { + return stepExecution; + } + } + fail("No stepExecution found with name: [" + stepName + "]"); + return null; + } + } diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DefaultFailureJobParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DefaultFailureJobParserTests-context.xml new file mode 100644 index 000000000..4eb7fdecc --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DefaultFailureJobParserTests-context.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DefaultSuccessJobParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DefaultSuccessJobParserTests-context.xml new file mode 100644 index 000000000..71da3fab4 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DefaultSuccessJobParserTests-context.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DuplicateTransitionJobParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DuplicateTransitionJobParserTests-context.xml new file mode 100644 index 000000000..5b2717b05 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DuplicateTransitionJobParserTests-context.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailFirstJobParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailFirstJobParserTests-context.xml new file mode 100644 index 000000000..5c5714311 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailFirstJobParserTests-context.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests-context.xml new file mode 100644 index 000000000..b13658951 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests-context.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file