REST Handling a Bad Parameter

What is the correct way to handle a bad parameter in a RESTful service? I have an endpoint right now that returns 400 if the wrong data type is sent.

@ResponseBody @RequestMapping(produces = "application/json", method = RequestMethod.GET, value="/v1/test") public MyResponse getSomething(@RequestParam BigDecimal bd) { MyResponse r = new MyResponse(); r.setBd(bd); return r; } 

It would be very nice if the end user passed, say, String instead of BigDecimal, that the response would return json with the response code, status and everything else that I want it to contain, not just 400. Is there a way to do this?

Update. My initial thought was to wrap each parameter and then check if it matches the correct type in this wrapper class. It seems a little silly. Isn't there a validator that I could just add to the classpath that recognizes something like this?

In addition, there is a way to handle this quite easily with a Bean type that I could create myself, but what about standard types like BigDecimal?

UPDATE-2: This update is responsible for the response using @ExceptionHandler.

TestController.java

 import java.math.BigDecimal; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; @Controller @RequestMapping("/") public class TestController { //this is where correct input from user is passed, no binding errors @RequestMapping(produces = "application/json", method = RequestMethod.GET, value="/v1/test") public @ResponseBody MyResponse getSomething(@RequestParam BigDecimal bd) { MyResponse r = new MyResponse(); r.setBd(bd); return r; } //this will handle situation when you except number and user passess string (A123.00 for example) @ExceptionHandler(ServletRequestBindingException.class) public @ResponseBody MyErrorResponse handleMyException(Exception exception, HttpServletRequest request) { MyErrorResponse r = new MyErrorResponse(); r.setEexception(exception); return r; } } 

TestUnitTest.java

 public class TestUnitTest { protected MockMvc mockMvc; @Autowired protected WebApplicationContext wac; @Before public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); } @Test public void test() throws Exception { String url = "/v1/test?bd=a123.00"; log.info("Testing Endpoint::: " + url); MvcResult result = mockMvc.perform(get(url)) .andExpect(status().isOk()) .andReturn(); log.info("RESPONSE::: " + result.getResponse().getContentAsString()); } } 

Myresponse.java

 import java.math.BigDecimal; public class MyResponse { private BigDecimal bd; public BigDecimal getBd() { return bd; } public void setBd(BigDecimal bd) { this.bd = bd; } } 

MyErrorResponse.java

 public class MyErrorResponse { private Exception exception; public Exception getException() { return exception; } public void setEexception(Exception e) { this.exception = e; } } 
+5
source share
1 answer

Use Spring @ExceptionHandler along with the standard @RequestMapping annotation as follows:

 //this is where correct input from user is passed, no binding errors @RequestMapping(produces = "application/json", method = RequestMethod.GET, value="/v1/test") public @ResponseBody MyResponse getSomething(@RequestParam BigDecimal bd) { MyResponse r = new MyResponse(); r.setBd(bd); return r; } //this will handle situation when there exception during binding, for example you except number and user passess string (A123.00 for example) @ExceptionHandler(TypeMismatchException.class) public @ResponseBody MyErrorResponse handleMyException(Exception exception, HttpServletRequest request) { //.... } 

TypeMismatchException is a general exception that occurs when trying to set the bean property. You can generalize the code even more and catch each mandatory exception using several methods, for example:

 @ExceptionHandler(TypeMismatchException.class) public @ResponseBody String typeMismatchExpcetionHandler(Exception exception, HttpServletRequest request) { return "type mismatch"; } @ExceptionHandler(MissingServletRequestParameterException.class) public @ResponseBody String missingParameterExceptionHandler(Exception exception, HttpServletRequest request) { return "missing param"; } @ExceptionHandler(Exception.class) public @ResponseBody String generalExceptionHandler(Exception exception, HttpServletRequest request) { return "general exception"; } 

It is very flexible, allowing many parameters in the signature and returned objects Annotation Type ExceptionHandler

With @ResponseBody you can return any object that can be serialized in JSON. It only required a jackson library in your classpath, but I assume you already know this

+3
source

Source: https://habr.com/ru/post/1202447/


All Articles