MultipleResourceItemReader 中的资源不能为 null
Resources must not be null in MultipleResourceItemReader
我正在开发一个 spring 批处理作业,首先从 S3Bucket 下载文件并将其放在我的本地(使用 Tasklet),然后使用 MultiResourceItemReader 从我的本地读取文件并将其填充到工作中 table.
我是先调用Tasklet,然后下一步读取文件。所以,我们有可用的输入文件。
但是,当我尝试 运行 该过程时,我猜是因为 bean 配置依赖性,它抛出了以下错误:资源不能为空。
我不知道该如何处理。一旦 tasklet 运行 完成,就会有可用的文件,但在此之前不会。
错误:
**Caused by: java.lang.IllegalArgumentException: The resources must not be null**
at org.springframework.util.Assert.notNull(Assert.java:201) ~[spring-core-5.3.3.jar:5.3.3]
at org.springframework.batch.item.file.MultiResourceItemReader.setResources(MultiResourceItemReader.java:246) ~[spring-batch-infrastructure-4.3.1.jar:4.3.1]
at com.cspprovemerald.SpringBatchApplication.ItemReader.FileItemReader.providerMultiResourceItemReader(FileItemReader.java:38) ~[classes/:na]
at com.cspprovemerald.SpringBatchApplication.Config.JobStepBuilderConfig.step2(JobStepBuilderConfig.java:64) ~[classes/:na]
at com.cspprovemerald.SpringBatchApplication.Config.JobStepBuilderConfig.job(JobStepBuilderConfig.java:110) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.3.jar:5.3.3]
... 38 common frames omitted
多资源项目读取器:
@Component
public class FileItemReader {
@Value("${local.file.download.path}")
private String localFileDownloadPath;
private static final Logger LOGGER = LoggerFactory.getLogger(FileItemReader.class);
// MultiResourceItemReader to read multiple files sequentially
public MultiResourceItemReader<Provider> providerMultiResourceItemReader() {
String locationPattern = "C:/Users/Desktop/data/in/*.csv";
Resource[] resources = null;
ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
try {
resources = patternResolver.getResources(locationPattern);
} catch (IOException e) {
e.printStackTrace();
}
MultiResourceItemReader<Provider> multiResourceItemReader = new MultiResourceItemReader<>();
multiResourceItemReader.setResources(resources);
multiResourceItemReader.setDelegate(providerItemReader());
return multiResourceItemReader;
}
}
JobBuilderConfig.java
@Component
@EnableBatchProcessing
public class JobStepBuilderConfig {
@Autowired
JobBuilderFactory jobBuilderFactory;
@Autowired
StepBuilderFactory stepBuilderFactory;
@Autowired
DataSource datasource;
@Autowired
JdbcItemWriter jdbcItemWriter;
@Autowired
JdbcItemReader jdbcItemReader;
@Autowired
FileItemReader fileItemReader;
@Autowired
FileItemWriter fileItemWriter;
@Autowired
TaskletSPExecutor taskletSPExecutor;
@Autowired
TaskletS3DownloadFiles taskletS3DownloadFiles;
public Step step1(){
// step 1 : Read records from custom table and call stored procedure to update facets table
return stepBuilderFactory.get("step1S3ListCopyFiles")
.tasklet(taskletS3DownloadFiles)
.build();
}
public Step step2(){
// step 2 : Read csv files and dump it into a custom table
return stepBuilderFactory.get("step2ReadLoadCSV")
.<Provider, Provider>chunk(1000)
.reader(fileItemReader.providerMultiResourceItemReader())
.writer(jdbcItemWriter.providerJdbcBatchItemWriter())
.build();
}
@Bean
public Job job(){
return jobBuilderFactory.get("jobCSProvMI4275")
.start(step1())
.next(step2())
.incrementer(new RunIdIncrementer())
.build();
}
}
这是因为 reader 项是在创建 Spring 应用程序上下文时急切创建的。此时,文件尚未下载,因此出现错误。 Spring Batch 提供了一个名为 Step
范围的自定义 bean 范围。此范围允许您定义应仅在需要时在运行时创建的 bean。
在您的情况下,您需要使您的项目 reader 具有步进范围。这意味着 item reader bean 只会在面向块的步骤需要它时创建(即在 tasklet 下载文件之后)。这是一个例子:
@Bean
@StepScope
public MultiResourceItemReader<Provider> providerMultiResourceItemReader() {
// configure your reader here
}
您可以在 documentation here.
中找到有关 Step
范围的更多详细信息
我正在开发一个 spring 批处理作业,首先从 S3Bucket 下载文件并将其放在我的本地(使用 Tasklet),然后使用 MultiResourceItemReader 从我的本地读取文件并将其填充到工作中 table.
我是先调用Tasklet,然后下一步读取文件。所以,我们有可用的输入文件。
但是,当我尝试 运行 该过程时,我猜是因为 bean 配置依赖性,它抛出了以下错误:资源不能为空。
我不知道该如何处理。一旦 tasklet 运行 完成,就会有可用的文件,但在此之前不会。
错误:
**Caused by: java.lang.IllegalArgumentException: The resources must not be null**
at org.springframework.util.Assert.notNull(Assert.java:201) ~[spring-core-5.3.3.jar:5.3.3]
at org.springframework.batch.item.file.MultiResourceItemReader.setResources(MultiResourceItemReader.java:246) ~[spring-batch-infrastructure-4.3.1.jar:4.3.1]
at com.cspprovemerald.SpringBatchApplication.ItemReader.FileItemReader.providerMultiResourceItemReader(FileItemReader.java:38) ~[classes/:na]
at com.cspprovemerald.SpringBatchApplication.Config.JobStepBuilderConfig.step2(JobStepBuilderConfig.java:64) ~[classes/:na]
at com.cspprovemerald.SpringBatchApplication.Config.JobStepBuilderConfig.job(JobStepBuilderConfig.java:110) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.3.jar:5.3.3]
... 38 common frames omitted
多资源项目读取器:
@Component
public class FileItemReader {
@Value("${local.file.download.path}")
private String localFileDownloadPath;
private static final Logger LOGGER = LoggerFactory.getLogger(FileItemReader.class);
// MultiResourceItemReader to read multiple files sequentially
public MultiResourceItemReader<Provider> providerMultiResourceItemReader() {
String locationPattern = "C:/Users/Desktop/data/in/*.csv";
Resource[] resources = null;
ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
try {
resources = patternResolver.getResources(locationPattern);
} catch (IOException e) {
e.printStackTrace();
}
MultiResourceItemReader<Provider> multiResourceItemReader = new MultiResourceItemReader<>();
multiResourceItemReader.setResources(resources);
multiResourceItemReader.setDelegate(providerItemReader());
return multiResourceItemReader;
}
}
JobBuilderConfig.java
@Component
@EnableBatchProcessing
public class JobStepBuilderConfig {
@Autowired
JobBuilderFactory jobBuilderFactory;
@Autowired
StepBuilderFactory stepBuilderFactory;
@Autowired
DataSource datasource;
@Autowired
JdbcItemWriter jdbcItemWriter;
@Autowired
JdbcItemReader jdbcItemReader;
@Autowired
FileItemReader fileItemReader;
@Autowired
FileItemWriter fileItemWriter;
@Autowired
TaskletSPExecutor taskletSPExecutor;
@Autowired
TaskletS3DownloadFiles taskletS3DownloadFiles;
public Step step1(){
// step 1 : Read records from custom table and call stored procedure to update facets table
return stepBuilderFactory.get("step1S3ListCopyFiles")
.tasklet(taskletS3DownloadFiles)
.build();
}
public Step step2(){
// step 2 : Read csv files and dump it into a custom table
return stepBuilderFactory.get("step2ReadLoadCSV")
.<Provider, Provider>chunk(1000)
.reader(fileItemReader.providerMultiResourceItemReader())
.writer(jdbcItemWriter.providerJdbcBatchItemWriter())
.build();
}
@Bean
public Job job(){
return jobBuilderFactory.get("jobCSProvMI4275")
.start(step1())
.next(step2())
.incrementer(new RunIdIncrementer())
.build();
}
}
这是因为 reader 项是在创建 Spring 应用程序上下文时急切创建的。此时,文件尚未下载,因此出现错误。 Spring Batch 提供了一个名为 Step
范围的自定义 bean 范围。此范围允许您定义应仅在需要时在运行时创建的 bean。
在您的情况下,您需要使您的项目 reader 具有步进范围。这意味着 item reader bean 只会在面向块的步骤需要它时创建(即在 tasklet 下载文件之后)。这是一个例子:
@Bean
@StepScope
public MultiResourceItemReader<Provider> providerMultiResourceItemReader() {
// configure your reader here
}
您可以在 documentation here.
中找到有关Step
范围的更多详细信息