弹出批次退出退出状态:实际作业完成前已完成?

时间:2017-05-17 08:40:07

标签: spring amazon-dynamodb spring-batch

在我的Spring Batch应用程序中,我编写了一个CustomItemWriter,它使用DynamoDBAsyncClient在内部将项目写入DynamoDB,此客户端返回Future对象。我有一个包含数百万条记录的输入文件。由于CustomItemWriter立即返回未来对象,我的批处理作业在5秒内退出,状态为COMPLETED,但实际上将所有项目写入数据库需要3-4分钟,我希望该批处理作业仅在所有项目写入DataBase后完成。我怎么能这样做?

工作定义如下

    <bean id="report" class="com.solution.model.Report" scope="prototype" />
        <batch:job id="job" restartable="true">
            <batch:step id="step1">
                <batch:tasklet>
                    <batch:chunk reader="cvsFileItemReader"  processor="filterReportProcessor" writer="customItemWriter"
                        commit-interval="20">
                    </batch:chunk>
                </batch:tasklet>
            </batch:step>
        </batch:job>
<bean id="customItemWriter" class="com.solution.writer.CustomeWriter"></bean>

CustomeItemWriter定义如下

public class CustomeWriter implements ItemWriter<Report>{
    public void write(List<? extends Report> item) throws Exception {
    List<Future<PutItemResult>> list = new LinkedList();
    AmazonDynamoDBAsyncClient client = new AmazonDynamoDBAsyncClient();
        for(Report report : item) {
            PutItemRequest req = new PutItemRequest();
            req.setTableName("MyTable");
            req.setReturnValue(ReturnValue.ALL_ODD);
            req.addItemEntry("customerId",new 
            AttributeValue(item.getCustomeId()));
            Future<PutItemResult> res = client.putItemAsync(req);
            list.add(res);
            }
    }

}

主类包含

JobExecution execution = jobLauncher.run(job, new JobParameters());
System.out.println("Exit Status : " + execution.getStatus());

因为在ItemWriter中它返回的未来对象它不会等待完成操作。并且从主要提交所有项目以进行写入批处理状态显示COMPLETED并且作业终止。 我希望只有在DynamoDB中执行实际写入后才能终止此作业。 我们可以有一些其他的步骤来等待这个或一些听众可用吗?

1 个答案:

答案 0 :(得分:1)

这是一种方法。由于ItemWriter::write不返回任何内容,因此您可以使用侦听器功能。

@Component
@JobScope
public class YourWriteListener implements ItemWriteListener<WhatEverYourTypeIs> {


  @Value("#{jobExecution.executionContext}")
  private ExecutionContext executionContext;


  @Override
  public void afterWrite(final List<? extends WhatEverYourTypeIs> paramList) {
     Future future = this.executionContext.readAndValidate("FutureKey", Future.class);
     //wait till the job is done using future object
  }

  @Override
  public void beforeWrite(final List<? extends WhatEverYourTypeIs> paramList) {

  }

  @Override
  public void onWriteError(final Exception paramException, final List<? extends WhatEverYourTypeIs> paramList) {

  }
}

在您的编写器类中,除了将未来对象添加到ExecutionContext之外,所有内容都保持不变。

public class YourItemWriter extends ItemWriter<WhatEverYourTypeIs> {

  @Value("#{jobExecution.executionContext}")
  private ExecutionContext executionContext;

  @Override
  protected void doWrite(final List<? extends WhatEverYourTypeIs> youritems) 

     //write to DynamoDb and get Future object
    executionContext.put("FutureKey", future);
    }

  }

}

您可以在配置中注册监听器。这是一个java代码,您需要在xml中执行相同的操作

@Bean
  public Step initStep() {

    return this.stepBuilders.get("someStepName").<YourTypeX, YourTypeY>chunk(10)
        .reader(yourReader).processor(yourProcessor)
        .writer(yourWriter).listener(YourWriteListener)
        .build();
  }