diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BaseContextListFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BaseContextListFactoryBean.java new file mode 100644 index 000000000..ddfa81780 --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BaseContextListFactoryBean.java @@ -0,0 +1,56 @@ +/* + * 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.support; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.factory.FactoryBean; + +/** + * A simple factory bean that consolidates the list of locations to look for the base context for the JSR-352 + * functionality + * + * @author Michael Minella + * @since 3.0.3 + */ +public class BaseContextListFactoryBean implements FactoryBean>{ + + @Override + public List getObject() throws Exception { + String overrideContextLocation = System.getProperty("JSR-352-BASE-CONTEXT"); + + List contextLocations = new ArrayList(2); + + contextLocations.add("baseContext.xml"); + + if(overrideContextLocation != null) { + contextLocations.add(overrideContextLocation); + } + + return contextLocations; + } + + @Override + public Class getObjectType() { + return List.class; + } + + @Override + public boolean isSingleton() { + return true; + } +} 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 9fa0e55d8..d23a0263b 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 @@ -122,6 +122,9 @@ import org.springframework.util.Assert; * </bean> * </beans> * + * A custom configuration of the above components can be specified by providing a system property JSR-352-BASE-CONTEXT. + * The location that is provided by this system property will override any beans as defined in baseContext.xml. + * * Calls to {@link JobOperator#start(String, Properties)} will provide a child context to the above context * using the job definition and batch.xml if provided. * @@ -200,6 +203,12 @@ public class JsrJobOperator implements JobOperator, InitializingBean { this.jobRepository = jobRepository; } + public void setTransactionManager(PlatformTransactionManager transactionManager) { + Assert.notNull(transactionManager, "A PlatformTransactionManager is required"); + + this.transactionManager = transactionManager; + } + public void setTaskExecutor(TaskExecutor taskExecutor) { this.taskExecutor = taskExecutor; } diff --git a/spring-batch-core/src/main/resources/beanRefContext.xml b/spring-batch-core/src/main/resources/beanRefContext.xml index 2525a99f9..a7fb505a4 100644 --- a/spring-batch-core/src/main/resources/beanRefContext.xml +++ b/spring-batch-core/src/main/resources/beanRefContext.xml @@ -5,10 +5,9 @@ http://www.springframework.org/schema/beans/spring-beans.xsd"> - - - baseContext.xml - - + + + 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 02323ad4b..47af692b9 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 @@ -23,8 +23,11 @@ import static org.junit.Assert.fail; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Properties; @@ -62,8 +65,10 @@ 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.context.access.ContextSingletonBeanFactoryLocator; import org.springframework.core.task.AsyncTaskExecutor; import org.springframework.core.task.SyncTaskExecutor; +import org.springframework.test.util.ReflectionTestUtils; public class JsrJobOperatorTests extends AbstractJsrTestCase { @@ -76,7 +81,9 @@ public class JsrJobOperatorTests extends AbstractJsrTestCase { private static final long TIMEOUT = 10000L; @Before - public void setup() { + public void setup() throws Exception { + resetBaseContext(); + MockitoAnnotations.initMocks(this); parameterConverter = new JobParametersConverterSupport(); jsrJobOperator = new JsrJobOperator(jobExplorer, jobRepository, parameterConverter, new ResourcelessTransactionManager()); @@ -117,6 +124,38 @@ public class JsrJobOperatorTests extends AbstractJsrTestCase { new JsrJobOperator(new SimpleJobExplorer(null, null, null, null), new JobRepositorySupport(), parameterConverter, new ResourcelessTransactionManager()); } + @Test + public void testCustomBaseContext() throws Exception { + System.setProperty("JSR-352-BASE-CONTEXT", "META-INF/alternativeJsrBaseContext.xml"); + + JobOperator jobOperator = BatchRuntime.getJobOperator(); + + Object transactionManager = ReflectionTestUtils.getField(jobOperator, "transactionManager"); + assertTrue(transactionManager instanceof ResourcelessTransactionManager); + + long executionId = jobOperator.start("longRunningJob", null); + // Give the job a chance to get started + Thread.sleep(1000L); + jobOperator.stop(executionId); + // Give the job the chance to finish stopping + Thread.sleep(1000L); + + assertEquals(BatchStatus.STOPPED, jobOperator.getJobExecution(executionId).getBatchStatus()); + + System.getProperties().remove("JSR-352-BASE-CONTEXT"); + } + + private void resetBaseContext() throws NoSuchFieldException, IllegalAccessException { + Field instancesField = ContextSingletonBeanFactoryLocator.class.getDeclaredField("instances"); + instancesField.setAccessible(true); + + Field instancesModifiers = Field.class.getDeclaredField("modifiers"); + instancesModifiers.setAccessible(true); + instancesModifiers.setInt(instancesField, instancesField.getModifiers() & ~Modifier.FINAL); + + instancesField.set(null, new HashMap()); + } + @Test public void testDefaultTaskExecutor() throws Exception { JsrJobOperator jsrJobOperatorImpl = (JsrJobOperator) jsrJobOperator; diff --git a/spring-batch-core/src/test/resources/META-INF/alternativeJsrBaseContext.xml b/spring-batch-core/src/test/resources/META-INF/alternativeJsrBaseContext.xml new file mode 100644 index 000000000..1965bfe97 --- /dev/null +++ b/spring-batch-core/src/test/resources/META-INF/alternativeJsrBaseContext.xml @@ -0,0 +1,9 @@ + + + + +