springspring-bootrestexception

How to handle MethodArgumentTypeMismatchException and set a custom error message in spring boot?


I'm making an REST API and, while trying purposefully wrong inputs to force errors, I stumbled in this one:

2023-12-01T19:43:11.427-03:00 WARN 23912 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; For input string: "43178asdas"]

The body of the response was as follows:

{
    "timestamp": "2023-12-01T22:43:11.433+00:00",
    "status": 400,
    "error": "Bad Request",
    "message": "Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; For input string: \"43178asdas\"",
    "path": "/objectName/43178asdas"
}

I want to make a custom message for the error, making it clearer that the expected input was type Long, but instead the request received a type String, but I'm not managing to handle the exception.

What I tried:

public class ThisObjectInvalidaException extends TypeMismatchException {
    public ThisObjectInvalidaException(String msg){
        super(msg);
    }
}

and

public SaidObject consult(Long param) throws ThisObjectInvalidaException {
        try {
            return this.objRepository.findById(identifier)
                    .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No object found with the following IDENTIFIER: " + identifier + "."));
        } catch (TypeMismatchException e){
            throw new ThisObjectInvalidaException("The IDENTIFIER you entered is invalid, as it should contain only numbers.");
        }
    }

Maybe I'm missing something in the error type or so, but not sure...


Solution

  • You can simply add ExceptionHandler to your controller.

    Example:

    @RestController
    public class YourController {
    
        // Your endpoint mappings
    
        @ExceptionHandler(MethodArgumentTypeMismatchException.class)
        public ResponseEntity<String> handleTypeMismatch(MethodArgumentTypeMismatchException ex) {
            String error = "The IDENTIFIER you entered is invalid, as it should contain only numbers.";
            return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
        }
    }
    

    As an alternative solution you can create the custom exception and throw it.

    Example 2:

        public class IdentifierFormatException extends RuntimeException {
    
        public IdentifierFormatException(String message) {
            super(message);
        }
    
    }
    

    and then add it to exception handler:

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
        public ResponseEntity<String> handleTypeMismatch(MethodArgumentTypeMismatchException ex) {
            throw new IdentifierFormatException("The IDENTIFIER you entered is invalid, as it should contain only numbers.");
        }