【问题标题】:Spring Boot + Spring Batch + @StepScope = No Proxied Beans?Spring Boot + Spring Batch + @StepScope = 没有代理 Bean?
【发布时间】:2016-04-17 02:36:58
【问题描述】:

我目前正在为应用程序设置文件导入服务,该服务将允许用户通过 REST 上传 csv 文件。作业的导入将通过 Spring Batch 完成,因为这些作业可能会长时间运行,具体取决于未来的处理要求和检查。

根据我的说法,以下设置对于 Spring Boot 和 Spring Batch 是正确的,但代码不会编译。

主 BatchConfiguration 文件:

@Configuration
@EnableBatchProcessing
public class PatientBatchConfiguration {

    @Autowired
    private JobBuilderFactory jobBuilders;

    @Autowired
    private StepBuilderFactory stepBuilders;

    @Autowired
    private PatientFieldSetMapper fieldSetMapper;

    @Autowired
    private PatientItemWriter writer;

    @Bean
    public Job importPatientsFromUpload(){
        return jobBuilders.get("importPatientsFromUpload")
                .start(step())
                .build();
    }

    @Bean
    public Step step(){
        return stepBuilders.get("step")
                .<Patient,Patient>chunk(1)
                .reader(reader(null))
                .writer(writer)
                .build();
    }

    @Bean
    @StepScope
    public ItemReader<Patient> reader(@Value("#{jobParameters['fileName']}") String filePath) {
        FlatFileItemReader<Patient> itemReader = new FlatFileItemReader<Patient>();
        itemReader.setLineMapper(lineMapper());
        itemReader.setResource(new FileSystemResource(filePath));
        return itemReader;
    }

    private LineMapper<Patient> lineMapper() {
        DefaultLineMapper<Patient> lineMapper = new DefaultLineMapper<Patient>();
        DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
        lineTokenizer.setNames(new String[]{"name","surname","idNumber","dob", "email", "cell"});
        lineMapper.setLineTokenizer(lineTokenizer);
        lineMapper.setFieldSetMapper(fieldSetMapper);
        return lineMapper;
    }

}

FieldSetMapper 代码:

@Component
public class PatientFieldSetMapper implements FieldSetMapper<Patient> {

    @Override
    public Patient mapFieldSet(FieldSet fieldSet) throws BindException {

        if(fieldSet == null){
            return null;
        }

        Patient patient = new Patient();
        patient.setName(fieldSet.readString("name"));
        patient.setSurname(fieldSet.readString("surname"));
        patient.setIdNo(fieldSet.readString("idNumber"));
        patient.setDob(0L);
        patient.setEmail(fieldSet.readString("email"));
        patient.setCell(fieldSet.readString("cell"));

        return patient;
    }
}

PatientItemWriter 代码:

@Component
public class PatientItemWriter implements ItemWriter<Patient> {

    @Autowired
    PatientRepository patientRepository;

    @Override
    public void write(List<? extends Patient> list) throws Exception {

        for(Patient patient: list) {
            patientRepository.save(patient);
        }
    }
}

堆栈跟踪:

Caused by: java.lang.IllegalArgumentException: Path must not be null
    at org.springframework.util.Assert.notNull(Assert.java:115) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.core.io.FileSystemResource.<init>(FileSystemResource.java:75) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at com.example.batch.patient.PatientBatchConfiguration.reader(PatientBatchConfiguration.java:59) ~[classes/:na]
    at com.example.batch.patient.PatientBatchConfiguration.step(PatientBatchConfiguration.java:49) ~[classes/:na]

最后是 application.properties 文件

spring.batch.job.enabled=false

spring.batch.job.enabled=false 位于属性文件中的原因是,在用户上传文件后,将从控制器调用作业 importPatientsFromUpload,如果没有它,作业将在启动时运行。

我遇到的问题是 FileSystemResource 无法创建,因为路径不能为空。但是我知道,只要使用@StepScope 注释一个方法,就会创建一个代理 bean,这将允许我使用在运行时传递的 jobParameter 来创建一个新的文件系统资源。我在网上看到了各种以这种方式使用 jobParameters 的示例,但由于某种原因,bean 似乎没有正确创建。我不确定这是否与我使用 Spring Boot 或其他错误有关。

任何帮助将不胜感激。提前致谢。

回复 Gaël 的更新

PatientItemReader 代码:

@Component
@StepScope
public class PatientItemReader implements ItemReader<Patient> {

    @Autowired
    private PatientFieldSetMapper fieldSetMapper;

    private FlatFileItemReader<Patient> itemReader;

    @Override
    public Patient read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        return itemReader.read();
    }

    public PatientItemReader(@Value("#{jobParameters[filePath]}") String filePath) {
            itemReader = new FlatFileItemReader<Patient>();
            DefaultLineMapper<Patient> lineMapper = new DefaultLineMapper<Patient>();
            DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
            lineTokenizer.setNames(new String[]{"name","surname","idNumber","dob", "email", "cell"});
            lineMapper.setLineTokenizer(lineTokenizer);
            lineMapper.setFieldSetMapper(fieldSetMapper);
            itemReader.setLineMapper(lineMapper);
            itemReader.setResource(new FileSystemResource(filePath));
    }
}

【问题讨论】:

  • 创建步骤时,您正在调用 .reader(reader(null)),并带有显式的 null 值。
  • 嗨 Gaël 是正确的,阅读器方法需要一个字符串变量,所以我必须传递一些东西,因此是空值。这应该不是问题,因为该变量应该是后期绑定到 Spring Batch 作业参数的,因此当代理 bean 被调用时,null 将被覆盖,或者不? reader(string) 方法只应在我调用批处理作业时执行,但编译不成功。我关注了 Tobias Flohre 的这篇博文 blog.codecentric.de/en/2013/06/…。有什么建议吗?

标签: java spring javabeans spring-batch


【解决方案1】:

我猜问题是您在 Spring 之外创建阅读器并在执行此操作时将 null 值传递给它:

@Bean
public Step step(){
    ...
    .reader(reader(null))
    ...
}

您应该这样做以使用诸如后期绑定之类的 Spring 功能:

@Autowired
private ItemReader<Patient> reader;

@Bean
public Step step(){
    ...
    .reader(reader)
    ...
}

就像你为你的作家所做的那样。

【讨论】:

  • 您好 Gaël,我编辑发布以提供我测试过的代码。该错误随后成为 Spring 无法自动装配所需依赖项的问题,不知道为什么?
【解决方案2】:

当您使用@Bean 时,这意味着您希望 Spring 容器来管理您的实例。所以,在这一步:

@Bean
public Step step() {...}

当你想获取一个 reader 实例来构建 step 的实例时,你不能像 reader(null) 这样使用。您应该将 reader 设置为 step 的参数,然后 Spring 容器将注入 reader 实例。这是正确的代码:

@Bean
public Step step(ItemReader<Patient> reader){
    return stepBuilders.get("step")
            .<Patient,Patient>chunk(1)
            .reader(reader)
            .writer(writer)
            .build();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-25
    • 2022-10-13
    • 2020-09-21
    • 2017-02-16
    • 2020-01-31
    • 2018-07-10
    • 2019-01-19
    • 1970-01-01
    相关资源
    最近更新 更多