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 ответ:
Я решил эту проблему, разработав вокруг этой проблемы. Отправка электронной почты никогда не должна была быть частью транзакции. Я создал объект, который выполнял задачи сохранения сообщений. Объект будет ловить исключение, вызванное при сохранении завершения, и если никаких исключений не было, я бы тогда инициировал отправку электронной почты. Можно также поместить это в аспект весны, который может быть выполнен после успешного возвращения после успешного сохранения.
Уроки не учатся: не включают в себя шаги, которые не относятся к методу, помеченному символом @ transaction. Если он включен в транзакцию, Spring будет молча обрабатывать исключение и не бросать исключение до тех пор, пока транзакция не будет завершена. Короче говоря, если метод снабжен аннотацией @Transaction, то каждая строка в этом методе будет выполняться, даже если строка в середине метода создает исключение.