David Portabella
David Portabella

Reputation: 12720

spring, show a custom error message for a restful webservice with invalid parameters (using the automatic parameter conversion from spring)

I have a rest webservice that expects a number:

@RequestMapping(value = "/bb/{number}", method = RequestMethod.GET, produces = "plain/text")
public void test(@PathVariable final double number, final HttpServletResponse response) 

However, if the client passes a text such "QQQ" instead of a number, the client gets an error from spring like this:

HTTP Status 500 -
The server encountered an internal error () that prevented it from fulfilling this request.
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'double'; nested exception is java.lang.NumberFormatException: For input string: "QQQ"
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894)
...

I need to handle this case, and show a proper error message, such as:

<MyError>
  <InvalidParameter parameterName="number"/>
  <message>...</message>
</MyError>

How can I do that?

This can be achieved by catching the org.springframework.beans.TypeMismatchException exception (as shown in the following code), but it has many problems. For instance, there could be other TypeMismatchException exceptions that are not related to parsing and converting the parameters of the webservice request.

import org.springframework.beans.TypeMismatchException;
import javax.annotation.*;
import javax.servlet.http.*;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.*;

@Controller
@RequestMapping(value = "/aa")
public class BaseController {

    @RequestMapping(value = "/bb/{number}", method = RequestMethod.GET, produces = "plain/text")
    public void test(@PathVariable final double number, final HttpServletResponse response) throws IOException {
        throw new MyException("whatever");
    }

    @ResponseBody
    @ExceptionHandler
    public MyError handleException(final Exception exception) throws IOException {
        if (exception instanceof TypeMismatchException) {
            response.setStatus(HttpStatus.BAD_REQUEST.value());
            TypeMismatchException e = (TypeMismatchException) exception;
            String msg = "the value for parameter " + e.getPropertyName() + " is invalid: " + e.getValue(); 
            return new MyError(msg);
        }

        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        return MyError("Unknown internal error");
    }
}

so, how to show a custom error message if the client calls with an invalid number, such as http://example.com/aa/bb/QQQ ?

ps: one solution could be to define the "number" parameter as a String, and do the conversion from inside my function (then I could catch and throw my custom exception). In this question, I am asking for a solution while keeping the automatic parameter conversion of spring.

ps: Moreover, spring responds to the client with a "HTTP 500 Internal Server Error", instead of a "HTTP 400 Bad Request". Does this make sense?!

Upvotes: 3

Views: 1849

Answers (1)

Manish Dubey
Manish Dubey

Reputation: 11

Use BindingResult in your controller class. It will make invalid fields as null,now you can write your own custom validation class where you can check if this filed is null then generate custom message like "Valid Date is required"

Upvotes: 1

Related Questions