How can we take the result of `MethodInvokingTaskletAdapter` as a reader in the Spring Batch Step?

人走茶凉 提交于 2021-01-25 07:21:11

问题


How can we take the result of MethodInvokingTaskletAdapter as a reader in the Spring Batch Step? Reference - https://docs.spring.io/spring-batch/docs/current/reference/html/index-single.html#taskletStep and https://github.com/spring-projects/spring-batch/pull/567

Here is the code that I developed

JobConfiguration.java

@Configuration
public class JobConfiguration {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    
    @Bean
    public CustomService service() {
        return new CustomService();
    }
    
    @StepScope
    @Bean
    public MethodInvokingTaskletAdapter methodInvokingTasklet() {
        MethodInvokingTaskletAdapter methodInvokingTaskletAdapter = new MethodInvokingTaskletAdapter();
        methodInvokingTaskletAdapter.setTargetObject(service());
        methodInvokingTaskletAdapter.setTargetMethod("getEmployees");
        return methodInvokingTaskletAdapter;
    }
    
    @Bean
    public Job methodInvokingJob() {
        return this.jobBuilderFactory.get("methodInvokingJob")
                .start(methodInvokingStep())
                .build();
    }

    @Bean
    public Step methodInvokingStep() {
        // Looking to configure the Chunk based Step here, dont know how to do using MethodInvokingTaskletAdapter
        return this.stepBuilderFactory.get("methodInvokingStep")
                .tasklet(methodInvokingTasklet())
                .build();
    }
}

CustomService.java

public class CustomService {
    public void serviceMethod(String message) {
        System.out.println(message);
    }
    
    public void invokeMethod() {
        System.out.println("=============== Your method has executed !");
    }
    
    public List<Employee> getEmployees(){
        // In real world, it will be an GET API call to XYZ system
        List<Employee> employees = new ArrayList<>();
        employees.add(Employee.builder().firstName("Ravi").lastName("Shankar").email("ravi.shankar@gmail.com").age(30).build());
        employees.add(Employee.builder().firstName("Parag").lastName("Rane").email("parag.rane@gmail.com").age(11).build());
        employees.add(Employee.builder().firstName("Priya").lastName("Pande").email("priya.pande@gmail.com").age(40).build());
        employees.add(Employee.builder().firstName("Kiran").lastName("khot").email("kiran.khot@gmail.com").age(50).build());
        return employees;
    }
}

Employee.java

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Employee {
    private String firstName;
    private String lastName;
    private String email;
    private int age;
}

MethodInvokingTaskletApplication.java

@EnableBatchProcessing
@SpringBootApplication
public class MethodInvokingTaskletApplication {

    public static void main(String[] args) {
        SpringApplication.run(MethodInvokingTaskletApplication.class, args);
    }
}

回答1:


To answer your question, you can't. The MethodInvokingTaskletAdapter is meant to adapt a POJO to a Tasklet. We have an ItemReaderAdapter that you can use to adapt a POJO to an ItemReader. You can read about it in the documentation here: https://docs.spring.io/spring-batch/docs/current/api/org/springframework/batch/item/adapter/ItemReaderAdapter.html

Now you'll have an issue with your service as configured in that each call to the delegating POJO is considered an item. That means that your item as configured will be a List<Employee> instead of just an Employee. Given your configuration states it's not the real service, I'll assume that your real service should return an Employee per call and null once the results are exhausted.

To update your configuration (with your service as it is configured in your question) in your sample:

...
    @StepScope
    @Bean
    public ItemReaderAdapter itemReader() {
        ItemReaderAdapter reader = new ItemReaderAdapter();
        reader.setTargetObject(service());
        reader.setTargetMethod("getEmployees");
        return reader;
    }
    
    @Bean
    public Job methodInvokingJob() {
        return this.jobBuilderFactory.get("methodInvokingJob")
                .start(methodInvokingStep())
                .build();
    }

    @Bean
    public Step methodInvokingStep() {
        return this.stepBuilderFactory.get("methodInvokingStep")
                .<List<Employee>, List<Employee>>chunk(methodInvokingTasklet())
                .reader(itemReader())
                // You'll need to define a writer...
                .writer(itemWriter())
                .build();
    }
    ...



来源:https://stackoverflow.com/questions/65507138/how-can-we-take-the-result-of-methodinvokingtaskletadapter-as-a-reader-in-the

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!