Spring Boot从2.7.x迁移到3.1.6时Spring Batch日志警告求助
迁移后出现的INFO日志
[16-12-2023 08:18:04.248] [] [] INFO
[o.s.b.c.c.annotation.BatchRegistrar] Finished Spring Batch
infrastructure beans configuration in 7 ms.
[16-12-2023 08:18:08.626] [] [] INFO [o.s.b.c.r.s.JobRepositoryFactoryBean] No database type set, using
meta data indicating: MYSQL
[16-12-2023 08:18:08.698] [] [] INFO [o.s.b.c.c.a.BatchObservabilityBeanPostProcessor] No Micrometer
observation registry found, defaulting to ObservationRegistry.NOOP
[16-12-2023 08:18:08.708] [] [] INFO [o.s.b.c.c.a.BatchObservabilityBeanPostProcessor] No Micrometer
observation registry found, defaulting to ObservationRegistry.NOOP
[16-12-2023 08:18:08.712] [] [] INFO [o.s.b.c.l.support.SimpleJobLauncher] No TaskExecutor has been set,
defaulting to synchronous executor.
相关代码片段
数据源配置类
@Configuration public class DataSourceBean { @Value("${db.datasource.driver-class-name}") private String driverName; @Value("${db.datasource.url}") private String url; @Value("${db.datasource.username}") private String userName; @Value("${db.datasource.password}") private String password; @Bean(name="dataSource") public DataSource dbDatasource() { return DataSourceBuilder.create() .driverClassName(driverName) .url(url) .username(userName) .password(password) .build(); } @Primary @Bean(name = "primaryEntityManagerFactory") public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(EntityManagerFactoryBuilder builder) { Map<String, Object> properties = new HashMap<String, Object>(); properties.put("hibernate.hbm2ddl.auto", "update"); return builder .dataSource(dbDatasource()) .packages("com.gigi.apm.card") .persistenceUnit("default") .properties(properties) .build(); } }
Batch配置类
@Configuration @EnableBatchProcessing @EntityScan(basePackages = {"com.gigi.apm.card"}) @EnableJpaRepositories(entityManagerFactoryRef = "primaryEntityManagerFactory",transactionManagerRef = "batchTransactionManager", basePackages="com.gigi.apm.card.batch.repository") public class ApmBatchConfig { @Value("${db.batch.batch-size}") private int batchSize; @Autowired @Qualifier("dataSource") public DataSource dataSource; @Autowired private ApmTransactionRepository repository; @Bean @StepScope public Tasklet deleteApmTransactionTasklet() { return new DeleteApmTransactionTasklet(repository,batchSize); } @Bean(name = "transactionManager") @Primary public JpaTransactionManager batchTransactionManager(@Qualifier("primaryEntityManagerFactory") EntityManagerFactory primaryEntityManagerFactory) { return new JpaTransactionManager(primaryEntityManagerFactory); } @Bean public Job deleteCompletedTransaction(Step deleteStep,JobRepository jobRepository) { return new JobBuilder("deleteCompletedTransaction",jobRepository) .incrementer(new RunIdIncrementer()) .start(deleteStep) .build(); } @Bean("step1") public Step deleteTransaction(Tasklet deleteApmTransactionTasklet, PlatformTransactionManager transactionManager,JobRepository jobRepository) { return new StepBuilder("deleteTransaction", jobRepository) .allowStartIfComplete(Boolean.TRUE) .tasklet(deleteApmTransactionTasklet, transactionManager) .build(); } }
Tasklet实现类
public class DeleteApmTransactionTasklet implements Tasklet { private static final Logger LOGGER = LoggerFactory.getLogger(DeleteApmTransactionTasklet.class); private static final int THREAD_DELAY = 1000; private static final String TRANSACTION_STATUS="DONE"; private int batchSize; private final ApmTransactionRepository repository; public DeleteApmTransactionTasklet(ApmTransactionRepository repository,int batchSize) { this.repository= repository; this.batchSize=batchSize; } @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { try { LOGGER.info("Delete action is started."); long count = repository.getCountByStatus(TRANSACTION_STATUS); LOGGER.info("Number of transactions to be deleted {}", count); while (count > 0) { repository.deleteTrnInBatch(TRANSACTION_STATUS, batchSize); Thread.sleep(1000); count = count - batchSize; } LOGGER.info("Completed transactions are deleted successfully"); } catch (DataAccessException exception) { LOGGER.error("Transactions are not deleted successfully because of error {}", exception); return RepeatStatus.CONTINUABLE; } return RepeatStatus.FINISHED; } }
Repository与启动类
@Repository public interface ApmTransactionRepository extends JpaRepository<ApmTransaction, String> { } @SpringBootApplication public class ApmBatchApplication { public static void main(String[] args) { System.exit(SpringApplication.exit(SpringApplication.run(DecoupledBatchApplication.class, args))); } }
日志提示的处理建议
这些INFO级日志本身不是错误,但可根据需求优化配置:
No database type set, using meta data indicating: MYSQL
Spring Batch已自动检测数据库类型,若需显式指定,可在配置JobRepository时添加数据库类型设置:@Bean public JobRepository jobRepository(@Qualifier("primaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) throws Exception { JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(dataSource); factory.setTransactionManager(batchTransactionManager(entityManagerFactory)); factory.setDatabaseType(DatabaseType.MYSQL.name()); return factory.getObject(); }No Micrometer observation registry found, defaulting to ObservationRegistry.NOOP
若要启用Spring Batch的可观测能力,添加Micrometer相关依赖(以Maven为例):<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>添加后Spring会自动配置ObservationRegistry,该日志提示会消失。
No TaskExecutor has been set, defaulting to synchronous executor
当前JobLauncher使用同步执行器,若需异步执行Job,可配置异步TaskExecutor:@Bean public SimpleJobLauncher jobLauncher(JobRepository jobRepository) throws Exception { SimpleJobLauncher launcher = new SimpleJobLauncher(); launcher.setJobRepository(jobRepository); launcher.setTaskExecutor(new SimpleAsyncTaskExecutor()); return launcher; }
内容的提问来源于stack exchange,提问作者cyrille gate

