Skip to content
This repository was archived by the owner on Mar 29, 2019. It is now read-only.

Commit 2d55e59

Browse files
committed
Add ability to configure jobs via java configuration
This commit provides the ability to configure Spring Batch jobs via java configuration. While a user will not want to use @EnableBatchProcessing with Spring Batch Admin, this allows the user to configure a package (org.springframework.batch.admin.sample.job by default) that will be scanned for classes using @configuration to define jobs. All other functionality related to jobs will be applied to these jobs. BATCHADM-209
1 parent 6be7910 commit 2d55e59

File tree

8 files changed

+226
-30
lines changed

8 files changed

+226
-30
lines changed

spring-batch-admin-manager/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ visualization of Batch meta data, and also launching and stopping jobs inside th
167167
<dependency>
168168
<groupId>org.springframework.batch</groupId>
169169
<artifactId>spring-batch-admin-resources</artifactId>
170-
<version>2.0.0.BUILD-SNAPSHOT</version>
170+
<version>${project.parent.version}</version>
171171
</dependency>
172172
<dependency>
173173
<groupId>com.fasterxml.jackson.core</groupId>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.admin.configuration;
17+
18+
import java.util.ArrayList;
19+
import java.util.Arrays;
20+
import java.util.List;
21+
22+
import org.springframework.batch.core.configuration.support.ApplicationContextFactory;
23+
import org.springframework.beans.factory.FactoryBean;
24+
import org.springframework.beans.factory.InitializingBean;
25+
import org.springframework.util.Assert;
26+
import org.springframework.util.CollectionUtils;
27+
28+
/**
29+
* @author Michael Minella
30+
*/
31+
public class CompositeApplicationContextFactory implements FactoryBean<ApplicationContextFactory[]>, InitializingBean {
32+
33+
private List<FactoryBean<ApplicationContextFactory[]>> factoryBeans;
34+
35+
private List<ApplicationContextFactory> delegateFactories;
36+
37+
public void setFactoryBeans(List<FactoryBean<ApplicationContextFactory[]>> factoryBeans) {
38+
this.factoryBeans = factoryBeans;
39+
}
40+
41+
public void setFactories(List<ApplicationContextFactory> delegateFactories) {
42+
this.delegateFactories = delegateFactories;
43+
}
44+
45+
@Override
46+
public ApplicationContextFactory[] getObject() throws Exception {
47+
List<ApplicationContextFactory> factories = new ArrayList<ApplicationContextFactory>();
48+
49+
if(factoryBeans != null) {
50+
for (FactoryBean<ApplicationContextFactory[]> factory : factoryBeans) {
51+
factories.addAll(Arrays.asList(factory.getObject()));
52+
}
53+
}
54+
55+
if(delegateFactories != null) {
56+
factories.addAll(delegateFactories);
57+
}
58+
59+
return factories.toArray(new ApplicationContextFactory[factories.size()]);
60+
}
61+
62+
@Override
63+
public Class<?> getObjectType() {
64+
return ApplicationContextFactory[].class;
65+
}
66+
67+
@Override
68+
public boolean isSingleton() {
69+
return true;
70+
}
71+
72+
@Override
73+
public void afterPropertiesSet() throws Exception {
74+
Assert.state(!CollectionUtils.isEmpty(factoryBeans) || !CollectionUtils.isEmpty(delegateFactories),
75+
"A factory or factoryBean is required");
76+
}
77+
}

spring-batch-admin-manager/src/main/resources/META-INF/spring/batch/bootstrap/manager/execution-context.xml

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,29 @@
3434
<bean id="jobExplorer" class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean"
3535
p:dataSource-ref="dataSource" />
3636

