最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Spring batch wiht separated datasource and job not running at application startup - Stack Overflow

programmeradmin2浏览0评论

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
  • with 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 of DefaultBatchConfiguration and @EnableBatchProcessing, you don't need that for your case. – Mahmoud Ben Hassine Commented Mar 7 at 13:21
  • I added an answer with a complete minimal example, hope it helps. – Mahmoud Ben Hassine Commented Mar 7 at 13:32
  • Actually, I was wrong. I put business logic code in the configuration part instead of the runtime job. So, at startup, the job was configured, but I thought it was the runtime job. Sorry. – Giuseppe Gallo Commented Mar 13 at 16:34
Add a comment  | 

1 Answer 1

Reset to default 0

It 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.

发布评论

评论列表(0)

  1. 暂无评论