我正在将 Spring Boot 从版本 2.6.6 升级到 3.1.3。
我通过参考this sof帖子进行了所需的JobRepository相关修改。
一切似乎都很顺利,但随后我面临以下错误 -
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 1 of method stepOne in com.mycompany.retail.esl.data_manager_job.product_publisher_job.ProductPublisherJob required a bean named 'dataSource' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Qualifier("PRODUCT_PUBLISHER_JOB_STEP_ONE")
Action:
Consider defining a bean named 'dataSource' in your configuration.
我的步骤生成器和作业生成器代码如下 -
@Configuration
@EnableBatchProcessing
@RequiredArgsConstructor
public class ProductPublisherJob {
private static final int DEFAULT_CHUNK_SIZE = 25;
public static final String JOB_NAME = JobName.PRODUCT_PUBLISHER_JOB;
@Bean(ProductPublisherJob.JOB_NAME)
public Job job(
@Qualifier(ProductPublisherJob.JOB_NAME + "_STEP_ONE") Step stepOne,
JobRepository jobRepository,
JobExecutionListener jobExecutionListener,
@Qualifier("ArticleFlatFilePublisher") ArticleFlatFilePublisher articleFlatFilePublisher
) {
return new JobBuilder(ProductPublisherJob.JOB_NAME, jobRepository)
.incrementer(new RunIdIncrementer())
.flow(stepOne)
.end()
.listener(jobExecutionListener)
.listener(articleFlatFilePublisher)
.build();
}
@Bean(ProductPublisherJob.JOB_NAME + "_STEP_ONE")
public Step stepOne(
@Qualifier("ProductPublisherJobPageReader") ProductPublisherJobPageReader pageReader,
JobRepository jobRepository,
@Qualifier("ProductItemProcessor") ProductItemProcessor itemProcessor,
@Qualifier("ArticleFlatFileWriter") ArticleFlatFileWriter itemWriter
) {
return new StepBuilder(ProductPublisherJob.JOB_NAME + "_ONE", jobRepository)
.<Product, Article>chunk(DEFAULT_CHUNK_SIZE)
.reader(pageReader)
.processor(itemProcessor)
.writer(itemWriter)
.build();
}
}
我确实在 application.properties 中定义了所需的数据源属性,而且它在 Spring Boot 2.6.6 中运行良好。
对于如何解决这个问题,有任何的建议吗。任何帮助将不胜感激,因为这对我来说是一个阻碍。
编辑 1 - 重新分级所需的数据源 bean
我在 application.properties 中有以下内容
spring.batch.datasource.driver-class-name = org.h2.Driver
spring.batch.datasource.password = sa
spring.batch.datasource.url = jdbc:h2:mem:db;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;
spring.batch.datasource.username = sa
在 build.gradle 中我有 -
implementation "com.h2database:h2:2.2.224"
implementation "org.springframework.boot:spring-boot-starter-batch"
implementation "org.springframework.boot:spring-boot-starter-data-jpa"
我还需要做些什么才能将数据源 Bean 放入应用程序上下文吗?
编辑 2 - 显式添加数据源 bean。
我明确地将以下 bean 定义添加到配置类中。
@Bean
public DataSource dataSource() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(
dataSourceBuilder.driverClassName("org.h2.Driver");
dataSourceBuilder.url("jdbc:h2:mem:test");
dataSourceBuilder.username("SA");
dataSourceBuilder.password("");
return dataSourceBuilder.build();
}
它建议:
考虑在您的应用程序中定义一个名为“transactionManager”的 bean 配置。
所以我添加了-
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
但现在它给出了另一个仍然与 transactionManager 相关的错误 -
org.springframework.beans.factory.UnsatisfiedDependencyException: 创建类中定义的名称为“Product_PUBLISHER_JOB”的 bean 时出错 路径资源 [com/wayfair/retail/esl/data_manager_job/product_publisher_job/ProductPublisherJob.class]: 通过方法“job”参数 0 表示不满足的依赖关系: 创建定义了名称“Product_PUBLISHER_JOB_STEP_ONE”的 bean 时出错 在类路径资源中 [com/wayfair/retail/esl/data_manager_job/product_publisher_job/ProductPublisherJob.class]: 无法实例化[org.springframework.batch.core.Step]:工厂 方法“stepOne”抛出异常并显示消息: java.lang.IllegalStateException:事务管理器必须是 提供
我明确提供了事务管理器,但为什么它还是抱怨。
编辑 3 - 根据 Gurkan 的要求编写条目代码。
@Component("ArticleFlatFileWriter")
public class ArticleFlatFileWriter extends FlatFileItemWriter<Article> {
private final ArticleMapper articleMapper;
ArticleFlatFileWriter(
@Value("${app.storage.localFile}") String file,
@Value("${app.storage.file.csv.header}") Boolean includeHeader,
@Qualifier("ArticleLineAggregator") ArticleLineAggregator lineAggregator,
ArticleMapper articleMapper
) {
super();
if (Boolean.TRUE.equals(includeHeader)) {
this.setHeaderCallback(this::headerCallback);
}
var fileSystemResource = new FileSystemResource(file);
this.setAppendAllowed(true);
this.setEncoding("UTF-8");
this.setLineAggregator(lineAggregator);
this.setResource(fileSystemResource);
this.setShouldDeleteIfExists(true);
this.articleMapper = articleMapper;
}
private void headerCallback(Writer writer) throws IOException {
writer.write(String.join(ArticleLineTokenizer.DEFAULT_DELIMITER, this.articleMapper.getHeaderNames()));
}
protected boolean isAppendAllowed() {
return this.append;
}
}
编辑4- 将 StepBuilder 代码更新到下面后(也像 Skillup 所建议的那样),事务管理器问题得到解决,但我面临
Error creating bean with name 'jpaMappingContext': JPA metamodel must not be empty
。 我为此发布了一个新问题。
@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();
}
您应该像这样替换步骤的代码:
@Bean(ProductPublisherJob.JOB_NAME + "_STEP_ONE")
public Step stepOne( JobRepository jobRepository,PlatformTransactionManager transactionManager,
@Qualifier("ProductPublisherJobPageReader") ProductPublisherJobPageReader pageReader,
@Qualifier("ProductItemProcessor") ProductItemProcessor itemProcessor,
@Qualifier("ArticleFlatFileWriter") ArticleFlatFileWriter itemWriter
) {
return new StepBuilder(ProductPublisherJob.JOB_NAME + "_ONE", jobRepository)
.<Product, Article>chunk(DEFAULT_CHUNK_SIZE, transactionManager)
.reader(pageReader)
.processor(itemProcessor)
.writer(itemWriter)
.build();
}