Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring rest Handling empty request body (400 Bad Request)

I am developing a RESTful app using Spring4. I want to handle the case when a POST request contains no body. I wrote the following custom exception handler:

    @ControllerAdvice
    public class MyRestExceptionHandler {
     
      @ExceptionHandler
      @ResponseStatus(HttpStatus.BAD_REQUEST)
      public ResponseEntity<MyErrorResponse> handleJsonMappingException(JsonMappingException ex) {
          MyErrorResponse errorResponse = new MyErrorResponse("request has empty body");
          return new ResponseEntity<MyErrorResponse>(errorResponse, HttpStatus.BAD_REQUEST);
      }   
      @ExceptionHandler(Throwable.class)
      public ResponseEntity<MyErrorResponse> handleDefaultException(Throwable ex) {
        MyErrorResponse errorResponse = new MyErrorResponse(ex);
        return new ResponseEntity<MyErrorResponse>(errorResponse, HttpStatus.BAD_REQUEST);
      }
    }
    
     @RestController
     public class ContactRestController{
        @RequestMapping(path="/contact", method=RequestMethod.POST)
        public void save(@RequestBody ContactDTO contactDto) {...}
     } 

When it receives a POST with no body, these methods aren't called. Instead, the client gets a response with 400 BAD REQUEST HTTP status and empty body. Does anybody know how to handle it?

like image 377
rvit34 Avatar asked Dec 22 '16 22:12

rvit34


3 Answers

I solved the issue (the custom exception handler must extend ResponseEntityExceptionHandler). My solution follows:

        @ControllerAdvice
        public class RestExceptionHandler extends ResponseEntityExceptionHandler {
    
            @Override
            protected ResponseEntity<Object> handleHttpMessageNotReadable(
                HttpMessageNotReadableException ex, HttpHeaders headers,
                HttpStatus status, WebRequest request) {
                // paste custom hadling here
            }
        }
like image 71
rvit34 Avatar answered Nov 03 '22 05:11

rvit34


In my case, I need to handle all requests that have invalid parameters. So I extend my class with ResponseEntityExceptionHandler and override the method handleMissingServletRequestParameter. You can find your own handlers defined inside the class ResponseEntityExceptionHandler

@ControllerAdvice 
public class YourExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(Exception.class)
    public final ResponseEntity handleAllExceptions(Exception ex) {
        // Log and return
    }

    @Override
    public ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // Do your code here
        return new ResponseEntity<>("YOUR REQUEST PARAMS NOT MATCH!");
    } 
}
like image 5
Nguyen Minh Hien Avatar answered Nov 03 '22 03:11

Nguyen Minh Hien


I faced a similar issue and it didn't work for me because the component-scanpackage provided didn't include the package where my @ControllerAdvice was provided.

My XML had :

<context:component-scan base-package="com.bandi.rest" />

My package had a typo com.bandi.test.spring.exception. After changing it to com.bandi.rest.spring.exception it started working.

@ControllerAdvice
public class SpringRestExceptionHandler {

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public @ResponseBody ResponseEntity<ErrorResponse> handleNoMethodException(HttpServletRequest request,
            NoHandlerFoundException ex) {
        ErrorResponse errorResponse = new ErrorResponse(ex);
        errorResponse.setErrorMessage("resource not found with exception");
        return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Throwable.class)
    public @ResponseBody ResponseEntity<ErrorResponse> handleDefaultException(Throwable ex) {
        ErrorResponse errorResponse = new ErrorResponse(ex);
        errorResponse.setErrorMessage("request has empty body  or exception occured");
        return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.BAD_REQUEST);
    }
}

Also, if you need to handle scenario where your requested resource was not found (bad URL), then you'll have to add another configuration to your dispatcher servlet.

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>throwExceptionIfNoHandlerFound</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
</servlet>

Complete Working code is available here

like image 2
Kishore Bandi Avatar answered Nov 03 '22 03:11

Kishore Bandi