Reputation: 35
I'm using @RepositoryRestResource to create my REST API, that avoids having to manually write the code as in @RestController, and gives me a nice HATEOAS response. However now the validations I added to my entity don't work, or rather I get the 500 response code instead of 400.
I tried using @ControllerAdvice + @ExceptionHandler to capture the ConstraintViolationException, however it seems that it's being captured before and what's thrown is a TransactionSystemException.
Validating the data is something pretty basic, and yet for some reason after much googling I haven't found a solution.
edit: To show the code:
@ControllerAdvice
public class ConstraintViolationExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler({ ConstraintViolationException.class })
public ResponseEntity<Object> handleConstraintViolationException(
Exception ex, WebRequest request) {
return new ResponseEntity<Object>("test 123", HttpStatus.BAD_REQUEST);
}
}
I still get:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction] with root cause javax.validation.ConstraintViolationException
So it seems the ConstraintViolationException is being captured earlier by Spring Data REST and a TransactionSystemException is thrown. If I change the code to capture this exception like:
@ControllerAdvice
public class ConstraintViolationExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler({ TransactionSystemException .class })
public ResponseEntity<Object> handleConstraintViolationException(
Exception ex, WebRequest request) {
return new ResponseEntity<Object>("test 123", HttpStatus.BAD_REQUEST);
}
}
Then it works, but this is not the exception I should be capturing.
Upvotes: 0
Views: 1329
Reputation: 528
Spring Data REST provides a RepositoryRestExceptionHandler
which contains a ResponseEntity<RepositoryConstraintViolationExceptionMessage> handleRepositoryConstraintViolationException(RepositoryConstraintViolationException o_O)
method.
The RepositoryRestMvcConfiguration
class provides a bean for such an exception handler. If you want to modify it, try providing your own bean and registering it with the configuration. You can do this by, for example, implementing the RepositoryRestConfigurer
as you should be familiar from other Spring projects (Spring Security, ...).
Upvotes: 0
Reputation: 669
You can handle ConstraintViolationException by ControllerAdvice, I have tried and it works fine, Please find below code snippets for Reference.
User.java
@Entity
@Getter
@Setter
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
private String name;
@NotNull
private String surname;
}
UserRepository.java
@RepositoryRestResource
public interface UserRepository extends JpaRepository<User, Long> {
}
GlobalExceptionHandler.java
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<?> handlerException(ConstraintViolationException e) {
final List<Object> errors = new ArrayList<>();
e.getConstraintViolations().stream().forEach(fieldError -> {
Map<String, Object> error = new HashMap<>();
error.put("path", String.valueOf(fieldError.getPropertyPath()));
error.put("messgae", fieldError.getMessage());
errors.add(error);
});
HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
Map<String, Object> body = new HashMap<>();
body.put("error", errors);
return new ResponseEntity<>(body, httpStatus);
}
}
I have used the map for the response body, you can use customize objects as per requirements.
Then try below CURL to test API.
curl --location --request POST 'http://localhost:8080/users' \
--header 'Content-Type: application/json' \
--data-raw '{}'
The response will look like.
Status: 400 BAD REQUEST
{"error":[{"path":"surname","messgae":"must not be null"},{"path":"name","messgae":"must not be null"}]}
Upvotes: 4