1

I am working on a Spring MVC application. I wrote an mvc:interceptor for printing the JSON content of the incoming request. I tried 2 ways for doing that but both don't work.

First way using getReader() this did not work because getReader() can get called only once and it seems it's already called by the container so the suggestion was to use the ServletInputStream interface. I have the following code:

public class RequestInterceptor implements HandlerInterceptor  {

private static final Logger logger = LoggerFactory.getLogger(RequestInterceptor.class);


@Override
public boolean preHandle(HttpServletRequest request,
        HttpServletResponse response, Object handler) throws Exception {

    logger.info("Received HTTP request with URL:" + request.getRequestURL());

    ServletInputStream in = request.getInputStream();
    byte[] buf = new byte[1000];
    StringBuilder sb = new StringBuilder();
    for (int nChunk = in.read(buf); nChunk!=-1; nChunk = in.read(buf))
    {
        sb.append(new String (buf,  0, nChunk));
    }

    logger.info("Request JSON Content" + sb.toString());


    return true;
}
...
}

The problem with this approach is that after it passes the interceptor and get to the spring controller, it gets no input, probably because my function already read the input.

I get the following log message:

INFO : com.feelstream.server.interceptors.RequestInterceptor - Received HTTP request with URL:http://localhost:8090/server/FsServer/push_event
INFO : com.feelstream.server.interceptors.RequestInterceptor - Request JSON Content{
    "evt_time":7,
    "cell_id":7866,
    "cell_lac":31,
    "device_id":"62c7c7042511c086",
    ...
}



DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor - Reading [class com.feelstream.utils.Event] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@4bec03a6]
DEBUG: org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Resolving exception from handler [public com.feelstream.utils.Response com.feelstream.server.controller.FsController.pushEvent(com.feelstream.utils.Event,org.springframework.validation.BindingResult)]: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: No content to map due to end-of-input
 at [Source: org.apache.catalina.connector.CoyoteInputStream@62818036; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
 at [Source: org.apache.catalina.connector.CoyoteInputStream@62818036; line: 1, column: 1]
7
  • Exception suggesting, input is not a valid json..could you please validate the json in online tool once? Commented Jun 22, 2014 at 6:03
  • The JSON works perfectly when I remove the interceptor. I read "No content to map due to end-of-input" as empty input, probably due to the first reading. Commented Jun 22, 2014 at 6:09
  • 1
    This is classic problem of logging request body... it is a strem of possibly arbitrary length. Either you need to wrap the request to allow double reading or it will be much simpler if you wrap MappingJackson2HttpMessageConverter . Commented Jun 22, 2014 at 6:19
  • Thx Pavel. How does the double reading technique work? Do you have an example? Commented Jun 22, 2014 at 8:16
  • 2
    Spring provides already a filter which can do that for you. The CommonsRequestLoggingFilter. Register the filter and set the includePayload property to true. Commented Jun 22, 2014 at 12:18

1 Answer 1

6

Isaac,

You should be able to add this filter like any other Filter

     <filter>
        <filter-name>commonsRequestLoggingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CommonsRequestLoggingFilter</filter-class>
     <init-param>
         <param-name>includePayload</param-name>
         <param-value>true</param-value>
      </init-param>
      </filter>

In your web.xml

This will log the message before it is read by Spring. If you need additional logging you can extend this filter and add more functionality.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.