добавили @Tansactional, но отката все еще не происходит при явном генерировании проверенного исключения - PullRequest
0 голосов
/ 05 февраля 2020
@Transactional(value="txManager", rollbackFor = DriverReassignmentException.class)
    public UserLoadAssocResponse<List<AssociateResponse>, UserLoadAssocResponseStatus> reassignAssignedLoad(String user, String scac, String adminId, DriverLoadAssocDetails driverLoadAssocDetails) throws DriverReassignmentException{

        UserLoadAssocResponse<Boolean, UserLoadAssocResponseStatus> removeUserResponse =null;

        UserLoadAssocResponse<List<AssociateResponse>, UserLoadAssocResponseStatus> userLoadAssignedResponse=null;

        if(!(StringUtils.isEmpty(driverLoadAssocDetails.getOrderNumber()) && StringUtils.isEmpty(user) && StringUtils.isEmpty(scac) && StringUtils.isEmpty(adminId))){
            try {
                removeUserResponse = this.userLoadAssociationClient.removeUserFromAssignedLoad(user, scac, driverLoadAssocDetails.getOrderNumber(),adminId, Constant.INTRANSIT);
            } catch (Exception e) {
                removeUserResponse = UserLoadAssocResponse.failure(UserLoadAssocResponseStatus.UNEXPECTED_ERROR);
                log.error("Unable to remove user {} from load {} scac: {} adminUser: {} admin", user, driverLoadAssocDetails.getOrderNumber(), scac, adminId, e);
            }
        } else{
            log.error("Insufficient data present to remove user {} from load {} scac: {} adminUser: {} admin", user, driverLoadAssocDetails.getOrderNumber()!=null?driverLoadAssocDetails.getOrderNumber():null, scac, adminId);
            return UserLoadAssocResponse.failure(UserLoadAssocResponseStatus.UNEXPECTED_ERROR);

        }

        if(removeUserResponse.isSuccess() && removeUserResponse.getStatus().toString().equalsIgnoreCase(UserLoadAssocResponseStatus.SUCCESS.toString())){
            try {
                userLoadAssignedResponse = this.associateSingleUserSingleLoad(scac, adminId, driverLoadAssocDetails);
            }catch(Exception ex){
                log.error("Unexpected error occured while assigning single load for carrierCode {} - {}", scac, ex);
                throw new DriverReassignmentException(UserLoadAssocResponseStatus.UNEXPECTED_ERROR.name());
            }
        }else{
            return UserLoadAssocResponse.failure(removeUserResponse.getStatus());
        }

        if(userLoadAssignedResponse.isSuccess() && userLoadAssignedResponse.getStatus().toString().equalsIgnoreCase(UserLoadAssocResponseStatus.SUCCESS.toString())){
            log.info("Load reassigned succesfully:{}", userLoadAssignedResponse);
            return userLoadAssignedResponse;
        }else{
            log.error("Error occured while assigning single load for carrierCode {}", scac);
            throw new DriverReassignmentException("Load reassigned Unsuccesfull");

        }

    }
// expecting to rollback this.userLoadAssociationClient.removeUserFromAssignedLoad(user, scac, driverLoadAssocDetails.getOrderNumber(),adminId, Constant.INTRANSIT) 

при throw new DriverReassignmentException("Load reassigned Unsuccesfull"). Но не быть тюком для достижения

Ответы [ 2 ]

0 голосов
/ 05 февраля 2020

Я попросил уточнить, как вы вызываете метод, потому что одной простой ошибкой в ​​настройке на основе Spring (Boot) является недопонимание того, как работает @Transactional.

В частности, учитывая настройки по умолчанию, аннотация @Transactional работает только тогда, когда экземпляр класса с вызываемым аннотированным методом был создан через Spring и вызван через Spring, а не напрямую из другого метода в том же классе.

Обычно это означает, что у вас есть экземпляр

@Autowired
CoolClass classInstance;

, а затем вы go с

classInstance.transactionalMethod

, где этот метод представляет собой аннотацию с @ Transactional

@Transactional
public void transactionalMethod(...){

Если вместо этого вы позвоните

classInstance.someOtherMethod()

, где

public void someOtherMethod(){
  this.transactionalMethod(...);
}

, это не сработает.

Аналогично, если вы создадите свой класс вручную, например, так:

CoolClass classInstance=new CoolClass(..);

if также не будет работать.

Это из-за того, что Spring в настройках по умолчанию поддерживает @Transactional. Это поведение можно изменить, переключив диспетчер транзакций в режим ткачества AspectJ (см. Здесь https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html).

В итоге, чтобы аннотация @Transactional работала правильно с режимом прокси по умолчанию :

  1. метод должен быть опубликован c
  2. вызов должен поступать извне (управляемого пружиной) компонента

(И это мои дорогие друзья, почему аннотация SpringTransactional - милая маленькая ловушка-ловушка - выглядит красиво, невинно и круто, но может серьезно сжечь вас, молча подведя вас.)

0 голосов
/ 05 февраля 2020

Возможная реальная ошибка

Удалите оператор возврата в следующей строке:

return UserLoadAssocResponse.failure

Я думаю, что вы возвращаетесь из метода без оценки условия if, которое вызовет правильное исключение.

Дополнительная отладка

В вашей логике есть ошибка c. Лучший способ действительно отладить, работает ли ваша транзакционная аннотация, - добавить следующую строку в качестве последней строки вашего метода НО без оператора if

throw new DriverReassignmentException("Load reassigned Unsuccessful");

Тогда вы будете быть в состоянии оценить, происходит ли откат, потому что вы будете знать, что для каждого запроса выдается конкретное c исключение.

Затем закомментируйте throws, и вы должны заметить, что ваши данные сохраняется, и исключений не бывает.

Проблема в условиях if statement. Вам нужно отладить логи c и понять, почему ваш if statement не имеет значения true.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...