@FnsactionalEventListener方法未被触发

时间:2016-08-31 23:51:28

标签: spring-boot spring-transactions

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

@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注释。

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

问题是我们的一个生产箱上没有触发监听器。它在本地开发环境中运行良好,但在生产中始终如一。

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

注意:我已检查过现有的类似帖子。我的方案与任何现有帖子都不匹配。

1 个答案:

答案 0 :(得分:0)

我能想到的唯一事情来自Spring's javadoc

  

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

可能没有正在运行的交易吗?我假设您的代码示例不完整,因此可能在事件被触发时回滚事务或者沿着这些事情回滚。

在任何情况下,您都可以尝试使用以下内容(我知道您指的是一个生产框,所以我不确定您在尝试时有什么选择):

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