I'm developing a Spring Boot 3.3.5 application using Spring Batch. I need to separate the Spring Batch database from the main application database. Additionally, I need to ensure that jobs do not run at application startup, as I want to execute them explicitly and programmatically. I tried using the property spring.batch.job.enabled=false, but the jobs still run at runtime. Perhaps something in my configuration is causing this issue.
Here is the configuration for multiple data sources:
@Configuration
@Profile({"!test"})
public class DataSourceFactory {
@Bean
@BatchDataSource
public DataSource h2Datasource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:/springframework/batch/core/schema-drop-h2.sql")
.addScript("//springframework/batch/core/schema-h2.sql")
.build();
}
@Bean
@BatchTransactionManager
public PlatformTransactionManager batchTransactionManager() {
return new JdbcTransactionManager(h2Datasource());
}
@Bean
@Primary
@ConfigurationProperties("spring.datasource")
public DataSourceProperties oracleDatasourceProperties() {
return new DataSourceProperties();
}
@Bean
@Primary
@ConfigurationProperties("spring.datasource.hikari")
public DataSource oracleDatasource() {
return oracleDatasourceProperties().initializeDataSourceBuilder().build();
}
@Bean
@Primary
public PlatformTransactionManager transactionManager() {
return new JdbcTransactionManager(oracleDatasource());
}
}
This the job:
@Configuration
@RequiredArgsConstructor
public class NotificationJobConfig {
private final JobRepository jobRepository;
...
@Bean
public Job notificationJob() {
return new JobBuilder(NOTIFICATION_JOB, jobRepository)
...
.build();
}
}
The is the service running the job:
@Service
@Slf4j
public class JobServiceImpl implements JobService {
@Autowired
private JobLauncher jobLauncher;
@Autowired
@Qualifier(NotificationJobConfig.NOTIFICATION_JOB)
private Job notificationJob;
@Override
public void runNotification() {
try {
JobParameters jobParameters = new JobParametersBuilder().addLocalDateTime("timestamp", LocalDateTime.now()).toJobParameters();
jobLauncher.run(notificationJob, jobParameters);
} catch (Exception e) {
log.error("Error starting notification job: {}", e.getMessage(), e);
}
}
}
I made a second solution adding a class configuration with @EnableBatchProcessing:
@Configuration
@EnableBatchProcessing
public class BatchConfig {
}
but in this case spring complains with this message:
Field jobLauncher in it.coop.coopitalia.rs.service.JobServiceImpl required a bean named 'dataSource' that could not be found.
At the end I tried to use DefaultBatchConfiguration instead of @EnableBatchProcessing like this:
@Configuration
public class BatchConfig extends DefaultBatchConfiguration {
@Autowired
@BatchDataSource
private DataSource batchDatasource;
@Autowired
@BatchTransactionManager
private PlatformTransactionManager batchTransactionManager;
@Override
protected DataSource getDataSource() {
return batchDatasource;
}
@Override
protected PlatformTransactionManager getTransactionManager() {
return this.batchTransactionManager;
}
@Bean
public JobLauncher jobLauncher() {
TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
try {
jobLauncher.setJobRepository(jobRepository());
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}
return jobLauncher;
}
}
But again the problem is that job automatically run at application start-up.
So, there is something I'm doing wrong... any ideas?
I'm developing a Spring Boot 3.3.5 application using Spring Batch. I need to separate the Spring Batch database from the main application database. Additionally, I need to ensure that jobs do not run at application startup, as I want to execute them explicitly and programmatically. I tried using the property spring.batch.job.enabled=false, but the jobs still run at runtime. Perhaps something in my configuration is causing this issue.
Here is the configuration for multiple data sources:
@Configuration
@Profile({"!test"})
public class DataSourceFactory {
@Bean
@BatchDataSource
public DataSource h2Datasource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:/springframework/batch/core/schema-drop-h2.sql")
.addScript("//springframework/batch/core/schema-h2.sql")
.build();
}
@Bean
@BatchTransactionManager
public PlatformTransactionManager batchTransactionManager() {
return new JdbcTransactionManager(h2Datasource());
}
@Bean
@Primary
@ConfigurationProperties("spring.datasource")
public DataSourceProperties oracleDatasourceProperties() {
return new DataSourceProperties();
}
@Bean
@Primary
@ConfigurationProperties("spring.datasource.hikari")
public DataSource oracleDatasource() {
return oracleDatasourceProperties().initializeDataSourceBuilder().build();
}
@Bean
@Primary
public PlatformTransactionManager transactionManager() {
return new JdbcTransactionManager(oracleDatasource());
}
}
This the job:
@Configuration
@RequiredArgsConstructor
public class NotificationJobConfig {
private final JobRepository jobRepository;
...
@Bean
public Job notificationJob() {
return new JobBuilder(NOTIFICATION_JOB, jobRepository)
...
.build();
}
}
The is the service running the job:
@Service
@Slf4j
public class JobServiceImpl implements JobService {
@Autowired
private JobLauncher jobLauncher;
@Autowired
@Qualifier(NotificationJobConfig.NOTIFICATION_JOB)
private Job notificationJob;
@Override
public void runNotification() {
try {
JobParameters jobParameters = new JobParametersBuilder().addLocalDateTime("timestamp", LocalDateTime.now()).toJobParameters();
jobLauncher.run(notificationJob, jobParameters);
} catch (Exception e) {
log.error("Error starting notification job: {}", e.getMessage(), e);
}
}
}
I made a second solution adding a class configuration with @EnableBatchProcessing:
@Configuration
@EnableBatchProcessing
public class BatchConfig {
}
but in this case spring complains with this message:
Field jobLauncher in it.coop.coopitalia.rs.service.JobServiceImpl required a bean named 'dataSource' that could not be found.
At the end I tried to use DefaultBatchConfiguration instead of @EnableBatchProcessing like this:
@Configuration
public class BatchConfig extends DefaultBatchConfiguration {
@Autowired
@BatchDataSource
private DataSource batchDatasource;
@Autowired
@BatchTransactionManager
private PlatformTransactionManager batchTransactionManager;
@Override
protected DataSource getDataSource() {
return batchDatasource;
}
@Override
protected PlatformTransactionManager getTransactionManager() {
return this.batchTransactionManager;
}
@Bean
public JobLauncher jobLauncher() {
TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
try {
jobLauncher.setJobRepository(jobRepository());
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}
return jobLauncher;
}
}
But again the problem is that job automatically run at application start-up.
So, there is something I'm doing wrong... any ideas?
Share asked Mar 7 at 12:18 Giuseppe GalloGiuseppe Gallo 1071 silver badge9 bronze badges 3 |1 Answer
Reset to default 0It seems like the spring.batch.job.enabled=false
property is not taken into account in your case. I gave that a quick test and things seem to work as expected:
import .springframework.batch.core.Job;
import .springframework.batch.core.Step;
import .springframework.batch.core.job.builder.JobBuilder;
import .springframework.batch.core.repository.JobRepository;
import .springframework.batch.core.step.builder.StepBuilder;
import .springframework.batch.repeat.RepeatStatus;
import .springframework.beans.factory.annotation.Qualifier;
import .springframework.boot.SpringApplication;
import .springframework.boot.autoconfigure.SpringBootApplication;
import .springframework.boot.autoconfigure.batch.BatchDataSource;
import .springframework.boot.autoconfigure.batch.BatchTransactionManager;
import .springframework.context.annotation.Bean;
import .springframework.context.annotation.Primary;
import .springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import .springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import .springframework.jdbc.support.JdbcTransactionManager;
import javax.sql.DataSource;
@SpringBootApplication
public class SO79492302Application {
public static void main(String[] args) {
SpringApplication.run(SO79492302Application.class, args);
}
@Bean
public Job job(JobRepository jobRepository, JdbcTransactionManager transactionManager) {
Step myStep = new StepBuilder("myStep", jobRepository)
.tasklet((contribution, chunkContext)
-> { System.out.println("Hello world!");
return RepeatStatus.FINISHED;
}, transactionManager)
.build();
return new JobBuilder("myJob", jobRepository)
.start(myStep)
.build();
}
// batch infrastructure
@Bean
@BatchDataSource
public DataSource batchDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("//springframework/batch/core/schema-h2.sql")
.build();
}
@Bean
@BatchTransactionManager
public JdbcTransactionManager batchTransactionManager(@Qualifier("batchDataSource") DataSource batchDataSource) {
return new JdbcTransactionManager(batchDataSource);
}
// business infrastructure
@Bean
@Primary
public DataSource datasource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
}
The pom.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache./POM/4.0.0" xmlns:xsi="http://www.w3./2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache./POM/4.0.0 https://maven.apache./xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-batch-resourceles-job-repository</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-batch-resourceles-job-repository</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The application.properties
file:
spring.batch.job.enabled=false
prints:
:: Spring Boot :: (v3.4.3)
2025-03-07T08:26:54.089-05:00 INFO 21002 --- [ main] c.e.s.SO79492302Application : Starting SO79492302Application using Java 21.0.2 with PID 21002
2025-03-07T08:26:54.090-05:00 INFO 21002 --- [ main] c.e.s.SO79492302Application : No active profile set, falling back to 1 default profile: "default"
2025-03-07T08:26:54.333-05:00 INFO 21002 --- [ main] o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database: url='jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
2025-03-07T08:26:54.430-05:00 INFO 21002 --- [ main] o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database: url='jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
2025-03-07T08:26:54.543-05:00 INFO 21002 --- [ main] c.e.s.SO79492302Application : Started SO79492302Application in 0.628 seconds (process running for 0.797)
2025-03-07T08:26:54.546-05:00 INFO 21002 --- [ionShutdownHook] o.s.j.d.e.EmbeddedDatabaseFactory : Shutting down embedded database: url='jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false'
2025-03-07T08:26:54.547-05:00 INFO 21002 --- [ionShutdownHook] o.s.j.d.e.EmbeddedDatabaseFactory : Shutting down embedded database: url='jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false'
The job did not run on startup as expected.
spring.batch.job.enabled=false
the job should not run. If it does, it means that that property is not taken into account. Probably what you are seeing is the job running during tests? BTW, remove the usage ofDefaultBatchConfiguration
and@EnableBatchProcessing
, you don't need that for your case. – Mahmoud Ben Hassine Commented Mar 7 at 13:21