Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpringBoot doesn't handle org.hibernate.exception.ConstraintViolationException

I have defined a pattern for validating email in my Entity class. In my validation exception handler class, I have added handler for ConstraintViolationException. My application utilize SpringBoot 1.4.5.

Profile.java

@Entity @EntityListeners(AuditingEntityListener.class) @Table(name = "profile") public class Profile extends AuditableEntity {    private static final long serialVersionUID = 8744243251433626827L;    @Column(name = "email", nullable = true, length = 250)   @NotNull   @Pattern(regexp = "^([^ @])+@([^ \\.@]+\\.)+([^ \\.@])+$")   @Size(max = 250)   private String email; .... } 

ValidationExceptionHandler.java

@ControllerAdvice public class ValidationExceptionHandler extends ResponseEntityExceptionHandler {    private MessageSource messageSource;    @Autowired   public ValidationExceptionHandler(MessageSource messageSource) {     this.messageSource = messageSource;   }    @ExceptionHandler(ConstraintViolationException.class)   public ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException ex,   WebRequest request) {     List<String> errors = new ArrayList<String>();     ....     } }  

When I run my code and pass invalid email address, I get the following exception. The code in handleConstraintViolation is never executed. The http status returned in the exception is 500, but I want to return 400. Any idea how I can achieve that?

2017-07-12 22:15:07.078 ERROR 55627 --- [nio-9000-exec-2] o.h.c.s.u.c.UserProfileController        : Validation failed for classes [org.xxxx.common.service.user.domain.Profile] during persist time for groups [javax.validation.groups.Default, ] List of constraint violations:[ ConstraintViolationImpl{interpolatedMessage='must match "^([^ @])+@([^ \.@]+\.)+([^ \.@])+$"', propertyPath=email, rootBeanClass=class org.xxxx.common.service.user.domain.Profile, messageTemplate='{javax.validation.constraints.Pattern.message}'}]  javax.validation.ConstraintViolationException: Validation failed for classes [org.xxxx.common.service.user.domain.Profile] during persist time for groups [javax.validation.groups.Default, ] List of constraint violations:[ ConstraintViolationImpl{interpolatedMessage='must match "^([^ @])+@([^ \.@]+\.)+([^ \.@])+$"', propertyPath=email, rootBeanClass=class org.xxxx.common.service.user.domain.Profile, messageTemplate='{javax.validation.constraints.Pattern.message}'}]  at  org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:138)  at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:78)     
like image 858
bostonjava Avatar asked Jul 13 '17 02:07

bostonjava


People also ask

What is ConstraintViolationException in hibernate?

hibernate. exception. ConstraintViolationException. This is by far the most common cause of DataIntegrityViolationException being thrown – the Hibernate ConstraintViolationException indicates that the operation has violated a database integrity constraint.

What is ConstraintViolationException in Java?

Exception thrown when an action would violate a constraint on repository structure. For example, when an attempt is made to persistently add an item to a node that would violate that node's node type.

What is @valid Annotation in spring boot?

The @Valid annotation ensures the validation of the whole object. Importantly, it performs the validation of the whole object graph. However, this creates issues for scenarios needing only partial validation. On the other hand, we can use @Validated for group validation, including the above partial validation.

What are the hibernate exceptions in Spring Boot?

When Spring is configured with Hibernate, the exception is thrown in the exception translation layer provided by Spring – SessionFactoryUtils – convertHibernateAccessException. There are three possible Hibernate exceptions that may cause the DataIntegrityViolationException to be thrown:

What is @exceptionhandler annotation in Spring Boot?

@ExceptionHandler annotation provided by Spring Boot can be used to handle exceptions in particular Handler classes or Handler methods. Any method annotated with this is automatically recognized by Spring Configuration as an Exception Handler Method. An Exception Handler method handles all exceptions and their subclasses passed in the argument.

What is dataintegrityviolationexception in hibernate?

When Spring is configured with Hibernate, the exception is thrown in the exception translation layer provided by Spring – SessionFactoryUtils – convertHibernateAccessException. There are three possible Hibernate exceptions that may cause the DataIntegrityViolationException to be thrown: 3.2. DataIntegrityViolationException With JPA

How to handle nosuchelementexception in Spring Boot?

On Running the Spring Boot Application and hitting the /getCustomer API with an Invalid Customer Id, we get a NoSuchElementException completely handled by Spring Boot as follows: Spring Boot provides a systematic error response to the user with information such as timestamp, HTTP status code, error, message, and the path.


2 Answers

You cannot catch ConstraintViolationException.class because it's not propagated to that layer of your code, it's caught by the lower layers, wrapped and rethrown under another type. So that the exception that hits your web layer is not a ConstraintViolationException.

In my case, it's a TransactionSystemException. I'm using @Transactional annotations from Spring with the JpaTransactionManager. The EntityManager throws a rollback exception when somethings goes wrong in the transaction, which is converted to a TransactionSystemException by the JpaTransactionManager.

So you could do something like this:

@ExceptionHandler({ TransactionSystemException.class }) public ResponseEntity<RestResponseErrorMessage> handleConstraintViolation(Exception ex, WebRequest request) {     Throwable cause = ((TransactionSystemException) ex).getRootCause();     if (cause instanceof ConstraintViolationException) {         Set<ConstraintViolation<?>> constraintViolations = ((ConstraintViolationException) cause).getConstraintViolations();         // do something here     } } 
like image 165
nimai Avatar answered Sep 26 '22 10:09

nimai


Just want to add something. I was trying to do the same thing, validating the entity. Then I realized Spring has already everything out of the box if you validate the controller's input.

@RequestMapping(value = "/profile", method = RequestMethod.POST) public ProfileDto createProfile(@Valid ProfileDto profile){ ...     } 

The @Valid annotation will trigger the validation with the javax.validation annotations.

Suppose you have a Pattern annotation on your profile username with a regexp not allowing whitespaces.

Spring will build a response with status 400 (bad request) and a body like this one:

{     "timestamp": 1544453370570,     "status": 400,     "error": "Bad Request",     "errors": [         {             "codes": [                 "Pattern.ProfileDto.username",                 "Pattern.username",                 "Pattern.java.lang.String",                 "Pattern"             ],             "arguments": [                 {                     "codes": [                         "profileDto.username",                         "username"                     ],                     "arguments": null,                     "defaultMessage": "username",                     "code": "username"                 },                 [],                 {                     "defaultMessage": "^[A-Za-z0-9_\\-.]+$",                     "arguments": null,                     "codes": [                         "^[A-Za-z0-9_\\-.]+$"                     ]                 }             ],             "defaultMessage": "must match \"^[A-Za-z0-9_\\-.]+$\"",             "objectName": "profileDto",             "field": "username",             "rejectedValue": "Wr Ong",             "bindingFailure": false,             "code": "Pattern"         }     ],     "message": "Validation failed for object='profileDto'. Error count: 1",     "path": "/profile" } 
like image 23
Ena Avatar answered Sep 23 '22 10:09

Ena