发出从SkipListener检索ExecutionContext的问题

时间:2017-05-15 19:10:04

标签: spring-batch

我正在尝试从ExecutionContext检索弹出批处理SkipListener

这是我尝试过的(我依靠注释而不是接口来实现我的听众):

import com.xxxx.domain.UserAccount;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.annotation.BeforeStep;
import org.springframework.batch.core.annotation.OnSkipInWrite;
import org.springframework.mail.MailSendException;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class MailSkipListener {

    private StepExecution stepExecution;

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

    @OnSkipInWrite
    public void logSkippedEmail(UserAccount userAccount, Throwable t) {
        if (t instanceof MailSendException) {
            MailSendException e = (MailSendException) t;
            log.warn("FailedMessages: " + e.getFailedMessages());
        }
    }
}

但是,引发logSkippedEmail时,永远不会执行MailSendException方法。当我删除saveStepExecution方法时,logSkippedEmail会再次执行MailSendException

我注册我的MailSkipListener如下:

@Bean
public Step messagesDigestMailingStep(EntityManagerFactory entityManagerFactory) {
    return stepBuilderFactory
            .get("messagesDigestMailingStep")
            .<UserAccount, UserAccount>chunk(5)

            ...

            .writer(itemWriter)
            .listener(mailSkipListener)//Here
            .build();
}

我在这里尝试实现的是从ExecutionContext中检索SkipListener。怎么能实现这一目标?似乎没有办法自动装配ExecutionContext

3 个答案:

答案 0 :(得分:0)

您可以在MailSkipListener上实施StepExecutionListener,以便在stepExecution方法中保存beforeStep()内容:

public class MailSkipListener implements StepExecutionListener {

    @Override
    public void beforeStep(StepExecution stepExecution) {
         this.stepExecution = stepExecution;
    }

答案 1 :(得分:0)

这是一个很老的问题,但我也只是在努力解决这个问题。 我最后两次注册skiplistener以使其工作,一次作为StepExecutionListener而另一次作为SkipListener。 它很糟糕,但似乎有效:

{{1}}

答案 2 :(得分:0)

我知道这是一个老问题,但我不得不自己处理这个问题,并整理了以下实现,其中我让 SkipListener 也实现了 StepExecutionListener,并添加了与 SkipListener 和 StepExecutionListener 相同的类。

@Component
public class PersonImportListener implements SkipListener<Person, Person>, StepExecutionListener {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
    private StepExecution stepExecution;
    @Override
    public void beforeStep(StepExecution stepExecution) {
        this.stepExecution = stepExecution;
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        return ExitStatus.COMPLETED;
    }

    @Override
    public void onSkipInRead(Throwable throwable) {
        logger.warn("Line skipped on read", throwable);
    }

    @Override
    public void onSkipInWrite(Person person, Throwable throwable) {
        logger.warn("Bean skipped on write", throwable);
        logger.warn("Execution Context" + stepExecution);
    }

    @Override
    public void onSkipInProcess(Person person, Throwable throwable) {
        logger.warn("Bean skipped on process", throwable);
    }
}

并将此类用作 StepExecutionListener 和 SkipListener 的侦听器。

@Bean
public Step step1(JdbcBatchItemWriter<Person> writer) {
    PersonImportListener listener = new PersonImportListener();
    return stepBuilderFactory.get("step1")
            .<Person, Person> chunk(10)
            .reader(reader())
            .faultTolerant()
            .skipLimit(10)
            .skip(DataIntegrityViolationException.class)
            .listener((StepExecutionListener) listener)
            .listener((SkipListener) listener)
            .processor(processor())
            .writer(writer)
            .build();
}