当前位置: 首页 > 知识库问答 >
问题:

Spring Batch:CompositeItemWriter、@BeforeStep和控制步骤执行

百里君博
2023-03-14

我最近偶然发现了一个非常扭曲的Spring批次问题。要求如下:

我有两个主要步骤:

  • 第一个从oracle数据库中读取一些数据,从一个表中写入另一个表
  • 第二个基于第一步处理的数据,完成其他一些数据库工作

从设计的角度来看,第一步如下所示:

    @Bean
    public Step myFirstStep(JdbcCursorItemReader<Revision> reader) {

        return stepBuilderFactory.get("my-first-step")
            .<Revision, Revision>chunk(1)
            .reader(readerRevisionNumber)
            .writer(compositeItemWriter())
            .listener(executionContextPromotionListener())
            .build();

复合项目编写器:

    @Bean
    public CompositeItemWriter<Revision> compositeItemWriter() {
        CompositeItemWriter writer = new CompositeItemWriter();
        writer.setDelegates(Arrays.asList(somewriter(), someOtherwriter(), aWriterThatIsSupposedToPassDataToAnotherStep()));
        return writer;
    }

虽然前两位作者并不复杂,但我的兴趣集中在第三位。

aWriterThatIsSupposedToPassDataToAnotherStep()

正如您可能已经猜到的,这一个将用于获取之前正在处理的一些数据,以便在我的第二步中进行升级:

@Component
@StepScope
public class AWriterThatIsSupposedToPassDataToAnotherStep implements ItemWriter<SomeEntity> {

    private StepExecution stepExecution;

    public void write(List<? extends SomeEntity> items) {

        ExecutionContext stepContext = this.stepExecution.getExecutionContext();
        stepContext.put("revisionNumber", items.stream().findFirst().get().getSomeField());
        System.out.println("writing : " + items.stream().findFirst().get().getSomeField()+ "to ExecutionContext");
    }

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

}

问题是:只要这个writer是复合writer列表(如上所述)的一部分,我上一个writer的@BeforeStep就永远不会执行,这最终导致我无法将信息传输到执行上下文。在步骤定义中,用我的单个“awriterthatissedtopassdatatoatotherstep”替换CompositeItemWriter时,它会得到正确的执行。

它是否与某种申报单或其他东西有关?

非常感谢进一步的帮助。

共有1个答案

尉迟哲瀚
2023-03-14

找到了解决方案(在我的一些同事的帮助下),并来源:https://stackoverflow.com/a/39698653/1957764

您需要将编写器声明为复合编写器的一部分,并声明一个步骤侦听器,以使其执行@BeforeStep注释方法。

 类似资料:
  • 根据spring batch中的某些条件,是否可以执行一个步骤或跳过它并继续下一步。例如,批处理作业中有5个步骤,在执行每个步骤之前,我们需要根据数据库中某个列的值检查是否跳过它。需求是通过监听器或其他方式创建通用逻辑,以控制运行时的步骤执行? 我需要在运行时填充下一个属性。示例xml: 但它引发了异常:配置问题:元素[step2]无法访问| 我认为spring不允许在运行时绑定下一个属性。请给出

  • 我想在每个步骤之前和之后执行一些操作(而不是场景)。用cucumber怎么做? 就像jUnit中的后和前。 **我正在使用java。

  • 我正在做一个Spring批处理工作,它包含几个步骤(超过10个)。 谢谢你的回答。

  • 我正在尝试修复Spring Batch中的一个问题,这个问题最近一直困扰着我们的系统。我们有一份工作,在大多数情况下都很好。下载和处理数据是一个多步骤的工作。 问题是有时工作会爆棚。也许我们试图连接到的服务器抛出了错误,或者我们在工作进行到一半时关闭了服务器。此时,下次我们的quartz调度程序尝试运行该作业时,它似乎什么也不做。以下是此作业定义的删节版本: 委婉地说,我是Spring Batch

  • 我目前正在尝试创建我的第一个cucumber测试。在Java Eclipse中,我创建了一个包含以下内容的“功能文件”: 我还创建了以下testrunner文件: 我还创建了我的步骤定义: 公共类LoginStepDefinitions{ } 当我将脚本作为Junit测试运行时,控制台会成功执行测试并显示结果: 但是当打开JUnit选项卡时,会发生两件事: 1)测试步骤似乎没有显示: 2)当我双击

  • 脚本是一个命令一个命令顺序执行的。 Selenese 本身不支持条件语句(if - else, 等)或循环迭代(for, while, 等)。没有流程控制也可以制作很多有用的测试案例。然而,对于动态内容的功能测试,可能涉及到多个页面,编程逻辑通常是必要的。 如果必须使用流程控制,有以下三种解决方案: 使用 Selenium RC 运行脚本结合客户端库,如:Java 或 PHP 库,利用编程语言的流