@TransactionalEventListener method not fired

落花浮王杯 提交于 2021-01-29 03:43:12

问题


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;
}

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.


回答1:


The only thing I can think of comes from Spring's javadoc:

If the event is not published within the boundaries of a managed transaction, the event is discarded unless the fallbackExecution() flag is explicitly set. If a transaction is running, the event is processed according to its 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)


来源:https://stackoverflow.com/questions/39260714/transactionaleventlistener-method-not-fired

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!