本記事の対象読者
- SpringBatch 5を新しく学習する人
- 下記書籍の学習途中でつまずいた人
悲惨なミスをなくすSpringBatch入門書: Spring解体新書(バッチ編): 基礎から学べるSpring Batch
初めに
筆者は下記書籍をもとにSpring Batchの学習を進めていましたが、情報が古く、最新のSpring Batch 5(以下V5)には対応していませんでした。V5でこの書籍の学習を進めるうえで、抑えておくべきV4とV5の相違点を共有したいと思います。また新しくV5を学習する人の手助けになれば幸いです。
悲惨なミスをなくすSpringBatch入門書: Spring解体新書(バッチ編): 基礎から学べるSpring Batch
JobBuilderFactoryとStepBuildFactoryの非推奨
JobBuilderFactoryとStepBuildFactoryは非推奨になっており、V5の構成で動作させるとエラーが発生します。
試しに期待動作として「HelloWorld」とログ出力するプログラムを実行してみると
@Configuration
@EnableBatchProcessing
public class BatchConfig {
/** JobBuilderのFactoryクラス */
@Autowired
private JobBuilderFactory jobBuilderFactory;
/** StepBuilderのFactoryクラス */
@Autowired
private StepBuilderFactory stepBuilderFactory;
/** Helloworldをログ出力するTasklet */
@Autowired
private Tasklet helloTasklet;
/** TaskletのStepを生成 */
@Bean
Step taskletStep1() {
return stepBuilderFactory.get("HelloTaskletStep1") // Builderの取得
.tasklet(helloTasklet) // Taskletのセット
.build(); // Stepの生成
}
/** Jobを生成 */
@Bean
Job taskletJob() throws Exception {
return jobBuilderFactory.get("HelloWorldTaskletJob") // Builderの取得
.incrementer(new RunIdIncrementer()) // IDのインクリメント
.start(taskletStep1()) // 最初のStep
.build(); // Jobの生成
}
}
[2m2024-11-19T11:17:06.238+09:00[0;39m [32m INFO[0;39m [35m4056[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mc.e.d.BatchHelloWorldTaskletApplication [0;39m [2m:[0;39m Starting BatchHelloWorldTaskletApplication using Java 21.0.4 with PID 4056 (C:\Users\yuma_nakajima\git\springbatch-study-ny\BatchHelloWorldTasklet\bin\main started by yuma_nakajima in C:\Users\yuma_nakajima\git\springbatch-study-ny\BatchHelloWorldTasklet)
[2m2024-11-19T11:17:06.240+09:00[0;39m [32m INFO[0;39m [35m4056[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mc.e.d.BatchHelloWorldTaskletApplication [0;39m [2m:[0;39m No active profile set, falling back to 1 default profile: "default"
[2m2024-11-19T11:17:06.299+09:00[0;39m [32m INFO[0;39m [35m4056[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36m.e.DevToolsPropertyDefaultsPostProcessor[0;39m [2m:[0;39m Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
[2m2024-11-19T11:17:06.761+09:00[0;39m [32m INFO[0;39m [35m4056[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.c.c.annotation.BatchRegistrar [0;39m [2m:[0;39m Finished Spring Batch infrastructure beans configuration in 6 ms.
[2m2024-11-19T11:17:06.904+09:00[0;39m [32m INFO[0;39m [35m4056[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36m.s.d.r.c.RepositoryConfigurationDelegate[0;39m [2m:[0;39m Bootstrapping Spring Data JDBC repositories in DEFAULT mode.
[2m2024-11-19T11:17:06.925+09:00[0;39m [32m INFO[0;39m [35m4056[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36m.s.d.r.c.RepositoryConfigurationDelegate[0;39m [2m:[0;39m Finished Spring Data repository scanning in 16 ms. Found 0 JDBC repository interfaces.
[2m2024-11-19T11:17:07.173+09:00[0;39m [33m WARN[0;39m [35m4056[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'jobRegistry' of type [org.springframework.batch.core.configuration.support.MapJobRegistry] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:17:07.208+09:00[0;39m [33m WARN[0;39m [35m4056[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36ms.c.a.AnnotationConfigApplicationContext[0;39m [2m:[0;39m Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'batchConfig': Unsatisfied dependency expressed through field 'jobBuilderFactory': No qualifying bean of type 'org.springframework.batch.core.configuration.annotation.JobBuilderFactory' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
[2m2024-11-19T11:17:07.215+09:00[0;39m [32m INFO[0;39m [35m4056[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36m.s.b.a.l.ConditionEvaluationReportLogger[0;39m [2m:[0;39m
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
[2m2024-11-19T11:17:07.249+09:00[0;39m [31mERROR[0;39m [35m4056[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.d.LoggingFailureAnalysisReporter [0;39m [2m:[0;39m
***************************
APPLICATION FAILED TO START
***************************
Description:
Field jobBuilderFactory in com.example.demo.config.BatchConfig required a bean of type 'org.springframework.batch.core.configuration.annotation.JobBuilderFactory' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'org.springframework.batch.core.configuration.annotation.JobBuilderFactory' in your configuration.
もうBeanとしてクラスが管理されていないため、エラーになっています。
次に公式リファレンス通りにJobBuilderとStepBuilderに置き換えて動作させてみます。
@Configuration
@EnableBatchProcessing
public class BatchConfig {
/** HelloTasklet */
@Autowired
private Tasklet helloTasklet;
/** TaskletのStepを生成 */
@Bean
Step taskletStep1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("HelloTaskletStep1", jobRepository) // Builderの生成
.tasklet(helloTasklet, transactionManager) // Taskletのセット
.build(); // Stepの生成
}
/** Jobを生成 */
@Bean
Job taskletJob(JobRepository jobRepository, PlatformTransactionManager transactionManager)
throws Exception {
return new JobBuilder("HelloWorldTaskletJob", jobRepository) // Builderの生成
.incrementer(new RunIdIncrementer()) // IDのインクリメント
.start(taskletStep1(jobRepository, transactionManager)) // 最初のStep
.build(); // Jobの生成
}
}
[2m2024-11-19T11:14:20.944+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mc.e.d.BatchHelloWorldTaskletApplication [0;39m [2m:[0;39m Starting BatchHelloWorldTaskletApplication using Java 21.0.4 with PID 23772 (C:\Users\yuma_nakajima\git\springbatch-study-ny\BatchHelloWorldTasklet\bin\main started by yuma_nakajima in C:\Users\yuma_nakajima\git\springbatch-study-ny\BatchHelloWorldTasklet)
[2m2024-11-19T11:14:20.946+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mc.e.d.BatchHelloWorldTaskletApplication [0;39m [2m:[0;39m No active profile set, falling back to 1 default profile: "default"
[2m2024-11-19T11:14:21.002+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36m.e.DevToolsPropertyDefaultsPostProcessor[0;39m [2m:[0;39m Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
[2m2024-11-19T11:14:21.495+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.c.c.annotation.BatchRegistrar [0;39m [2m:[0;39m Finished Spring Batch infrastructure beans configuration in 8 ms.
[2m2024-11-19T11:14:21.646+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36m.s.d.r.c.RepositoryConfigurationDelegate[0;39m [2m:[0;39m Bootstrapping Spring Data JDBC repositories in DEFAULT mode.
[2m2024-11-19T11:14:21.667+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36m.s.d.r.c.RepositoryConfigurationDelegate[0;39m [2m:[0;39m Finished Spring Data repository scanning in 16 ms. Found 0 JDBC repository interfaces.
[2m2024-11-19T11:14:21.922+09:00[0;39m [33m WARN[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'jobRegistry' of type [org.springframework.batch.core.configuration.support.MapJobRegistry] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:14:22.061+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mcom.zaxxer.hikari.HikariDataSource [0;39m [2m:[0;39m HikariPool-1 - Starting...
[2m2024-11-19T11:14:22.277+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mcom.zaxxer.hikari.pool.HikariPool [0;39m [2m:[0;39m HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:9ed8c693-8658-4f29-bd33-366d2f500bba user=SA
[2m2024-11-19T11:14:22.279+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mcom.zaxxer.hikari.HikariDataSource [0;39m [2m:[0;39m HikariPool-1 - Start completed.
[2m2024-11-19T11:14:22.291+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.c.r.s.JobRepositoryFactoryBean [0;39m [2m:[0;39m No database type set, using meta data indicating: H2
[2m2024-11-19T11:14:22.342+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36m.c.a.BatchObservabilityBeanPostProcessor[0;39m [2m:[0;39m No Micrometer observation registry found, defaulting to ObservationRegistry.NOOP
[2m2024-11-19T11:14:22.353+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36m.c.a.BatchObservabilityBeanPostProcessor[0;39m [2m:[0;39m No Micrometer observation registry found, defaulting to ObservationRegistry.NOOP
[2m2024-11-19T11:14:22.356+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.c.l.support.SimpleJobLauncher [0;39m [2m:[0;39m No TaskExecutor has been set, defaulting to synchronous executor.
[2m2024-11-19T11:14:22.624+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.d.a.OptionalLiveReloadServer [0;39m [2m:[0;39m LiveReload server is running on port 35729
[2m2024-11-19T11:14:22.660+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mc.e.d.BatchHelloWorldTaskletApplication [0;39m [2m:[0;39m Started BatchHelloWorldTaskletApplication in 2.187 seconds (process running for 2.957)
[2m2024-11-19T11:14:22.675+09:00[0;39m [33m WARN[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ionShutdownHook][0;39m [2m[0;39m[36mo.s.b.f.support.DisposableBeanAdapter [0;39m [2m:[0;39m Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLNonTransientConnectionException: データベースはすでに閉じられています (VM終了時の自動データベースクローズを無効にするためには、db URLに ";DB_CLOSE_ON_EXIT=FALSE" を追加してください)
Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-224]
[2m2024-11-19T11:14:22.677+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ionShutdownHook][0;39m [2m[0;39m[36mcom.zaxxer.hikari.HikariDataSource [0;39m [2m:[0;39m HikariPool-1 - Shutdown initiated...
[2m2024-11-19T11:14:22.680+09:00[0;39m [32m INFO[0;39m [35m23772[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ionShutdownHook][0;39m [2m[0;39m[36mcom.zaxxer.hikari.HikariDataSource [0;39m [2m:[0;39m HikariPool-1 - Shutdown completed.
しかし、公式通りの単純な置き換えを行っても期待動作はせずにプログラムは終了しています。気になるログとしては下記が挙げられます。
Bean 'jobRegistry' of type [org.springframework.batch.core.configuration.support.MapJobRegistry] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
jobRegistryの設定が上手くいっていないようです。
ここで下記公式の「Updated code for Batch 5 and Boot 3」のコードを確認してみると、
https://github.com/spring-guides/gs-batch-processing/commit/ed2604bfa5b8140e0b98e0c1bd8f307e85ce2979#diff-c61a8fde67d30987ddfc8ee91fa6d180fb0f22d631a7205068bfaa7e74ac36c3L28
EnableBatchProcessingアノテーションが外されています。よって@EnableBatchProcessingを外して実行してみると
[2m2024-11-19T11:33:01.574+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mc.e.d.BatchHelloWorldTaskletApplication [0;39m [2m:[0;39m Starting BatchHelloWorldTaskletApplication using Java 21.0.4 with PID 16972 (C:\Users\yuma_nakajima\git\springbatch-study-ny\BatchHelloWorldTasklet\bin\main started by yuma_nakajima in C:\Users\yuma_nakajima\git\springbatch-study-ny\BatchHelloWorldTasklet)
[2m2024-11-19T11:33:01.576+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mc.e.d.BatchHelloWorldTaskletApplication [0;39m [2m:[0;39m No active profile set, falling back to 1 default profile: "default"
[2m2024-11-19T11:33:01.631+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36m.e.DevToolsPropertyDefaultsPostProcessor[0;39m [2m:[0;39m Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
[2m2024-11-19T11:33:02.256+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36m.s.d.r.c.RepositoryConfigurationDelegate[0;39m [2m:[0;39m Bootstrapping Spring Data JDBC repositories in DEFAULT mode.
[2m2024-11-19T11:33:02.278+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36m.s.d.r.c.RepositoryConfigurationDelegate[0;39m [2m:[0;39m Finished Spring Data repository scanning in 16 ms. Found 0 JDBC repository interfaces.
[2m2024-11-19T11:33:02.504+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:33:02.553+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:33:02.554+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$PooledDataSourceConfiguration' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$PooledDataSourceConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:33:02.555+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'jdbcConnectionDetails' of type [org.springframework.boot.autoconfigure.jdbc.PropertiesJdbcConnectionDetails] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:33:02.572+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'dataSource' of type [com.zaxxer.hikari.HikariDataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:33:02.577+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration$JdbcTransactionManagerConfiguration' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration$JdbcTransactionManagerConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:33:02.582+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizationAutoConfiguration' of type [org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizationAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:33:02.588+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'transactionExecutionListeners' of type [org.springframework.boot.autoconfigure.transaction.ExecutionListenersTransactionManagerCustomizer] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:33:02.591+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'spring.transaction-org.springframework.boot.autoconfigure.transaction.TransactionProperties' of type [org.springframework.boot.autoconfigure.transaction.TransactionProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:33:02.592+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'platformTransactionManagerCustomizers' of type [org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:33:02.599+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'transactionManager' of type [org.springframework.jdbc.support.JdbcTransactionManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:33:02.600+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'spring.batch-org.springframework.boot.autoconfigure.batch.BatchProperties' of type [org.springframework.boot.autoconfigure.batch.BatchProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.
[2m2024-11-19T11:33:02.608+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration$SpringBootBatchConfiguration' of type [org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration$SpringBootBatchConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). The currently created BeanPostProcessor [jobRegistryBeanPostProcessor] is declared through a non-static factory method on that class; consider declaring it as static instead.
[2m2024-11-19T11:33:02.664+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mcom.zaxxer.hikari.HikariDataSource [0;39m [2m:[0;39m HikariPool-1 - Starting...
[2m2024-11-19T11:33:02.900+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mcom.zaxxer.hikari.pool.HikariPool [0;39m [2m:[0;39m HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:0a91ccd8-cada-4c70-8ec0-59cc16ebfcfe user=SA
[2m2024-11-19T11:33:02.902+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mcom.zaxxer.hikari.HikariDataSource [0;39m [2m:[0;39m HikariPool-1 - Start completed.
[2m2024-11-19T11:33:03.328+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.d.a.OptionalLiveReloadServer [0;39m [2m:[0;39m LiveReload server is running on port 35729
[2m2024-11-19T11:33:03.364+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mc.e.d.BatchHelloWorldTaskletApplication [0;39m [2m:[0;39m Started BatchHelloWorldTaskletApplication in 2.218 seconds (process running for 3.0)
[2m2024-11-19T11:33:03.367+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.a.b.JobLauncherApplicationRunner [0;39m [2m:[0;39m Running default command line with: []
[2m2024-11-19T11:33:03.415+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.c.l.support.SimpleJobLauncher [0;39m [2m:[0;39m Job: [SimpleJob: [name=HelloWorldTaskletJob]] launched with the following parameters: [{'run.id':'{value=1, type=class java.lang.Long, identifying=true}'}]
[2m2024-11-19T11:33:03.446+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mo.s.batch.core.job.SimpleStepHandler [0;39m [2m:[0;39m Executing step: [HelloTaskletStep1]
[2m2024-11-19T11:33:03.457+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mcom.example.demo.tasklet.HelloTasklet [0;39m [2m:[0;39m Hello World
[2m2024-11-19T11:33:03.460+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mo.s.batch.core.step.AbstractStep [0;39m [2m:[0;39m Step: [HelloTaskletStep1] executed in 14ms
[2m2024-11-19T11:33:03.467+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.c.l.support.SimpleJobLauncher [0;39m [2m:[0;39m Job: [SimpleJob: [name=HelloWorldTaskletJob]] completed with the following parameters: [{'run.id':'{value=1, type=class java.lang.Long, identifying=true}'}] and the following status: [COMPLETED] in 34ms
[2m2024-11-19T11:33:03.482+09:00[0;39m [33m WARN[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ionShutdownHook][0;39m [2m[0;39m[36mo.s.b.f.support.DisposableBeanAdapter [0;39m [2m:[0;39m Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLNonTransientConnectionException: データベースはすでに閉じられています (VM終了時の自動データベースクローズを無効にするためには、db URLに ";DB_CLOSE_ON_EXIT=FALSE" を追加してください)
Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-224]
[2m2024-11-19T11:33:03.485+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ionShutdownHook][0;39m [2m[0;39m[36mcom.zaxxer.hikari.HikariDataSource [0;39m [2m:[0;39m HikariPool-1 - Shutdown initiated...
[2m2024-11-19T11:33:03.487+09:00[0;39m [32m INFO[0;39m [35m16972[0;39m [2m---[0;39m [2m[BatchHelloWorldTasklet] [ionShutdownHook][0;39m [2m[0;39m[36mcom.zaxxer.hikari.HikariDataSource [0;39m [2m:[0;39m HikariPool-1 - Shutdown completed.
Stepが実行され、期待動作通り「Hello World」がログに出力されています。
@EnableBatchProcessingが悪さをしていたようです。
確かに下記「Spring Boot 3.0 Migration Guide」によると@EnableBatchProcessingは非推奨となっています。
バッチの実行状況を管理するメタテーブルを初期化していた@EnableBatchProcessingですが、V5からはそれが自動的に構成されるようになり、余計に@EnableBatchProcessingをつけると挙動が変化するようです。詳しくは下記記事が参考になります。
動作環境
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.5'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-batch'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.batch:spring-batch-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
番外
Spring解体新書(バッチ編)の書籍では、application.ymlでプロパティを設定していますが、プロパティ名が誤っています。正しくは下記の通りです。これはapplication.propertiesの場合でも同様です。
spring:
batch:
job:
- names:
+ name:
最後に
SpringBatch 5に関して、あまり情報が落ちていないので調査には苦労しました。
公式リファレンスで矛盾している内容があるので困りものですね。
実際、私は@EnableBatchProcessingの非推奨に関してギブアップしてしまい、上司のFさんに助けを求めたところ、解決していただきました。Fさんありがとうございました!
今後も業務を通して、SpringBatch 5の有益な情報が見つかったら共有しようと思います。
最後までお読みいただきありがとうございました。