Charlie
Charlie

Reputation: 3374

Spring Data Rest - Transaction not rolled back when run-time exception occurs in @HandleBeforeSave?

I am using Spring Data REST with Spring Boot 1.5.16 and my project has following entities.

Atoll.class

@Data
@Entity
public class Atoll {

    @Id
    @GeneratedValue
    private long id;

    private String atollName;

}

ErrorLog.class

@Data
@Entity
public class ErrorLog {


    @Id
    @GeneratedValue
    private long id;

    private String errorMessage;

    public ErrorLog() {

    }

    public ErrorLog(String errorMessage) {
        this.errorMessage = errorMessage;
    }
}

I also have the following RepositoryEventHandler for Atoll class. For the purpose of the question I am just throwing an exception here.

@Component
@RepositoryEventHandler
public class AtollHandler {

    @HandleBeforeSave
    public void handleBeforeSave(Atoll atoll){

        if(true){
            throw new ResourceNotFoundException("A");
        }

    }
}

When I send a PATCH request occurs to atolls/1 a runtime exception is logged however the Atoll entity still gets updated. So what am I doing wrong?

I found some similar questions like this one but it does not have a proper explanation for why this occurs

Note: I also have a Rest Exception handler class which writes errorlogs to database. When I comment out the errorlog writing part of the code, then the atoll entity does not get updated when a runtime exception occurs

@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {

    @Autowired
    ErrorLogRepository errorLogRepository;

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<?> handleResourceNotFoundException(ResourceNotFoundException rnfe, HttpServletRequest request) {

        ErrorLog errorLog = new ErrorLog(rnfe.getMessage());
        errorLogRepository.save(new ErrorLog(rnfe.getMessage()));
        return new ResponseEntity<>(errorLog, null, HttpStatus.NOT_FOUND);
    }


}

Upvotes: 1

Views: 347

Answers (1)

Charlie
Charlie

Reputation: 3374

I finally figured this out. By default spring @Transactional only catches unchecked exceptions. Since ResourceNotFoundException is being thrown by the handler it is a checked exception and therefore the transaction is not rolled back. So @Transactional(rollbackFor = Exception.class) annotation needs to be added to the AtollHandler class.

Upvotes: 1

Related Questions