Issue
I am working on REST-service (with Spring boot), which runs batch job. I want Batch to work only with embedded datasource (to store metadata), while default datasource (Postgres in my case) will be used to store buisness entities.
The problem is that Batch tries to create metadata tables (like batch_job_execution, batch_job_instance, etc.) in default datasource at startup.
Here is the sample configuration, which reproduces the problem:
BatchConfiguration
@Configuration
@EnableBatchProcessing
public class BatchConfiguration extends DefaultBatchConfigurer {
@Override
@Autowired
public void setDataSource(@Qualifier("batchDataSource") DataSource dataSource) {
super.setDataSource(dataSource);
}
}
DataSourceConfiguration
@Configuration
public class DataSourceConfiguration {
@Bean
@Primary
public DataSource DataSource() {
final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(org.postgresql.Driver.class);
dataSource.setUrl("jdbc:postgresql://localhost:5432/test_batch");
dataSource.setUsername("user");
dataSource.setPassword("password");
return dataSource;
}
@Bean(name = "batchDataSource")
public DataSource batchDataSource() {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
}
}
With this configuration I am getting batch tables in Postgres when microservice started, though aftewards, it seems, that embeded datasource is used, because I am getting "Table not found" error for H2 when trying to launch a job.
So how should I properly write configuration to make Batch work only with embedded datasource? I don't want any metadata (even empty tables) in main datasource.
UPDATE:
As Michael Minella said, one more bean should be added:
@Configuration
@EnableBatchProcessing
public class BatchConfiguration extends DefaultBatchConfigurer {
@Override
@Autowired
public void setDataSource(@Qualifier("batchDataSource") DataSource dataSource) {
super.setDataSource(dataSource);
}
@Bean
public BatchDatabaseInitializer batchDatabaseInitializer(@Qualifier("batchDataSource") DataSource dataSource, ResourceLoader resourceLoader){
BatchDatabaseInitializer batchDatabaseInitializer = new BatchDatabaseInitializer(dataSource, resourceLoader, new BatchProperties());
return batchDatabaseInitializer;
}
}
Solution
Using Spring Boot the DataSource
that is used by the BatchDataSourceInitializer
is, unfortunately, not related to the BatchConfigurer
. It just grabs the default DataSource
in the context. If you configure your own BatchDataSourceInitializer
, the Boot one won't kick in and you can define which DataSource
is used directly.
Answered By - Michael Minella
Answer Checked By - Clifford M. (JavaFixing Volunteer)