RESOLVED - BATCH-1032: Modify AbstractJobTests in test project to be able to launch FlowJob steps individually
applied patch with some tweaks
This commit is contained in:
@@ -1,157 +1,164 @@
|
||||
/*
|
||||
* 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 org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobExecutionException;
|
||||
import org.springframework.batch.core.JobInterruptedException;
|
||||
import org.springframework.batch.core.StartLimitExceededException;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.job.AbstractJob;
|
||||
import org.springframework.batch.core.repository.JobRestartException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class FlowJob extends AbstractJob {
|
||||
|
||||
private Flow flow;
|
||||
|
||||
/**
|
||||
* Create a {@link FlowJob} with null name and no flow (invalid state).
|
||||
*/
|
||||
public FlowJob() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link FlowJob} with provided name and no flow (invalid state).
|
||||
*/
|
||||
public FlowJob(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the flow.
|
||||
* @param flow the flow to set
|
||||
*/
|
||||
public void setFlow(Flow flow) {
|
||||
this.flow = flow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AbstractJob#doExecute(JobExecution)
|
||||
*/
|
||||
@Override
|
||||
protected StepExecution doExecute(final JobExecution execution) throws JobExecutionException {
|
||||
try {
|
||||
FlowExecution result = flow.start(new JobFlowExecutor(execution));
|
||||
return getLastStepExecution(execution, result);
|
||||
}
|
||||
catch (FlowExecutionException e) {
|
||||
if (e.getCause() instanceof JobExecutionException) {
|
||||
throw (JobExecutionException) e.getCause();
|
||||
}
|
||||
throw new JobExecutionException("Flow execution ended unexpectedly", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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(backup,stepExecution)) {
|
||||
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 (first==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
|
||||
*
|
||||
*/
|
||||
private class JobFlowExecutor implements FlowExecutor {
|
||||
|
||||
private final ThreadLocal<StepExecution> stepExecutionHolder = new ThreadLocal<StepExecution>();
|
||||
private final JobExecution execution;
|
||||
|
||||
/**
|
||||
* @param execution
|
||||
*/
|
||||
private JobFlowExecutor(JobExecution execution) {
|
||||
this.execution = execution;
|
||||
stepExecutionHolder.set(null);
|
||||
}
|
||||
|
||||
public String executeStep(Step step) throws JobInterruptedException, JobRestartException, StartLimitExceededException {
|
||||
StepExecution stepExecution = handleStep(step, execution);
|
||||
stepExecutionHolder.set(stepExecution);
|
||||
return stepExecution==null ? FlowExecution.COMPLETED : stepExecution.getExitStatus().getExitCode();
|
||||
}
|
||||
|
||||
public JobExecution getJobExecution() {
|
||||
return execution;
|
||||
}
|
||||
|
||||
public StepExecution getStepExecution() {
|
||||
return stepExecutionHolder.get();
|
||||
}
|
||||
|
||||
public void close(FlowExecution result) {
|
||||
stepExecutionHolder.set(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobExecutionException;
|
||||
import org.springframework.batch.core.JobInterruptedException;
|
||||
import org.springframework.batch.core.StartLimitExceededException;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.job.AbstractJob;
|
||||
import org.springframework.batch.core.repository.JobRestartException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class FlowJob extends AbstractJob {
|
||||
|
||||
private Flow flow;
|
||||
|
||||
/**
|
||||
* Create a {@link FlowJob} with null name and no flow (invalid state).
|
||||
*/
|
||||
public FlowJob() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link FlowJob} with provided name and no flow (invalid state).
|
||||
*/
|
||||
public FlowJob(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the flow.
|
||||
* @param flow the flow to set
|
||||
*/
|
||||
public void setFlow(Flow flow) {
|
||||
this.flow = flow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the flow
|
||||
*/
|
||||
public Flow getFlow(){
|
||||
return this.flow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AbstractJob#doExecute(JobExecution)
|
||||
*/
|
||||
@Override
|
||||
protected StepExecution doExecute(final JobExecution execution) throws JobExecutionException {
|
||||
try {
|
||||
FlowExecution result = flow.start(new JobFlowExecutor(execution));
|
||||
return getLastStepExecution(execution, result);
|
||||
}
|
||||
catch (FlowExecutionException e) {
|
||||
if (e.getCause() instanceof JobExecutionException) {
|
||||
throw (JobExecutionException) e.getCause();
|
||||
}
|
||||
throw new JobExecutionException("Flow execution ended unexpectedly", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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(backup,stepExecution)) {
|
||||
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 (first==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
|
||||
*
|
||||
*/
|
||||
private class JobFlowExecutor implements FlowExecutor {
|
||||
|
||||
private final ThreadLocal<StepExecution> stepExecutionHolder = new ThreadLocal<StepExecution>();
|
||||
private final JobExecution execution;
|
||||
|
||||
/**
|
||||
* @param execution
|
||||
*/
|
||||
private JobFlowExecutor(JobExecution execution) {
|
||||
this.execution = execution;
|
||||
stepExecutionHolder.set(null);
|
||||
}
|
||||
|
||||
public String executeStep(Step step) throws JobInterruptedException, JobRestartException, StartLimitExceededException {
|
||||
StepExecution stepExecution = handleStep(step, execution);
|
||||
stepExecutionHolder.set(stepExecution);
|
||||
return stepExecution==null ? FlowExecution.COMPLETED : stepExecution.getExitStatus().getExitCode();
|
||||
}
|
||||
|
||||
public JobExecution getJobExecution() {
|
||||
return execution;
|
||||
}
|
||||
|
||||
public StepExecution getStepExecution() {
|
||||
return stepExecutionHolder.get();
|
||||
}
|
||||
|
||||
public void close(FlowExecution result) {
|
||||
stepExecutionHolder.set(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -81,6 +81,14 @@ public class SimpleFlow implements Flow, InitializingBean {
|
||||
this.stateTransitions = stateTransitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stateName
|
||||
* @return state with given name, null if not found
|
||||
*/
|
||||
public State getState(String stateName) {
|
||||
return stateMap.get(stateName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate start state and pre-populate data structures needed for execution.
|
||||
*
|
||||
|
||||
@@ -1,56 +1,62 @@
|
||||
/*
|
||||
* 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.support.state;
|
||||
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.job.flow.FlowExecutor;
|
||||
import org.springframework.batch.core.job.flow.support.State;
|
||||
|
||||
/**
|
||||
* {@link State} implementation that delegates to a {@link FlowExecutor} to
|
||||
* execute the specified {@link Step}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class StepState extends AbstractState {
|
||||
|
||||
private final Step step;
|
||||
|
||||
/**
|
||||
* @param step the step that will be executed
|
||||
*/
|
||||
public StepState(Step step) {
|
||||
super(step.getName());
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name for the step that will be executed
|
||||
* @param step the step that will be executed
|
||||
*/
|
||||
public StepState(String name, Step step) {
|
||||
super(name);
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(FlowExecutor executor) throws Exception {
|
||||
return executor.executeStep(step);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.support.state;
|
||||
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.job.flow.FlowExecutor;
|
||||
import org.springframework.batch.core.job.flow.support.State;
|
||||
|
||||
/**
|
||||
* {@link State} implementation that delegates to a {@link FlowExecutor} to
|
||||
* execute the specified {@link Step}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class StepState extends AbstractState {
|
||||
|
||||
private final Step step;
|
||||
|
||||
/**
|
||||
* @param step the step that will be executed
|
||||
*/
|
||||
public StepState(Step step) {
|
||||
super(step.getName());
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name for the step that will be executed
|
||||
* @param step the step that will be executed
|
||||
*/
|
||||
public StepState(String name, Step step) {
|
||||
super(name);
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(FlowExecutor executor) throws Exception {
|
||||
return executor.executeStep(step);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the step
|
||||
*/
|
||||
public Step getStep() {
|
||||
return step;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
<configs>
|
||||
<config>src/test/resources/data-source-context.xml</config>
|
||||
<config>src/test/resources/simple-job-launcher-context.xml</config>
|
||||
<config>src/test/resources/jobs/sampleJob.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/sample/config/common-context.xml</config>
|
||||
<config>src/test/resources/jobs/sampleFlowJob.xml</config>
|
||||
<config>src/test/resources/jobs/sampleSimpleJob.xml</config>
|
||||
<config>src/test/resources/jobs/sample-steps.xml</config>
|
||||
</configs>
|
||||
<configSets>
|
||||
<configSet>
|
||||
@@ -19,7 +21,6 @@
|
||||
<incomplete>false</incomplete>
|
||||
<configs>
|
||||
<config>src/test/resources/data-source-context.xml</config>
|
||||
<config>src/test/resources/jobs/sampleJob.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/sample/config/common-context.xml</config>
|
||||
<config>src/test/resources/simple-job-launcher-context.xml</config>
|
||||
</configs>
|
||||
|
||||
@@ -1,111 +1,224 @@
|
||||
/*
|
||||
* 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.test;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobParameter;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Base class for testing batch jobs using the SimpleJob implementation. It
|
||||
* provides methods for launching a Job, or individual Steps within a Job on
|
||||
* their own, allowing for end to end testing of individual steps, without
|
||||
* having to run every step in the job. Any test classes inheriting from this
|
||||
* class should make sure they are part of an ApplicationContext, which is
|
||||
* generally expected to be done as part of the Spring test framework.
|
||||
* Furthermore, the ApplicationContext in which it is a part of is expected to
|
||||
* have one {@link JobLauncher}, {@link JobRepository}, and a single Job
|
||||
* implementation. It should be noted that using any of the methods that don't
|
||||
* conain {@link JobParameters} in their signature, will result in one being
|
||||
* created with the current system time as a parameter.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dan Garrette
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractJobTests {
|
||||
|
||||
/** Logger */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@Autowired
|
||||
private JobLauncher launcher;
|
||||
|
||||
@Autowired
|
||||
private Job job;
|
||||
|
||||
@Autowired
|
||||
private JobRepository jobRepository;
|
||||
|
||||
public JobRepository getJobRepository() {
|
||||
return jobRepository;
|
||||
}
|
||||
|
||||
public Job getJob() {
|
||||
return job;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public getter for the launcher.
|
||||
*
|
||||
* @return the launcher
|
||||
*/
|
||||
protected JobLauncher getJobLauncher() {
|
||||
return launcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the entire job, including all steps, in order.
|
||||
*
|
||||
* @return JobExecution, so that the test may validate the exit status
|
||||
* @throws Exception
|
||||
*/
|
||||
public JobExecution launchJob() throws Exception {
|
||||
return this.launchJob(this.makeUniqueJobParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the entire job, including all steps, in order.
|
||||
*
|
||||
* @param jobParameters
|
||||
* @return JobExecution, so that the test may validate the exit status
|
||||
* @throws Exception
|
||||
*/
|
||||
public JobExecution launchJob(JobParameters jobParameters) throws Exception {
|
||||
return getJobLauncher().run(this.job, jobParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new JobParameters object containing only a parameter for the
|
||||
* current timestamp, to ensure that the job instance will be unique
|
||||
*/
|
||||
private JobParameters makeUniqueJobParameters() {
|
||||
Map<String, JobParameter> parameters = new HashMap<String, JobParameter>();
|
||||
parameters.put("timestamp", new JobParameter(new Date().getTime()));
|
||||
return new JobParameters(parameters);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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.test;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobParameter;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.job.SimpleJob;
|
||||
import org.springframework.batch.core.job.flow.FlowJob;
|
||||
import org.springframework.batch.core.job.flow.support.SimpleFlow;
|
||||
import org.springframework.batch.core.job.flow.support.State;
|
||||
import org.springframework.batch.core.job.flow.support.state.StepState;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Base class for testing batch jobs. It provides methods for launching an
|
||||
* entire {@link Job}, allowing for end to end testing of individual steps,
|
||||
* without having to run every step in the job. Any test classes inheriting from
|
||||
* this class should make sure they are part of an {@link ApplicationContext},
|
||||
* which is generally expected to be done as part of the Spring test framework.
|
||||
* Furthermore, the {@link ApplicationContext} in which it is a part of is
|
||||
* expected to have one {@link JobLauncher}, {@link JobRepository}, and a
|
||||
* single {@link Job} implementation.
|
||||
*
|
||||
* <p>
|
||||
* This class also provides the ability to run {@link Step}s from a
|
||||
* {@link FlowJob} or {@link SimpleJob} individually. By launching {@link Step}s
|
||||
* within a {@link Job} on their own, end to end testing of individual steps can
|
||||
* be performed without having to run every step in the job.
|
||||
*
|
||||
* <p>
|
||||
* It should be noted that using any of the methods that don't contain
|
||||
* {@link JobParameters} in their signature, will result in one being created
|
||||
* with the current system time as a parameter. This will ensure restartability
|
||||
* when no parameters are provided.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dan Garrette
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractJobTests {
|
||||
|
||||
/** Logger */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@Autowired
|
||||
private JobLauncher launcher;
|
||||
|
||||
@Autowired
|
||||
private Job job;
|
||||
|
||||
@Autowired
|
||||
private JobRepository jobRepository;
|
||||
|
||||
private StepRunner stepRunner;
|
||||
private Map<String, Step> stepMap;
|
||||
|
||||
/**
|
||||
* @return the job repository
|
||||
*/
|
||||
public JobRepository getJobRepository() {
|
||||
return jobRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the job
|
||||
*/
|
||||
public Job getJob() {
|
||||
return job;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the launcher
|
||||
*/
|
||||
protected JobLauncher getJobLauncher() {
|
||||
return launcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the entire job, including all steps.
|
||||
*
|
||||
* @return JobExecution, so that the test may validate the exit status
|
||||
* @throws Exception
|
||||
*/
|
||||
public JobExecution launchJob() throws Exception {
|
||||
return this.launchJob(this.makeUniqueJobParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the entire job, including all steps
|
||||
*
|
||||
* @param jobParameters
|
||||
* @return JobExecution, so that the test may validate the exit status
|
||||
* @throws Exception
|
||||
*/
|
||||
public JobExecution launchJob(JobParameters jobParameters) throws Exception {
|
||||
return getJobLauncher().run(this.job, jobParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new JobParameters object containing only a parameter for the
|
||||
* current timestamp, to ensure that the job instance will be unique
|
||||
*/
|
||||
private JobParameters makeUniqueJobParameters() {
|
||||
Map<String, JobParameter> parameters = new HashMap<String, JobParameter>();
|
||||
parameters.put("timestamp", new JobParameter(new Date().getTime()));
|
||||
return new JobParameters(parameters);
|
||||
}
|
||||
|
||||
protected StepRunner getStepRunner() {
|
||||
if (this.stepRunner == null) {
|
||||
this.stepRunner = new StepRunner(getJobLauncher(), getJobRepository());
|
||||
}
|
||||
return this.stepRunner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch just the specified step in the job.
|
||||
*
|
||||
* @param stepName
|
||||
*/
|
||||
public JobExecution launchStep(String stepName) {
|
||||
return getStepRunner().launchStep(getStep(stepName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stepName
|
||||
* @return
|
||||
*/
|
||||
public Step getStep(String stepName) {
|
||||
Job job = getJob();
|
||||
if (job instanceof FlowJob) {
|
||||
return getFlowJobStep(stepName);
|
||||
}
|
||||
else if (job instanceof SimpleJob) {
|
||||
return getSimpleJobStep(stepName);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Job is neither a FlowJob or a SimpleJob");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the step from a FlowJob. Throw an exception of the step does not
|
||||
* exist.
|
||||
*
|
||||
* @param stepName
|
||||
* @return the step
|
||||
*/
|
||||
private Step getFlowJobStep(String stepName) {
|
||||
try{
|
||||
State state = ((SimpleFlow) ((FlowJob) getJob()).getFlow()).getState(stepName);
|
||||
Assert.notNull(state, "no matching state found in flow for " + stepName);
|
||||
Assert.isInstanceOf(StepState.class, state);
|
||||
return ((StepState) state).getStep();
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new IllegalStateException("No Step found with name: [" + stepName + "]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the step from a SimpleJob. Throw an exception of the step does
|
||||
* not exist.
|
||||
*
|
||||
* @param stepName
|
||||
* @return the step
|
||||
*/
|
||||
private Step getSimpleJobStep(String stepName) {
|
||||
if (this.stepMap == null) {
|
||||
//
|
||||
// Populate the step map
|
||||
//
|
||||
SimpleJob simpleJob = (SimpleJob) getJob();
|
||||
this.stepMap = new HashMap<String, Step>();
|
||||
for (Step step : simpleJob.getSteps()) {
|
||||
this.stepMap.put(step.getName(), step);
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.stepMap.containsKey(stepName)) {
|
||||
throw new IllegalStateException("No Step found with name: [" + stepName + "]");
|
||||
}
|
||||
return this.stepMap.get(stepName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch just the specified step in the job.
|
||||
*
|
||||
* @param stepName
|
||||
* @param jobParameters
|
||||
*/
|
||||
public JobExecution launchStep(String stepName, JobParameters jobParameters) {
|
||||
return getStepRunner().launchStep(getStep(stepName), jobParameters);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.batch.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.job.SimpleJob;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
|
||||
/**
|
||||
* Base class for testing batch jobs using the SimpleJob implementation.
|
||||
* It provides methods for launching a Job, or individual Steps within a Job on their own,
|
||||
* allowing for end to end testing of individual steps, without having to run every step
|
||||
* in the job. Any test classes inheriting from this class should make sure they are part
|
||||
* of an ApplicationContext, which is generally expected to be done as part of the Spring
|
||||
* test framework. Furthermore, the ApplicationContext in which it is a part of is expected
|
||||
* to have one {@link JobLauncher}, {@link JobRepository}, and a single Job implementation.
|
||||
* It should be noted that using any of the methods that don't conain {@link JobParameters}
|
||||
* in their signature, will result in one being created with the current system time as a
|
||||
* parameter.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dan Garrette
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractSimpleJobTests extends AbstractJobTests {
|
||||
|
||||
private StepRunner stepRunner;
|
||||
|
||||
private Map<String, Step> stepMap = new HashMap<String, Step>();
|
||||
private List<Step> stepList = new ArrayList<Step>();
|
||||
|
||||
@Before
|
||||
public void setUpSteps() {
|
||||
for (Step step : (getSimpleJob()).getSteps()) {
|
||||
stepMap.put(step.getName(), step);
|
||||
stepList.add(step);
|
||||
}
|
||||
}
|
||||
|
||||
protected StepRunner getStepRunner() {
|
||||
if(stepRunner == null){
|
||||
stepRunner = new StepRunner(getJobLauncher(), getJobRepository());
|
||||
}
|
||||
return stepRunner;
|
||||
}
|
||||
|
||||
public SimpleJob getSimpleJob() {
|
||||
return (SimpleJob)getJob();
|
||||
}
|
||||
|
||||
public Step getStep(String stepName){
|
||||
|
||||
if(!stepMap.containsKey(stepName)){
|
||||
throw new IllegalStateException("No Step found with name: [" + stepName + "]");
|
||||
}
|
||||
return stepMap.get(stepName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch just the specified step in the job.
|
||||
*
|
||||
* @param stepName
|
||||
*/
|
||||
public JobExecution launchStep(String stepName) {
|
||||
return getStepRunner().launchStep(getStep(stepName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch just the specified step in the job.
|
||||
*
|
||||
* @param stepName
|
||||
* @param jobParameters
|
||||
*/
|
||||
public JobExecution launchStep(String stepName, JobParameters jobParameters) {
|
||||
return getStepRunner().launchStep(getStep(stepName), jobParameters);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,64 +1,66 @@
|
||||
package org.springframework.batch.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/sampleJob.xml" })
|
||||
public class SampleJobTests extends AbstractSimpleJobTests {
|
||||
|
||||
private SimpleJdbcTemplate jdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
public void setJdbcTemplate(SimpleJdbcTemplate jdbcTemplate) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.jdbcTemplate.update("create table TESTS (ID integer, NAME varchar(40))");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
this.jdbcTemplate.update("drop table TESTS");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJob() throws Exception {
|
||||
assertEquals(BatchStatus.COMPLETED,this.launchJob().getStatus());
|
||||
this.verifyTasklet(1);
|
||||
this.verifyTasklet(2);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void voidTestNonExistentStep(){
|
||||
launchStep("nonExistent");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStep1Execution() {
|
||||
assertEquals(BatchStatus.COMPLETED, this.launchStep("step1").getStatus());
|
||||
this.verifyTasklet(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStep2Execution() {
|
||||
assertEquals(BatchStatus.COMPLETED, this.launchStep("step2").getStatus());
|
||||
this.verifyTasklet(2);
|
||||
}
|
||||
|
||||
private void verifyTasklet(int id) {
|
||||
assertEquals(id, jdbcTemplate.queryForInt("SELECT ID from TESTS where NAME = 'SampleTasklet" + id + "'"));
|
||||
}
|
||||
|
||||
}
|
||||
package org.springframework.batch.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
|
||||
/**
|
||||
* This is an abstract test class to be used by test classes to test the
|
||||
* {@link AbstractJobTests} class.
|
||||
*
|
||||
* @author Dan Garrette
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractSampleJobTests extends AbstractJobTests {
|
||||
|
||||
private SimpleJdbcTemplate jdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
public void setJdbcTemplate(SimpleJdbcTemplate jdbcTemplate) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.jdbcTemplate.update("create table TESTS (ID integer, NAME varchar(40))");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
this.jdbcTemplate.update("drop table TESTS");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJob() throws Exception {
|
||||
assertEquals(BatchStatus.COMPLETED, this.launchJob().getStatus());
|
||||
this.verifyTasklet(1);
|
||||
this.verifyTasklet(2);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testNonExistentStep() {
|
||||
launchStep("nonExistent");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStep1Execution() {
|
||||
assertEquals(BatchStatus.COMPLETED, this.launchStep("step1").getStatus());
|
||||
this.verifyTasklet(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStep2Execution() {
|
||||
assertEquals(BatchStatus.COMPLETED, this.launchStep("step2").getStatus());
|
||||
this.verifyTasklet(2);
|
||||
}
|
||||
|
||||
private void verifyTasklet(int id) {
|
||||
assertEquals(id, jdbcTemplate.queryForInt("SELECT ID from TESTS where NAME = 'SampleTasklet" + id + "'"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.springframework.batch.test;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.batch.core.job.flow.FlowJob;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* This class will specifically test the capabilities of
|
||||
* {@link AbstractSampleJobTests} to test {@link FlowJob}s.
|
||||
*
|
||||
* @author Dan Garrette
|
||||
* @since 2.0
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/sampleFlowJob.xml" })
|
||||
public class SampleFlowJobTests extends AbstractSampleJobTests {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.springframework.batch.test;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.batch.core.job.SimpleJob;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* This class will specifically test the capabilities of
|
||||
* {@link AbstractSampleJobTests} to test {@link SimpleJob}s.
|
||||
*
|
||||
* @author Dan Garrette
|
||||
* @since 2.0
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/sampleSimpleJob.xml" })
|
||||
public class SampleSimpleJobTests extends AbstractSampleJobTests {
|
||||
|
||||
}
|
||||
@@ -1,60 +1,60 @@
|
||||
package org.springframework.batch.test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/sampleJob.xml" })
|
||||
public class SampleStepTests implements ApplicationContextAware{
|
||||
|
||||
@Autowired
|
||||
private SimpleJdbcTemplate jdbcTemplate;
|
||||
|
||||
private StepRunner stepRunner;
|
||||
private ApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private JobLauncher jobLauncher;
|
||||
|
||||
@Autowired
|
||||
private JobRepository jobRepository;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
jdbcTemplate.update("create table TESTS (ID integer, NAME varchar(40))");
|
||||
stepRunner = new StepRunner(jobLauncher, jobRepository);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
this.jdbcTemplate.update("drop table TESTS");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTasklet() {
|
||||
Step step = (Step)context.getBean("step2");
|
||||
assertEquals(BatchStatus.COMPLETED, stepRunner.launchStep(step).getStatus());
|
||||
assertEquals(2, jdbcTemplate.queryForInt("SELECT ID from TESTS where NAME = 'SampleTasklet2'"));
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.context = applicationContext;
|
||||
}
|
||||
|
||||
}
|
||||
package org.springframework.batch.test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/sample-steps.xml" })
|
||||
public class SampleStepTests implements ApplicationContextAware{
|
||||
|
||||
@Autowired
|
||||
private SimpleJdbcTemplate jdbcTemplate;
|
||||
|
||||
private StepRunner stepRunner;
|
||||
private ApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private JobLauncher jobLauncher;
|
||||
|
||||
@Autowired
|
||||
private JobRepository jobRepository;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
jdbcTemplate.update("create table TESTS (ID integer, NAME varchar(40))");
|
||||
stepRunner = new StepRunner(jobLauncher, jobRepository);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
this.jdbcTemplate.update("drop table TESTS");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTasklet() {
|
||||
Step step = (Step)context.getBean("step2");
|
||||
assertEquals(BatchStatus.COMPLETED, stepRunner.launchStep(step).getStatus());
|
||||
assertEquals(2, jdbcTemplate.queryForInt("SELECT ID from TESTS where NAME = 'SampleTasklet2'"));
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.context = applicationContext;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
57
spring-batch-test/src/test/resources/jobs/sampleJob.xml → spring-batch-test/src/test/resources/jobs/sample-steps.xml
Executable file → Normal file
57
spring-batch-test/src/test/resources/jobs/sampleJob.xml → spring-batch-test/src/test/resources/jobs/sample-steps.xml
Executable file → Normal file
@@ -1,33 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
|
||||
|
||||
<bean id="sampleJob" parent="simpleJob">
|
||||
<property name="steps">
|
||||
<list>
|
||||
<bean id="step1" parent="taskletStep">
|
||||
<property name="tasklet">
|
||||
<bean class="org.springframework.batch.test.sample.SampleTasklet">
|
||||
<constructor-arg value="1" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
<ref bean="step2" />
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="step2" parent="taskletStep">
|
||||
<property name="tasklet">
|
||||
<bean class="org.springframework.batch.test.sample.SampleTasklet">
|
||||
<constructor-arg value="2" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
|
||||
|
||||
<bean id="step1" parent="taskletStep">
|
||||
<property name="tasklet">
|
||||
<bean class="org.springframework.batch.test.sample.SampleTasklet">
|
||||
<constructor-arg value="1" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="step2" parent="taskletStep">
|
||||
<property name="tasklet">
|
||||
<bean class="org.springframework.batch.test.sample.SampleTasklet">
|
||||
<constructor-arg value="2" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
22
spring-batch-test/src/test/resources/jobs/sampleFlowJob.xml
Normal file
22
spring-batch-test/src/test/resources/jobs/sampleFlowJob.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/batch"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/batch
|
||||
http://www.springframework.org/schema/batch/spring-batch-2.0.xsd
|
||||
http://www.springframework.org/schema/aop
|
||||
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<beans:import resource="sample-steps.xml" />
|
||||
|
||||
<job id="sampleFlowJob">
|
||||
<step name="step1" next="step2"/>
|
||||
<step name="step2"/>
|
||||
</job>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
|
||||
|
||||
<import resource="sample-steps.xml" />
|
||||
|
||||
<bean id="sampleJob" parent="simpleJob">
|
||||
<property name="steps">
|
||||
<list>
|
||||
<ref bean="step1" />
|
||||
<ref bean="step2" />
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user