diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/launch/JsrJobOperator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/launch/JsrJobOperator.java index 2ce7efdcd..9fa0e55d8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/launch/JsrJobOperator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/launch/JsrJobOperator.java @@ -81,6 +81,7 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.core.task.TaskExecutor; +import org.springframework.transaction.PlatformTransactionManager; import org.springframework.util.Assert; /** @@ -144,7 +145,8 @@ public class JsrJobOperator implements JobOperator, InitializingBean { private JobRepository jobRepository; private TaskExecutor taskExecutor; private JobParametersConverter jobParametersConverter; - private static ApplicationContext baseContext; + private ApplicationContext baseContext; + private PlatformTransactionManager transactionManager; private static ExecutingJobRegistry jobRegistry = new ExecutingJobRegistry(); /** @@ -174,14 +176,16 @@ public class JsrJobOperator implements JobOperator, InitializingBean { * @param jobRepository an instance of Spring Batch's {@link JobOperator} * @param jobParametersConverter an instance of Spring Batch's {@link JobParametersConverter} */ - public JsrJobOperator(JobExplorer jobExplorer, JobRepository jobRepository, JobParametersConverter jobParametersConverter) { + public JsrJobOperator(JobExplorer jobExplorer, JobRepository jobRepository, JobParametersConverter jobParametersConverter, PlatformTransactionManager transactionManager) { Assert.notNull(jobExplorer, "A JobExplorer is required"); Assert.notNull(jobRepository, "A JobRepository is required"); Assert.notNull(jobParametersConverter, "A ParametersConverter is required"); + Assert.notNull(transactionManager, "A PlatformTransactionManager is required"); this.jobExplorer = jobExplorer; this.jobRepository = jobRepository; this.jobParametersConverter = jobParametersConverter; + this.transactionManager = transactionManager; } public void setJobExplorer(JobExplorer jobExplorer) { @@ -607,7 +611,14 @@ public class JsrJobOperator implements JobOperator, InitializingBean { beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON); batchContext.registerBeanDefinition(JSR_JOB_CONTEXT_BEAN_NAME, beanDefinition); - batchContext.setParent(baseContext); + if(baseContext != null) { + batchContext.setParent(baseContext); + } else { + batchContext.getBeanFactory().registerSingleton("jobExplorer", jobExplorer); + batchContext.getBeanFactory().registerSingleton("jobRepository", jobRepository); + batchContext.getBeanFactory().registerSingleton("jobParametersConverter", jobParametersConverter); + batchContext.getBeanFactory().registerSingleton("transactionManager", transactionManager); + } try { batchContext.refresh(); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/CustomWiredJsrJobOperatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/CustomWiredJsrJobOperatorTests.java new file mode 100644 index 000000000..91e10b002 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/CustomWiredJsrJobOperatorTests.java @@ -0,0 +1,61 @@ +/* + * Copyright 2014 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.jsr.configuration.xml; + +import java.util.Date; +import java.util.Properties; +import java.util.concurrent.TimeoutException; + +import javax.batch.operations.JobOperator; +import javax.batch.runtime.BatchStatus; +import javax.batch.runtime.JobExecution; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Michael Minella + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class CustomWiredJsrJobOperatorTests { + + @Autowired + JobOperator jobOperator; + + @Test + public void testRunningJobWithManuallyWiredJsrJobOperator() throws Exception { + Date startTime = new Date(); + long jobExecutionId = jobOperator.start("jsrJobOperatorTestJob", new Properties()); + + JobExecution jobExecution = jobOperator.getJobExecution(jobExecutionId); + + long timeout = startTime.getTime() + 10000; + + while(!jobExecution.getBatchStatus().equals(BatchStatus.COMPLETED)) { + Thread.sleep(500); + jobExecution = jobOperator.getJobExecution(jobExecutionId); + + if(new Date().getTime() > timeout) { + throw new TimeoutException("Job didn't finish within 10 seconds"); + } + } + } +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/launch/JsrJobOperatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/launch/JsrJobOperatorTests.java index b61e9db83..02323ad4b 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/launch/JsrJobOperatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/launch/JsrJobOperatorTests.java @@ -15,26 +15,20 @@ */ package org.springframework.batch.core.jsr.launch; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.converter.JobParametersConverter; -import org.springframework.batch.core.converter.JobParametersConverterSupport; -import org.springframework.batch.core.explore.JobExplorer; -import org.springframework.batch.core.explore.support.SimpleJobExplorer; -import org.springframework.batch.core.jsr.AbstractJsrTestCase; -import org.springframework.batch.core.jsr.JsrJobParametersConverter; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.step.JobRepositorySupport; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.core.task.AsyncTaskExecutor; -import org.springframework.core.task.SyncTaskExecutor; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; import javax.batch.api.AbstractBatchlet; import javax.batch.api.Batchlet; @@ -47,20 +41,29 @@ import javax.batch.operations.NoSuchJobExecutionException; import javax.batch.operations.NoSuchJobInstanceException; import javax.batch.runtime.BatchRuntime; import javax.batch.runtime.BatchStatus; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Properties; -import java.util.Set; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.converter.JobParametersConverter; +import org.springframework.batch.core.converter.JobParametersConverterSupport; +import org.springframework.batch.core.explore.JobExplorer; +import org.springframework.batch.core.explore.support.SimpleJobExplorer; +import org.springframework.batch.core.jsr.AbstractJsrTestCase; +import org.springframework.batch.core.jsr.JsrJobParametersConverter; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.JobRepositorySupport; +import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.core.task.AsyncTaskExecutor; +import org.springframework.core.task.SyncTaskExecutor; public class JsrJobOperatorTests extends AbstractJsrTestCase { @@ -76,7 +79,7 @@ public class JsrJobOperatorTests extends AbstractJsrTestCase { public void setup() { MockitoAnnotations.initMocks(this); parameterConverter = new JobParametersConverterSupport(); - jsrJobOperator = new JsrJobOperator(jobExplorer, jobRepository, parameterConverter); + jsrJobOperator = new JsrJobOperator(jobExplorer, jobRepository, parameterConverter, new ResourcelessTransactionManager()); } @Test @@ -88,24 +91,30 @@ public class JsrJobOperatorTests extends AbstractJsrTestCase { @Test public void testNullsInConstructor() { try { - new JsrJobOperator(null, new JobRepositorySupport(), parameterConverter); + new JsrJobOperator(null, new JobRepositorySupport(), parameterConverter, null); fail("JobExplorer should be required"); } catch (IllegalArgumentException correct) { } try { - new JsrJobOperator(new SimpleJobExplorer(null, null, null, null), null, parameterConverter); + new JsrJobOperator(new SimpleJobExplorer(null, null, null, null), null, parameterConverter, null); fail("JobRepository should be required"); } catch (IllegalArgumentException correct) { } try { - new JsrJobOperator(new SimpleJobExplorer(null, null, null, null), new JobRepositorySupport(), null); + new JsrJobOperator(new SimpleJobExplorer(null, null, null, null), new JobRepositorySupport(), null, null); fail("ParameterConverter should be required"); } catch (IllegalArgumentException correct) { } - new JsrJobOperator(new SimpleJobExplorer(null, null, null, null), new JobRepositorySupport(), parameterConverter); + try { + new JsrJobOperator(new SimpleJobExplorer(null, null, null, null), new JobRepositorySupport(), parameterConverter, null); + } + catch (IllegalArgumentException correct) { + } + + new JsrJobOperator(new SimpleJobExplorer(null, null, null, null), new JobRepositorySupport(), parameterConverter, new ResourcelessTransactionManager()); } @Test diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/jsr/configuration/xml/CustomWiredJsrJobOperatorTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/jsr/configuration/xml/CustomWiredJsrJobOperatorTests-context.xml new file mode 100644 index 000000000..c0c4f1535 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/jsr/configuration/xml/CustomWiredJsrJobOperatorTests-context.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file