37-
<bean id="jobLoader" class="org.springframework.batch.core.configuration.support.AutomaticJobRegistrar">
38-
<property name="applicationContextFactories">
39-
<bean class="org.springframework.batch.core.configuration.support.ClasspathXmlApplicationContextsFactoryBean">
40-
<property name="resources" value="classpath*:/META-INF/spring/batch/jobs/*.xml" />
41-
</bean>
37+
<bean id="applicationContextFactories" class="org.springframework.batch.admin.configuration.CompositeApplicationContextFactory">
38+
<property name="factoryBeans">
39+
<list>
40+
<ref bean="&amp;xmlJobContextFactories"/>
41+
</list>
42+
</property>
43+
<property name="factories">
44+
<list>
45+
<ref bean="javaJobContextFactories"/>
46+
</list>
4247
</property>
48+
</bean>
49+
50+
<bean id="xmlJobContextFactories" class="org.springframework.batch.core.configuration.support.ClasspathXmlApplicationContextsFactoryBean">
51+
<property name="resources" value="classpath*:/META-INF/spring/batch/jobs/*.xml" />
52+
</bean>
53+
54+
<bean id="javaJobContextFactories" class="org.springframework.batch.core.configuration.support.GenericApplicationContextFactory">
55+
<constructor-arg value="${batch.job.configuration.package:org.springframework.batch.admin.sample.job}"/>
56+
</bean>
57+
58+
<bean id="jobLoader" class="org.springframework.batch.core.configuration.support.AutomaticJobRegistrar">
59+
<property name="applicationContextFactories" ref="applicationContextFactories"/>
4360
<property name="jobLoader">
4461
<bean class="org.springframework.batch.core.configuration.support.DefaultJobLoader">
4562
<property name="jobRegistry" ref="jobRegistry" />
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* Copyright 2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.admin.configuration;
17+
18+
import static org.junit.Assert.assertEquals;
19+
import static org.junit.Assert.assertTrue;
20+
21+
import java.util.Arrays;
22+
23+
import org.junit.Before;
24+
import org.junit.Test;
25+
26+
import org.springframework.batch.core.configuration.support.ApplicationContextFactory;
27+
import org.springframework.batch.core.configuration.support.ClasspathXmlApplicationContextsFactoryBean;
28+
import org.springframework.batch.core.configuration.support.GenericApplicationContextFactory;
29+
import org.springframework.beans.factory.FactoryBean;
30+
import org.springframework.core.io.ClassPathResource;
31+
import org.springframework.core.io.Resource;
32+
33+
/**
34+
* @author Michael Minella
35+
*/
36+
public class CompositeApplicationContextFactoryTests {
37+
38+
private CompositeApplicationContextFactory factory;
39+
40+
@Before
41+
public void setUp() {
42+
factory = new CompositeApplicationContextFactory();
43+
}
44+
45+
@Test
46+
public void testAfterPropertiesSet() throws Exception {
47+
try {
48+
factory.afterPropertiesSet();
49+
} catch (Exception expected) {
50+
assertEquals(expected.getMessage(), "A factory or factoryBean is required");
51+
}
52+
53+
factory.setFactories(Arrays.<ApplicationContextFactory>asList(new GenericApplicationContextFactory(null)));
54+
55+
factory.afterPropertiesSet();
56+
57+
factory = new CompositeApplicationContextFactory();
58+
factory.setFactoryBeans(Arrays.<FactoryBean<ApplicationContextFactory[]>>asList(new ClasspathXmlApplicationContextsFactoryBean()));
59+
factory.afterPropertiesSet();
60+
}
61+
62+
@Test
63+
public void testIsSingleton() {
64+
assertTrue(factory.isSingleton());
65+
}
66+
67+
@Test
68+
public void testGetObjectType() {
69+
assertTrue(factory.getObjectType().equals(ApplicationContextFactory[].class));
70+
}
71+
72+
@Test
73+
public void testGetObjectFactorBeansOnly() throws Exception {
74+
ClasspathXmlApplicationContextsFactoryBean classpathXmlApplicationContextsFactoryBean =
75+
new ClasspathXmlApplicationContextsFactoryBean();
76+
77+
Resource resource1 = new ClassPathResource("classpath:dummy-context.xml");
78+
Resource resource2 = new ClassPathResource("classpath:dummy-context.xml");
79+
80+
classpathXmlApplicationContextsFactoryBean.setResources(new Resource[] {resource1, resource2});
81+
82+
factory.setFactoryBeans(Arrays.<FactoryBean<ApplicationContextFactory[]>>asList(
83+
classpathXmlApplicationContextsFactoryBean));
84+
85+
factory.afterPropertiesSet();
86+
87+
assertEquals(2, factory.getObject().length);
88+
}
89+
90+
@Test
91+
public void testGetObjectFactoriesOnly() throws Exception {
92+
Resource resource1 = new ClassPathResource("classpath:dummy-context.xml");
93+
Resource resource2 = new ClassPathResource("classpath:dummy-context.xml");
94+
95+
factory.setFactories(Arrays.<ApplicationContextFactory>asList(new GenericApplicationContextFactory(resource1),
96+
new GenericApplicationContextFactory(resource2)));
97+
factory.afterPropertiesSet();
98+
99+
assertEquals(2, factory.getObject().length);
100+
}
101+
102+
@Test
103+
public void testGetObjectBothOptionsProvided() throws Exception {
104+
ClasspathXmlApplicationContextsFactoryBean classpathXmlApplicationContextsFactoryBean =
105+
new ClasspathXmlApplicationContextsFactoryBean();
106+
107+
Resource resource1 = new ClassPathResource("classpath:dummy-context.xml");
108+
Resource resource2 = new ClassPathResource("classpath:dummy-context.xml");
109+
110+
classpathXmlApplicationContextsFactoryBean.setResources(new Resource[] {resource1, resource2});
111+
112+
factory.setFactoryBeans(Arrays.<FactoryBean<ApplicationContextFactory[]>>asList(
113+
classpathXmlApplicationContextsFactoryBean));
114+
115+
Resource resource3 = new ClassPathResource("classpath:dummy-context.xml");
116+
Resource resource4 = new ClassPathResource("classpath:dummy-context.xml");
117+
118+
factory.setFactories(Arrays.<ApplicationContextFactory>asList(new GenericApplicationContextFactory(resource3),
119+
new GenericApplicationContextFactory(resource4)));
120+
factory.afterPropertiesSet();
121+
122+
assertEquals(4, factory.getObject().length);
123+
}
124+
}

