【问题标题】:Spring Batch - Pass parameter from Writer to Listener for afterJob(JobExecution jobExecution)Spring Batch - 将参数从 Writer 传递到 Listener 以进行 afterJob(JobExecution jobExecution)
【发布时间】:2018-11-09 18:55:26
【问题描述】:

我有一个编写器,我有一个动态值需要传递给 JobExecutionListener 的afterJob(JobExecution jobExecution)。将不胜感激一些建议。谢谢。

<beans:bean>
    <job id="GoodJob">
        <step id="XXX"
              allow-start-if-complete="true"
              parent="XXX">
            <tasklet transaction-manager="XXX">
                <chunk reader="READER"
                       writer="WRITER"
                       commit-interval="100"/>
            </tasklet>
        </step>

        <listener>
            <beans:bean class="class that implements JobExecutionListener">
                <beans:constructor-arg name="value"
                                       value="DEFAULT IS FALSE DURING INITIALIZATION/MIGHT GET CHANGED IN WRITER, GET THIS VALUE FROM WRITER"/>
            </beans:bean>
        </listener>
    </job>
</beans:beans>

【问题讨论】:

  • 请参阅here 以从编写器访问执行上下文以放置值。然后在afterJob()jobExecution参数中从执行上下文中获取值。

标签: java spring spring-batch


【解决方案1】:

您可以通过作业执行上下文在这两个组件之间传递数据。这在Passing Data to Future Steps 部分中有详细说明。这是一个简单的例子:

import java.util.Arrays;
import java.util.List;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.annotation.BeforeStep;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableBatchProcessing
public class MyJob {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    @Bean
    public ItemReader<Integer> itemReader() {
        return new ListItemReader<>(Arrays.asList(1, 2, 3, 4));
    }

    @Bean
    public ItemWriter<Integer> itemWriter() {
        return new ItemWriter<Integer>() {

            private StepExecution stepExecution;

            @Override
            public void write(List<? extends Integer> items) throws Exception {
                for (Integer item : items) {
                    System.out.println("item = " + item);
                }
                stepExecution.getJobExecution().getExecutionContext().put("data", "foo");
            }

            @BeforeStep
            public void saveStepExecution(StepExecution stepExecution) {
                this.stepExecution = stepExecution;
            }

        };
    }

    @Bean
    public Step step() {
        return steps.get("step")
                .<Integer, Integer>chunk(2)
                .reader(itemReader())
                .writer(itemWriter())
                .build();
    }

    @Bean
    public Job job() {
        return jobs.get("job")
                .start(step())
                .listener(new JobExecutionListener() {
                    @Override
                    public void beforeJob(JobExecution jobExecution) {

                    }

                    @Override
                    public void afterJob(JobExecution jobExecution) {
                        ExecutionContext executionContext = jobExecution.getExecutionContext();
                        String data = executionContext.getString("data");
                        System.out.println("data from writer = " + data);
                    }
                })
                .build();
    }

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyJob.class);
        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        Job job = context.getBean(Job.class);
        jobLauncher.run(job, new JobParameters());
    }

}

在此示例中,编写器在作业执行上下文中写入键 data 和值 foo。然后,从作业侦听器的执行上下文中检索此键。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    我将为 Mahmoud 所说的内容添加新信息。 现在您必须添加一个额外的步骤 - 如果您想在 JobListener 中获取数据,则将 ExecutionContext 从 Step 提升到 Job 上下文。

    @Bean
    public ExecutionContextPromotionListener promotionListener() {
        ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
        listener.setKeys(new String[] {"data"});
        return listener;
    }
    

    比在你的步骤中注册它。

    @Bean
    public Step step() {
        return steps.get("step")
                .<Integer, Integer>chunk(2)
                .reader(itemReader())
                .writer(itemWriter())
                .listener(promotionListener())
                .build();
    }
    

    【讨论】:

      猜你喜欢
      • 2014-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-20
      • 2016-01-14
      • 1970-01-01
      • 1970-01-01
      • 2019-09-27
      相关资源
      最近更新 更多