本文介绍了@TransactionalEventListener 方法未触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个代码,其中事件发布在用 Spring @Transactional 注释注释的方法中.

I have a code where event is published in a method annotated with Spring @Transactional annotation.

@Override
@Transactional
public Task updateStatus(Integer taskId, ExecutionStatus newStatus) {
    Task task = Task.builder().executionStatus(newStatus).build();
    return updateStatusInternal(taskId, rteWithMetadata);
}

private TaskExecution updateStatusInternal(Integer taskId,
        Task newStatus) {
    Task task = taskService.findById(taskId);
    TaskExecution te = task.getFirstExecution();

    TaskExecution.ExecutionStatus oldStatus = te.getExecutionStatus();

    TaskExecution.ExecutionStatus newStatus = newStatus.getExecutionStatus();
    log.info(
            "Task Execution status changed. Task id={}, from={}, to={}. Manual override : {}",
            task.getId(), oldStatus, newStatus,
            newStatus.isManualOverrideInitiated());

    te.setExecutionStatus(newStatus);

    if (te.getExecutionStatus() == ExecutionStatus.COMPLETED
            || te.getExecutionStatus() == ExecutionStatus.FAILED) {
        te.setEndDate(DateTimeHelper.getUtcNow());
        if (rte.isManualOverrideInitiated()) {
            rte.setManualOverrideEndDate(DateTimeHelper.getUtcNow());
        }
    }

    publisher.publishEvent(TaskStatusChanged.of(task, oldStatus, newStatus));
    log.info("Published TaskStatusChanged event. task Id={}", task.getId());

    // Send STOMP message
    final Object payload = StompMessageHelper.getTaskExecutionUpdateMessage(task);
    messageTemplate.convertAndSend(taskDestination(task), payload);
    log.info("STOMP message for task status update sent. task Id={}",
            task.getId());

    return te;
}

应用事件有对应的监听方法,用@TransactionalEventListener注解.

There is a corresponding listener method for the application event which is annotated with @TransactionalEventListener.

@Async("changeEventExecutor")
@TransactionalEventListener(phase=TransactionPhase.AFTER_COMMIT)
public void taskStatusChanged(final TaskStatusChanged e) {
    log.info("taskStatusChanged called");
}

问题是我们的其中一个生产设备上没有触发侦听器.它在本地开发环境中始终运行良好,但在生产环境中始终失败.

Problem is listener is not fired on one of our production boxes. It works fine consistently on local dev environment but fails consistently in production.

有人之前遇到过这个问题吗?我能想到的唯一解决方案是手动触发应用程序事件.

Did somebody face this issue earlier? Only solution I can think of is to manually fire the application event.

注意:我已经检查了现有的类似帖子.我的场景与任何现有帖子都不匹配.

Note: I have checked the existing similar posting. My scenario does not match with any of the existing posting.

推荐答案

我唯一能想到的来自Spring 的 javadoc:

如果事件未在托管的范围内发布事务,事件被丢弃,除非 fallbackExecution()标志是明确设置的.如果事务正在运行,则事件为根据其 TransactionPhase 进行处理.

会不会没有事务在运行?我假设您的代码示例不完整,所以当事件被触发或类似的事情发生时,事务可能正在回滚.

Could there be no transaction running? I assume your code sample isn't complete, so perhaps the transaction is being rolled-back when the event is fired or something along those lines.

在任何情况下,您都可以尝试以下操作(我知道您指的是生产盒,所以我不确定您在尝试时有哪些选择):

In any case, you could try with the following (I know you are referring to a production box, so I'm not sure what are your options in trying things out):

@TransactionalEventListener(fallbackExecution=true, phase=TransactionPhase.AFTER_COMMIT)

这篇关于@TransactionalEventListener 方法未触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 06:54