1

Hi I am new to spring boot.when I try submit the request from the postman it is returning org.springframework.transaction.TransactionSystemException with HttpStatus code : 500 if invalid it throwing the javax.validation.ConstraintViolationException in the server. Can any one share the best solution to handle these exceptions? I tried in controller with the below code:

@ExceptionHandler(ConstraintViolationException.class)
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  ResponseEntity<String> handleConstraintViolationException(ConstraintViolationException e) {
    return new ResponseEntity<>("not valid due to validation error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
  }

But I want the response to be send in Json format with customized error message How can I achieve it ?

And also wanted to avoid the exception handling code in the controller.Is there any better way?

ban29
  • 11
  • 1
  • 1
  • 4
  • Given that HttpStatus 500 is Server error, the best way to handle this is to fix whatever is causing the exception in the first place. And for anyone to help, you will need to provide the code that is causing the error as well as the trace of it. – Jetto Martínez Sep 08 '21 at 15:31
  • This answer may will help you https://stackoverflow.com/questions/22946549/javax-validation-constraintviolationexception – 4EACH Sep 08 '21 at 15:39
  • The main cause for the 500 response is invalid data input. But now I am handling this error at the controller level where I am sending the request parameters that has to be validated.( I am not sure if it is a good practise).But now want the response as json error response not simply a text – ban29 Sep 08 '21 at 15:39
  • 1
    change ResponseEntity to ResponseEntity and put the object with any fields you want instead of ""not valid due to validation error: " + e.getMessage()", than the object will be automatically converted to json – Alexandr Arhipov Sep 08 '21 at 15:50
  • Well you can always use `@ControllerAdvice` to cover up your exception, yet I found it better investigate what cause this issue in the first place. Who knows may be you are doing it wrong! – ray Sep 09 '21 at 02:23

3 Answers3

1

Each of such exceptions must be handled separately like below

@RestControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
  
    @ExceptionHandler ({ConstraintViolationException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    protected ResponseEntity<Object> handleConstraintViolationException(
            ConstraintViolationException e) {
        return new ResponseEntity<>(new JsonErrorResponse(e.getMessage()), HttpStatus.BAD_REQUEST);
    }
}

If you want to create your own response object then u can use the below way in the RestExceptionHandler class.

@Override
    protected ResponseEntity<Object> handleHttpMessageNotReadable(
            HttpMessageNotReadableException e, HttpHeaders headers, HttpStatus status, WebRequest request) {

        return new ResponseEntity<>(new CustomErrorResponse(e.getMessage()), HttpStatus.BAD_REQUEST);

    }

private class CustomErrorResponse {
        String message;

        public CustomErrorResponse() {
        }

        public CustomErrorResponse(String message) {
            super();
            this.message = message;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }
Ramya Musunuru
  • 177
  • 1
  • 5
0

You can use @ControllerAdvice. It's a special component to handle error across the hole application. Here I show you a example:

@ControllerAdvice
public class CustomErrorHandler{

    @ResponseStatus(HttpStatus.BAD_REQUEST)  
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<String> handleContraintViolationException() {
        // Your custom response
    }
}

The pro is that you have a different class that handle the exceptions in all the application.

  • But I am getting this as error response {"status": "BAD_REQUEST", "message": "Invalid input request parameters", "errors": [ "functionname.object[0].fieldname: fieldname cannot be empty ] } I dont want to expose the field name and object details in error response . Is there any way I avoid exposing and only message is displayed? – ban29 Sep 09 '21 at 08:13
  • You can create you custom response, for example you can pass the exception as parameter in the function and then extract the Set from it and create your custom message with this data. Check the solution 4 for more details about ControllerAdvice: [link](https://www.baeldung.com/exception-handling-for-rest-with-spring) – Alvaro Berrocal Sep 09 '21 at 10:31
-1

500 is a server problem. It means your server encounter a problem while executing the code. Specifically it's ConstraintViolationException which means you have a constraint when inserting your data in the database.

Example : Imagine we have an entity that has a unique field

@Entity
user {
   UUID id;
   @column
   String name;
}

and when creating the entity you have made a uniquness contrainte in database :

ALTER TABLE USER
ADD CONSTRAINT UC_name UNIQUE (name);

Here if you try to insert two user with the same name you would receive a ConstraintViolationException

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • Ok Thank you but is there any way to send the custom json error response instead of whole stack trace as error response with HTTP status code 400 ? – ban29 Sep 08 '21 at 15:48
  • You can do two things here : First validate data and if it's not good throw specifc runtime exception as follows : example: `@ResponseStatus(HttpStatus.NOT_FOUND) public class CarNotFoundException extends RuntimeException { public CarNotFoundException() { super(ErrorCode.CAR_NOT_FOUND.getCode()); } }` Otherwise, you need to define a global error handler by using `@ExceptionHandler` with the `@ControllerAdvice` annotation. – Kais Neffati Sep 08 '21 at 15:59