Home > Software design >  Spring Boot request body validation add customize messages when input an invalid data type
Spring Boot request body validation add customize messages when input an invalid data type

Time:11-22

I am using Spring Boot to create a POST request and I need to validate the request body based on user inputs. However, when the user inputS an invalid data type, the response shows nothing, just 400 bad request status. Can I add a message to show the user which field is an invalid data type?

For example: Here is my controller:

@RestController
@RequestMapping("/api/foo")
public class FooController {

  @PostMapping("/save")
  public void postFoo(@Valid @RequestBody Foo foo) {
    // do somethings
  }
}

And here is my Foo class:

public class Foo {
  @NotBlank
  private String name;
  private Integer age;

  // getter/setter
}

So now I post a request as below:

{
  "name": "Foo Name",
  "age": "A String"
}

The server will respond with the status 400 Bad request without any message. How can I put my message such as Age must be an integer.

Until now I only have a solution that changes Age to String and adds a @Pattern validation annotation.

public class Foo {
  @NotBlank
  private String name;
  @Pattern(regexp = "[0-9]*", message = "Age must be an intege")
  private String age;

  // getter/setter
}

CodePudding user response:

In your post method signature, you can make use of Response Entity class to show some exception message that is to be returned to the user, along with some status code .

CodePudding user response:

You need to implement error handling mechanism.

In your error handler you need to catch all exceptions and return error response. Here is an example based on Controller level ExceptionHandling

public class FooController{

   //...
   @ResponseStatus(value=HttpStatus.BAD_REQUEST)
   @ExceptionHandler({ CustomException1.class, CustomException2.class })
      public ErrorResponse handleException() {
      //
   }
}

Here in ErrorResponse model you can set error code and message according to exception and via ResponseStatus you can assign http errro code

However this his approach has a major drawback: The @ExceptionHandler annotated method is only active for that particular Controller, not globally for the entire application.

To globally handle exception you can use ControllerAdvice. Here is a good article on overall error handling mechanism

CodePudding user response:

Thanks, everybody. I found a way to add messages and respond to users can aware of the error by using ControllerAdvice and overriding the handleHttpMessageNotReadable method as example below:

@ControllerAdvice
public class ErrorHandlerConfig extends ResponseEntityExceptionHandler {
 @Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers,
                                                              HttpStatus status, WebRequest request) {
    if (ex.getCause() instanceof InvalidFormatException) {
        InvalidFormatException iex = (InvalidFormatException) ex.getCause();
        List<Map<String, String>> errors = new ArrayList<>();
        iex.getPath().forEach(reference -> {
            Map<String, String> error = new HashMap<>();
            error.put(reference.getFieldName(), iex.getOriginalMessage());
            errors.add(error);
        });

        return handleExceptionInternal(ex, errors, new HttpHeaders(), apiError.getStatus(), request);
    }
    return super.handleHttpMessageNotReadable(ex, headers, status, request);
}
}

The response will be:

[
    {
        "testId": "Cannot deserialize value of type `java.lang.Long` from String \"accm\": not a valid Long value"
    }
]
  • Related