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 范围的更多详细信息