Spring @аннотация транзакций и обработка исключений


Рассмотрим следующий фрагмент кода. (Я использую Spring 3.1 и Hibernate 3.6)

@Override
@Transactional
public <T extends Termination> void progressToPendingStage(Class<T> entity,
        Long terminationId, String userName) throws Exception {

    Termination termination = findTerminationById(entity, terminationId);
    //TODO improvise such that email does not get sent if data is not saved
    if (termination.getStatus().equals(TerminationStatus.BEING_PREPARED.toString())) {
        termination.setStatus(TerminationStatus.PENDING.toString());
        termination.setSubmittedDate(new Date());
        termination.setSubmittedBy(userName);
        saveOrUpdateTermination(termination);
        //Send an email to SAS
        emailHelper.configureEmailAndSend(termination);
    }   

}
Модульные тесты для вышеуказанного метода показывают, что электронная почта будет отправлена независимо от того, вызывает ли saveOrUpdateTermination(завершение) исключение или нет. При дальнейшем тестировании и некоторых исследованиях я обнаружил, что это поведение является ожидаемым поведением. Это не то, чего хотят правила бизнеса. Письмо должно быть отправлено только в том случае, если запись о завершении была успешно сохранена. Любые предложения по поводу как заставить его вести себя желаемым образом? Один из способов, который я могу придумать, состоит в том, чтобы заставить вызывающий объект обрабатывать исключение, вызванное методом progressstopendingstage, и если исключение не было вызвано, отправить электронное письмо. Я на правильном пути или мы можем изменить поведение @Transaction?
1 2

1 ответ:

Я решил эту проблему, разработав вокруг этой проблемы. Отправка электронной почты никогда не должна была быть частью транзакции. Я создал объект, который выполнял задачи сохранения сообщений. Объект будет ловить исключение, вызванное при сохранении завершения, и если никаких исключений не было, я бы тогда инициировал отправку электронной почты. Можно также поместить это в аспект весны, который может быть выполнен после успешного возвращения после успешного сохранения.

Уроки не учатся: не включают в себя шаги, которые не относятся к методу, помеченному символом @ transaction. Если он включен в транзакцию, Spring будет молча обрабатывать исключение и не бросать исключение до тех пор, пока транзакция не будет завершена. Короче говоря, если метод снабжен аннотацией @Transaction, то каждая строка в этом методе будет выполняться, даже если строка в середине метода создает исключение.