When adding more jobs to an ApplicationContext
, you will soon run into problems with the naming and the uniqueness of beans. Normally you define one configuration class or one configuration XML file for each job, and then it feels natural to name the ItemReader
reader
. When adding both configurations to the ApplicationContext
, we have two beans with the same name – reader
. If we’re lucky, we get an Exception
when starting the ApplicationContext
, if we’re not they silently override each other. How can we deal with this problem?
This is the fifth post about the new Java based configuration features in Spring Batch 2.2. Previous posts are about a comparison between the new Java DSL and XML , JobParameters, ExecutionContexts and StepScope , profiles and environments and job inheritance . Future posts will be about partitioning and multi-threaded step , everything regarding Java based configuration, of course. You can find the JavaConfig code examples on Github .
The solution to this problem is the following construct:
Instead of having just one ApplicationContext
we have one for each job, this way we have no problems with bean naming or overriding. The infrastructure part resides in a common parent ApplicationContext
, and we access jobs via the JobRegistry
defined in the parent context.
Let’s have a look at a modular job configuration:
1@Configuration
2@EnableBatchProcessing(modular=true)
3public class ModularJobConfiguration {
4
5 @Bean
6 public DataSource dataSource(){
7 EmbeddedDatabaseBuilder embeddedDatabaseBuilder = new EmbeddedDatabaseBuilder();
8 return embeddedDatabaseBuilder.addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql")
9 .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql")
10 .addScript("classpath:schema-partner.sql")
11 .setType(EmbeddedDatabaseType.HSQL)
12 .build();
13 }
14
15 @Bean
16 public ApplicationContextFactory someJobs() {
17 return new GenericApplicationContextFactory(FlatfileToDbJobConfiguration.class);
18 }
19
20 @Bean
21 public ApplicationContextFactory someMoreJobs() {
22 return new GenericApplicationContextFactory(FlatfileToDbWithParametersJobConfiguration.class);
23 }
24
25}
This way an AutomaticJobRegistrar
is added to the ApplicationContext
which is responsible for creating separate ApplicationContext
s for each bean of type ApplicationContextFactory
. So we have two jobs registered in two different client ApplicationContext
s. We can access them with the JobRegistry
:
1@ContextConfiguration(classes=ModularJobConfiguration.class)
2@RunWith(SpringJUnit4ClassRunner.class)
3public class ModularJobTests {
4
5 @Autowired
6 private JobRegistry jobRegistry;
7
8 @Autowired
9 private JobLauncher jobLauncher;
10
11 @Autowired
12 private DataSource dataSource;
13
14 private JdbcTemplate jdbcTemplate;
15
16 @Before
17 public void setup(){
18 jdbcTemplate = new JdbcTemplate(dataSource);
19 }
20
21 @Test
22 public void testLaunchJob() throws Exception {
23 Job job = jobRegistry.getJob("flatfileToDbJob");
24 jobLauncher.run(job, new JobParameters());
25 assertThat(jdbcTemplate.queryForObject("select count(*) from partner",Integer.class),is(6));
26 job = jobRegistry.getJob("flatfileToDbWithParametersJob");
27 assertThat(job.getName(),is("flatfileToDbWithParametersJob"));
28 }
29
30}
Conclusion
If you want to separate jobs in different contexts so that they don’t interfere with each other, make use of this modular configuration feature.
More articles
fromTobias Flohre
Your job at codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog author
Tobias Flohre
Senior Software Developer
Do you still have questions? Just send me a message.
Do you still have questions? Just send me a message.