spring-batch-admin-manager/src/test/resources/org/springframework/batch/admin/launch/JobLauncherSynchronizerIntegrationTests-context.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xmlns:aop="http://www.springframework.org/schema/aop"
55
xmlns:beans="http://www.springframework.org/schema/beans"
6-
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
6+
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
77
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
88
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
99

spring-batch-admin-sample/src/main/resources/META-INF/spring/batch/jobs/java-jobs-context.xml

Lines changed: 0 additions & 9 deletions
This file was deleted.

spring-batch-admin-sample/src/test/java/org/springframework/batch/admin/sample/BootstrapTests.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,11 @@
3333
import org.springframework.batch.poller.DirectPoller;
3434
import org.springframework.beans.factory.BeanFactoryUtils;
3535
import org.springframework.context.support.ClassPathXmlApplicationContext;
36-
import org.springframework.test.annotation.DirtiesContext;
3736

3837
/**
3938
* @author Dave Syer
4039
*
4140
*/
42-
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
4341
public class BootstrapTests {
4442

4543
@Test

spring-batch-admin-sample/src/test/resources/org/springframework/batch/admin/sample/JobExecutionTests-context.xml

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,7 @@
88

99
<bean id="jobLauncherTaskExecutor" class="org.springframework.core.task.SyncTaskExecutor"/>
1010
<!-- prevent loading of other jobs by overriding the loader in the main bootstrap context -->
11-
<bean id="jobLoader" class="org.springframework.batch.core.configuration.support.AutomaticJobRegistrar">
12-
<property name="applicationContextFactories">
13-
<bean class="org.springframework.batch.core.configuration.support.ClasspathXmlApplicationContextsFactoryBean">
14-
<property name="resources" value="classpath:/META-INF/spring/batch/jobs/*.xml" />
15-
</bean>
16-
</property>
17-
<property name="jobLoader">
18-
<bean class="org.springframework.batch.core.configuration.support.DefaultJobLoader">
19-
<property name="jobRegistry" ref="jobRegistry" />
20-
</bean>
21-
</property>
22-
</bean>
11+
<!--<bean id="jobLoader" class="java.lang.String"/>-->
2312

2413
<integration:channel id="job-requests"/>
2514

0 commit comments

Comments
 (0)