diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractor.java new file mode 100644 index 000000000..613fb642b --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractor.java @@ -0,0 +1,125 @@ +/* + * Copyright 2006-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.job; + +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.item.ExecutionContext; + +/** + * Simple implementation of {@link JobParametersExtractor} which pulls + * parameters with named keys out of the step execution context and the job + * parameters of the surrounding job. + * + * @author Dave Syer + * + */ +public class DefaultJobParametersExtractor implements JobParametersExtractor { + + private Set keys = new HashSet(); + + /** + * The key names to pull out of the execution context or job parameters, if + * they exist. If a key doesn't exist in the execution context then the job + * parameters from the enclosing job execution are tried, and if there is + * nothing there either then no parameter is extracted. Key names ending + * with (long), (int), (double), + * (date) or (string) will be assumed to refer to + * values of the respective type and assigned to job parameters accordingly + * (there will be an error if they are not of the right type). Without a + * special suffix in that form a parameter is assumed to be of type String. + * + * @param keys the keys to set + */ + public void setKeys(String[] keys) { + this.keys = new HashSet(Arrays.asList(keys)); + } + + /** + * @see JobParametersExtractor#getJobParameters(StepExecution) + */ + public JobParameters getJobParameters(Job job, StepExecution stepExecution) { + JobParametersBuilder builder = new JobParametersBuilder(); + Map jobParameters = stepExecution.getJobParameters().getParameters(); + ExecutionContext executionContext = stepExecution.getExecutionContext(); + for (String key : keys) { + if (key.endsWith("(long)")) { + key = key.replace("(long)", ""); + if (executionContext.containsKey(key)) { + builder.addLong(key, executionContext.getLong(key)); + } + else if (jobParameters.containsKey(key)) { + builder.addLong(key, (Long) jobParameters.get(key).getValue()); + } + } + else if (key.endsWith("(int)")) { + key = key.replace("(int)", ""); + if (executionContext.containsKey(key)) { + builder.addLong(key, (long) executionContext.getInt(key)); + } + else if (jobParameters.containsKey(key)) { + builder.addLong(key, (Long) jobParameters.get(key).getValue()); + } + } + else if (key.endsWith("(double)")) { + key = key.replace("(double)", ""); + if (executionContext.containsKey(key)) { + builder.addDouble(key, executionContext.getDouble(key)); + } + else if (jobParameters.containsKey(key)) { + builder.addDouble(key, (Double) jobParameters.get(key).getValue()); + } + } + else if (key.endsWith("(string)")) { + key = key.replace("(string)", ""); + if (executionContext.containsKey(key)) { + builder.addString(key, executionContext.getString(key)); + } + else if (jobParameters.containsKey(key)) { + builder.addString(key, (String) jobParameters.get(key).getValue()); + } + } + else if (key.endsWith("(date)")) { + key = key.replace("(date)", ""); + if (executionContext.containsKey(key)) { + builder.addDate(key, (Date) executionContext.get(key)); + } + else if (jobParameters.containsKey(key)) { + builder.addDate(key, (Date) jobParameters.get(key).getValue()); + } + } + else { + if (executionContext.containsKey(key)) { + builder.addString(key, executionContext.get(key).toString()); + } + else if (jobParameters.containsKey(key)) { + builder.addString(key, jobParameters.get(key).getValue().toString()); + } + } + } + return builder.toJobParameters(); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobParametersExtractor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobParametersExtractor.java new file mode 100644 index 000000000..75caa1fc1 --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobParametersExtractor.java @@ -0,0 +1,42 @@ +/* + * Copyright 2006-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.job; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; + +/** + * Strategy interface for translating a {@link StepExecution} into + * {@link JobParameters}. + * + * @author Dave Syer + * + */ +public interface JobParametersExtractor { + + /** + * Extract job parameters from the step execution, for example from the + * execution context or other properties. + * + * @param job a {@link Job} + * @param stepExecution a {@link StepExecution} + * + * @return some {@link JobParameters} + */ + JobParameters getJobParameters(Job job, StepExecution stepExecution); + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobStep.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobStep.java new file mode 100644 index 000000000..31d9331a2 --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobStep.java @@ -0,0 +1,125 @@ +/* + * Copyright 2006-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.job; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.UnexpectedJobExecutionException; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.step.AbstractStep; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.util.Assert; + +/** + * A {@link Step} that delegates to a {@link Job} to do its work. This is a + * great tool for managing dependencies between jobs, and also to modularise + * complex step logic into something that is testable in isolation. The job is + * executed with parameters that can be extracted from the step execution, hence + * this step can also be usefully used as the worker in a parallel or + * partitioned execution. + * + * @author Dave Syer + * + */ +public class JobStep extends AbstractStep { + + /** + * The key for the job parameters in the step execution context. Needed for + * restarts. + */ + private static final String JOB_PARAMETERS_KEY = JobStep.class.getName() + ".JOB_PARAMETERS"; + + private Job job; + + private JobLauncher jobLauncher; + + private JobParametersExtractor jobParametersExtractor = new DefaultJobParametersExtractor(); + + @Override + public void afterPropertiesSet() throws Exception { + super.afterPropertiesSet(); + Assert.state(jobLauncher != null, "A JobLauncher must be provided"); + Assert.state(job != null, "A Job must be provided"); + } + + /** + * The {@link Job} to delegate to in this step. + * + * @param job a {@link Job} + */ + public void setJob(Job job) { + this.job = job; + } + + /** + * A {@link JobLauncher} is required to be able to run the enclosed + * {@link Job}. + * + * @param jobLauncher the {@link JobLauncher} to set + */ + public void setJobLauncher(JobLauncher jobLauncher) { + this.jobLauncher = jobLauncher; + } + + /** + * The {@link JobParametersExtractor} is used to extract + * {@link JobParametersExtractor} from the {@link StepExecution} to run the + * {@link Job}. By default an instance will be provided that simply creates + * empty {@link JobParameters}. This is unlikely to be very useful, since + * the {@link Job} normally cannot be run with empty parameters more than + * once. + * + * @param jobParametersExtractor the {@link JobParametersExtractor} to set + */ + public void setJobParametersExtractor(JobParametersExtractor jobParametersExtractor) { + this.jobParametersExtractor = jobParametersExtractor; + } + + /** + * Execute the job provided by delegating to the {@link JobLauncher} to + * prevent duplicate executions. The job parameters will be generated by the + * {@link JobParametersExtractor} provided (if any), otherwise empty. On a + * restart, the job parameters will be the same as the last (failed) + * execution. + * + * @see AbstractStep#doExecute(StepExecution) + */ + @Override + protected void doExecute(StepExecution stepExecution) throws Exception { + + ExecutionContext executionContext = stepExecution.getExecutionContext(); + + JobParameters jobParameters; + if (executionContext.containsKey(JOB_PARAMETERS_KEY)) { + jobParameters = (JobParameters) executionContext.get(JOB_PARAMETERS_KEY); + } + else { + jobParameters = jobParametersExtractor.getJobParameters(job, stepExecution); + executionContext.put(JOB_PARAMETERS_KEY, jobParameters); + } + + JobExecution jobExecution = jobLauncher.run(job, jobParameters); + if (jobExecution.getStatus().isUnsuccessful()) { + // AbstractStep will take care of the step execution status + throw new UnexpectedJobExecutionException("Step failure: the delegate Job failed in JobStep."); + } + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorJobParametersTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorJobParametersTests.java new file mode 100644 index 000000000..b24ff5483 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorJobParametersTests.java @@ -0,0 +1,98 @@ +/* + * Copyright 2006-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.job; + +import static org.junit.Assert.*; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.converter.DefaultJobParametersConverter; +import org.springframework.batch.support.PropertiesConverter; + +/** + * @author Dave Syer + * + */ +public class DefaultJobParametersExtractorJobParametersTests { + + private DefaultJobParametersExtractor extractor = new DefaultJobParametersExtractor(); + + @Test + public void testGetNamedJobParameters() throws Exception { + StepExecution stepExecution = getStepExecution("foo=bar"); + extractor.setKeys(new String[] {"foo", "bar"}); + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{foo=bar}", jobParameters.toString()); + } + + @Test + public void testGetNamedLongStringParameters() throws Exception { + StepExecution stepExecution = getStepExecution("foo=bar"); + extractor.setKeys(new String[] {"foo(string)", "bar"}); + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{foo=bar}", jobParameters.toString()); + } + + @Test + public void testGetNamedLongJobParameters() throws Exception { + StepExecution stepExecution = getStepExecution("foo(long)=11"); + extractor.setKeys(new String[] {"foo(long)", "bar"}); + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{foo=11}", jobParameters.toString()); + } + + @Test + public void testGetNamedIntJobParameters() throws Exception { + StepExecution stepExecution = getStepExecution("foo(long)=11"); + extractor.setKeys(new String[] {"foo(int)", "bar"}); + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{foo=11}", jobParameters.toString()); + } + + @Test + public void testGetNamedDoubleJobParameters() throws Exception { + StepExecution stepExecution = getStepExecution("foo(double)=11.1"); + extractor.setKeys(new String[] {"foo(double)"}); + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{foo=11.1}", jobParameters.toString()); + } + + @Test + public void testGetNamedDateJobParameters() throws Exception { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); + Date date = dateFormat.parse(dateFormat.format(new Date())); + StepExecution stepExecution = getStepExecution("foo(date)="+dateFormat.format(date)); + extractor.setKeys(new String[] {"foo(date)"}); + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{foo="+date.getTime()+"}", jobParameters.toString()); + } + + /** + * @param parameters + * @return + */ + private StepExecution getStepExecution(String parameters) { + JobParameters jobParameters = new DefaultJobParametersConverter().getJobParameters(PropertiesConverter.stringToProperties(parameters)); + return new StepExecution("step", new JobExecution(new JobInstance(1L, jobParameters, "job"))); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorTests.java new file mode 100644 index 000000000..6eadff04c --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorTests.java @@ -0,0 +1,91 @@ +/* + * Copyright 2006-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.job; + +import static org.junit.Assert.*; + +import java.util.Date; + +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; + +/** + * @author Dave Syer + * + */ +public class DefaultJobParametersExtractorTests { + + private DefaultJobParametersExtractor extractor = new DefaultJobParametersExtractor(); + private StepExecution stepExecution = new StepExecution("step", new JobExecution(0L)); + + @Test + public void testGetEmptyJobParameters() throws Exception { + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{}", jobParameters.toString()); + } + + @Test + public void testGetNamedJobParameters() throws Exception { + stepExecution.getExecutionContext().put("foo", "bar"); + extractor.setKeys(new String[] {"foo", "bar"}); + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{foo=bar}", jobParameters.toString()); + } + + @Test + public void testGetNamedLongStringParameters() throws Exception { + stepExecution.getExecutionContext().putString("foo","bar"); + extractor.setKeys(new String[] {"foo(string)", "bar"}); + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{foo=bar}", jobParameters.toString()); + } + + @Test + public void testGetNamedLongJobParameters() throws Exception { + stepExecution.getExecutionContext().putLong("foo",11L); + extractor.setKeys(new String[] {"foo(long)", "bar"}); + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{foo=11}", jobParameters.toString()); + } + + @Test + public void testGetNamedIntJobParameters() throws Exception { + stepExecution.getExecutionContext().putInt("foo",11); + extractor.setKeys(new String[] {"foo(int)", "bar"}); + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{foo=11}", jobParameters.toString()); + } + + @Test + public void testGetNamedDoubleJobParameters() throws Exception { + stepExecution.getExecutionContext().putDouble("foo",11.1); + extractor.setKeys(new String[] {"foo(double)"}); + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{foo=11.1}", jobParameters.toString()); + } + + @Test + public void testGetNamedDateJobParameters() throws Exception { + Date date = new Date(); + stepExecution.getExecutionContext().put("foo",date); + extractor.setKeys(new String[] {"foo(date)"}); + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + assertEquals("{foo="+date.getTime()+"}", jobParameters.toString()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/JobStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/JobStepTests.java new file mode 100644 index 000000000..d8fcb8296 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/JobStepTests.java @@ -0,0 +1,177 @@ +/* + * Copyright 2006-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.job; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Date; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.UnexpectedJobExecutionException; +import org.springframework.batch.core.job.JobSupport; +import org.springframework.batch.core.launch.support.SimpleJobLauncher; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.support.transaction.ResourcelessTransactionManager; + +/** + * @author Dave Syer + * + */ +public class JobStepTests { + + private JobStep step = new JobStep(); + + private StepExecution stepExecution; + + private JobRepository jobRepository; + + @Before + public void setUp() throws Exception { + MapJobRepositoryFactoryBean.clear(); + step.setName("step"); + MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean(); + factory.setTransactionManager(new ResourcelessTransactionManager()); + jobRepository = (JobRepository) factory.getObject(); + step.setJobRepository(jobRepository); + JobExecution jobExecution = jobRepository.createJobExecution("job", new JobParameters()); + stepExecution = jobExecution.createStepExecution("step"); + jobRepository.add(stepExecution); + SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); + jobLauncher.setJobRepository(jobRepository); + jobLauncher.afterPropertiesSet(); + step.setJobLauncher(jobLauncher); + } + + /** + * Test method for + * {@link org.springframework.batch.core.step.job.JobStep#afterPropertiesSet()} + * . + */ + @Test(expected = IllegalStateException.class) + public void testAfterPropertiesSet() throws Exception { + step.afterPropertiesSet(); + } + + /** + * Test method for + * {@link org.springframework.batch.core.step.job.JobStep#afterPropertiesSet()} + * . + */ + @Test(expected = IllegalStateException.class) + public void testAfterPropertiesSetWithNoLauncher() throws Exception { + step.setJob(new JobSupport("child")); + step.setJobLauncher(null); + step.afterPropertiesSet(); + } + + /** + * Test method for + * {@link org.springframework.batch.core.step.AbstractStep#execute(org.springframework.batch.core.StepExecution)} + * . + */ + @Test + public void testExecuteSunnyDay() throws Exception { + step.setJob(new JobSupport("child") { + @Override + public void execute(JobExecution execution) throws UnexpectedJobExecutionException { + execution.setStatus(BatchStatus.COMPLETED); + execution.setEndTime(new Date()); + } + }); + step.afterPropertiesSet(); + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertTrue("Missing job parameters in execution context: " + stepExecution.getExecutionContext(), stepExecution + .getExecutionContext().containsKey(JobStep.class.getName() + ".JOB_PARAMETERS")); + } + + @Test + public void testExecuteFailure() throws Exception { + step.setJob(new JobSupport("child") { + @Override + public void execute(JobExecution execution) throws UnexpectedJobExecutionException { + execution.setStatus(BatchStatus.FAILED); + execution.setEndTime(new Date()); + } + }); + step.afterPropertiesSet(); + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + } + + @Test + public void testExecuteException() throws Exception { + step.setJob(new JobSupport("child") { + @Override + public void execute(JobExecution execution) throws UnexpectedJobExecutionException { + throw new RuntimeException("FOO"); + } + }); + step.afterPropertiesSet(); + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals("FOO", stepExecution.getFailureExceptions().get(0).getMessage()); + } + + @Test + public void testExecuteRestart() throws Exception { + + DefaultJobParametersExtractor jobParametersExtractor = new DefaultJobParametersExtractor(); + jobParametersExtractor.setKeys(new String[] {"foo"}); + ExecutionContext executionContext = stepExecution.getExecutionContext(); + executionContext.put("foo", "bar"); + step.setJobParametersExtractor(jobParametersExtractor); + + step.setJob(new JobSupport("child") { + @Override + public void execute(JobExecution execution) throws UnexpectedJobExecutionException { + assertEquals(1, execution.getJobInstance().getJobParameters().getParameters().size()); + execution.setStatus(BatchStatus.FAILED); + execution.setEndTime(new Date()); + jobRepository.update(execution); + throw new RuntimeException("FOO"); + } + @Override + public boolean isRestartable() { + return true; + } + }); + step.afterPropertiesSet(); + step.execute(stepExecution); + assertEquals("FOO", stepExecution.getFailureExceptions().get(0).getMessage()); + JobExecution jobExecution = stepExecution.getJobExecution(); + jobExecution.setEndTime(new Date()); + jobRepository.update(jobExecution); + + jobExecution = jobRepository.createJobExecution("job", new JobParameters()); + stepExecution = jobExecution.createStepExecution("step"); + // In a restart the surrounding Job would set up the context like this... + stepExecution.setExecutionContext(executionContext); + jobRepository.add(stepExecution); + step.execute(stepExecution); + assertEquals("FOO", stepExecution.getFailureExceptions().get(0).getMessage()); + + } + +} diff --git a/spring-batch-samples/.springBeans b/spring-batch-samples/.springBeans index 2a7d109fb..115962acc 100644 --- a/spring-batch-samples/.springBeans +++ b/spring-batch-samples/.springBeans @@ -1,7 +1,7 @@ 1 - + @@ -74,6 +74,8 @@ src/test/resources/org/springframework/batch/sample/GroovyJobFunctionalTests-context.xml src/test/resources/org/springframework/batch/sample/TaskletJobFunctionalTests-context.xml src/main/resources/jobs/partitionJdbcJob.xml + src/main/resources/jobs/jobStepSample.xml + src/main/resources/jobs/partitionFileJob.xml diff --git a/spring-batch-samples/src/main/resources/jobs/jobStepSample.xml b/spring-batch-samples/src/main/resources/jobs/jobStepSample.xml new file mode 100644 index 000000000..9f8dae918 --- /dev/null +++ b/spring-batch-samples/src/main/resources/jobs/jobStepSample.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobStepFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobStepFunctionalTests.java new file mode 100644 index 000000000..19f08d249 --- /dev/null +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobStepFunctionalTests.java @@ -0,0 +1,71 @@ +/* + * 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.sample; + +import static org.junit.Assert.assertEquals; + +import javax.sql.DataSource; + +import org.junit.After; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.converter.DefaultJobParametersConverter; +import org.springframework.batch.support.PropertiesConverter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * Sample using a step to launch a job. + * + * @author Dave Syer + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration() +public class JobStepFunctionalTests extends AbstractBatchLauncherTests { + + // auto-injected attributes + private SimpleJdbcTemplate simpleJdbcTemplate; + + @Autowired + public void setJob(@Qualifier("jobStepJob") Job job) { + super.setJob(job); + } + + @Autowired + public void setDataSource(DataSource dataSource) { + this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); + } + + @Before + public void onTearDown() throws Exception { + simpleJdbcTemplate.update("DELETE FROM TRADE"); + setJobParameters(new DefaultJobParametersConverter() + .getJobParameters(PropertiesConverter + .stringToProperties("run.id(long)=1,parameter=true,run.date=20070122,input.file=classpath:data/fixedLengthImportJob/input/20070122.teststream.ImportTradeDataStep.txt"))); + } + + @After + public void onSetUp() { + int after = simpleJdbcTemplate.queryForInt("SELECT COUNT(*) FROM TRADE"); + assertEquals(5, after); + } + +} diff --git a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/JobStepFunctionalTests-context.xml b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/JobStepFunctionalTests-context.xml new file mode 100644 index 000000000..74bdf371c --- /dev/null +++ b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/JobStepFunctionalTests-context.xml @@ -0,0 +1,10 @@ + + + + + + +