springspring-bootspring-batchspring-boot-3spring-batch-job-monitoring

spring batch 5: how to NOT use the internal spring batch tables?


I am migrating my spring boot spring batch application from spring batch 4.x to 5.0 (this is part of spring boot 2.6.6 to 3.1.3 migration).

In our batch application we do not use any spring batch internal table (that spring batch uses for internal house keeping / status / history etc). On migrating to spring batch 5.0 the usage of these internal table seems to be the default behavior which I think was not the case in 4.x)

My Job Configuration looks like below -

@Configuration
@EnableBatchProcessing
@RequiredArgsConstructor
public class UpdateAssignedProductsJob {

  private static final int DEFAULT_CHUNK_SIZE = 25;

  public static final String JOB_NAME = JobName.UPDATE_ASSIGNED_PRODUCTS;

  @Bean(UpdateAssignedProductsJob.JOB_NAME)
  public Job job(
      @Qualifier(UpdateAssignedProductsJob.JOB_NAME + "_STEP_ONE") Step stepOne,
      JobRepository jobRepository,
      JobExecutionListener jobExecutionListener,
      @Qualifier("ArticleFlatFilePublisher") ArticleFlatFilePublisher articleFlatFilePublisher
  ) {
    return new JobBuilder(UpdateAssignedProductsJob.JOB_NAME, jobRepository)
        .incrementer(new RunIdIncrementer())
        .flow(stepOne)
        .end()
        .listener(jobExecutionListener)
        .listener(articleFlatFilePublisher)
        .build();
  }

  @Bean(UpdateAssignedProductsJob.JOB_NAME + "_STEP_ONE")
  public Step stepOne(
      @Qualifier("UpdateAssignedProductsJobPagedItemReader") UpdateAssignedProductsJobPagedItemReader itemReader,
      JobRepository jobRepository, PlatformTransactionManager transactionManager,
      @Qualifier("ProductItemProcessor") ProductItemProcessor itemProcessor,
      @Qualifier("ArticleFlatFileWriter") ArticleFlatFileWriter itemWriter
  ) {
     return new StepBuilder(UpdateAssignedProductsJob.JOB_NAME + "_STEP_ONE", jobRepository)
        .<Product, Article>chunk(DEFAULT_CHUNK_SIZE, transactionManager)
        .reader(itemReader)
        .processor(itemProcessor)
        .writer(itemWriter)
        .build();
  }
}

As you can see the StepBuilder is now using JobRepository jobRepository and PlatformTransactionManager transactionManager, which was not the case in 4.x.

On executing above job through a CommandLineRunner (a temporary attempt), i am facing below error -

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:774) [spring-boot-3.1.3.jar:3.1.3]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:755) [spring-boot-3.1.3.jar:3.1.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:319) [spring-boot-3.1.3.jar:3.1.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) [spring-boot-3.1.3.jar:3.1.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) [spring-boot-3.1.3.jar:3.1.3]
    at com.wayfair.retail.esl.data_manager_job.DataManagerJobApplication.main(DataManagerJobApplication.java:30) [main/:?]
Caused by: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT JOB_INSTANCE_ID, JOB_NAME
FROM BATCH_JOB_INSTANCE
WHERE JOB_NAME = ?
 and JOB_KEY = ?]
    at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:101) ~[spring-jdbc-6.0.11.jar:6.0.11]
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:70) ~[spring-jdbc-6.0.11.jar:6.0.11]

Clearly Spring Batch 5.0 is referring to it's internal tables, which I want to disable and avoid above exception. How can I achieve this.

I have gone through the migration doc, but this did not help.

Job repository/explorer configuration updates.
The Map-based job repository/explorer implementation were deprecated in v4 and completely removed in v5. You should use the Jdbc-based implementation instead. Unless you are using a custom Job repository/explorer implementation, the @EnableBatchProcessing annotation will configure a Jdbc-based JobRepository which requires a DataSource bean in the application context. The DataSource bean could refer to an embedded database like H2, HSQL, etc to work with an in-memory job repository.


Solution

  • Historically, Spring Batch provided a map-based job repository and job explorer implementations to work with an in-memory job repository. These implementations were deprecated in version 4 and completely removed in version 5. The recommended replacement is to use the JDBC-based implementations with an embedded database, such as H2, HSQL, and others.

    This is mentioned in the What's new in Spring Batch 5 section of the reference documentation. In your case, you need to provide an in-memory data source and use the JDBC job repository with it (which is the default if you use @EnableBatchProcessing), or provide a custom JobRepository implementation as mentioned in the migration guide.

    EDIT: Add example of initializing an embedded datasource with batch tables

    @Configuration
    @EnableBatchProcessing(dataSourceRef = "batchDataSource", transactionManagerRef = "batchTransactionManager")
    public static class MyJobConfiguration {
    
        // Infrastructure beans
    
        @Bean
        public DataSource batchDataSource() {
            return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.HSQL)
                .addScript("/org/springframework/batch/core/schema-hsqldb.sql")
                .generateUniqueName(true)
                .build();
        }
    
        @Bean
        public JdbcTransactionManager batchTransactionManager(DataSource dataSource) {
            return new JdbcTransactionManager(dataSource);
        }
    
        // "Business" beans
    
        // Add jobs, steps, etc here
    
    }