13

We have REST services exposed via Spring MVC. We use a HandlerExceptionResolver to log exceptions. We currently log the following:

  • The exception and its stack trace
  • The URL
  • The request headers

It would make debugging easier if we could also log the JSON post data as well. Any suggestions on how to get this?

Tom Norton
  • 751
  • 1
  • 8
  • 19

3 Answers3

19

Add this to the class representing the configuration for the application:

import javax.servlet.Filter;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.filter.AbstractRequestLoggingFilter;

....

@Bean
public Filter loggingFilter(){
    AbstractRequestLoggingFilter f = new AbstractRequestLoggingFilter() {

        @Override
        protected void beforeRequest(HttpServletRequest request, String message) {
            System.out.println("beforeRequest: " +message);
        }

        @Override
        protected void afterRequest(HttpServletRequest request, String message) {
            System.out.println("afterRequest: " +message);
        }
    };
    f.setIncludeClientInfo(true);
    f.setIncludePayload(true);
    f.setIncludeQueryString(true);

    f.setBeforeMessagePrefix("BEFORE REQUEST  [");
    f.setAfterMessagePrefix("AFTER REQUEST    [");
    f.setAfterMessageSuffix("]\n");
    return f;
}

you may have to comment out

   f.setIncludePayload(true);
Gary
  • 6,357
  • 5
  • 30
  • 36
nyxee
  • 2,773
  • 26
  • 22
10

You need a filter that would save request body when it's being read and provide the saved data to your exception logger later.

Spring contains AbstractRequestLoggingFilter that does the similar thing. Though it's not directly suitable for your problem, you can use it as a reference to implement your own filter.

axtavt
  • 239,438
  • 41
  • 511
  • 482
  • 1
    If you're using Spring 4.1.3+ (see SPR-12477), make sure to map your filter to your MVC Dispatcher Servlet and not to `/*`, or your request won't get wrapped in the essential `ContentCachingRequestWrapper`. – László van den Hoek May 26 '15 at 15:47
  • 2
    @LászlóvandenHoek, Can you elaborate? I don't follow you. I am using the `ContentCachingRequestWrapper`, but the request body is always an empty string. – Abhijith Madhav Sep 11 '16 at 17:55
  • @AbhijithMadhav filters are enabled by mapping them either to a URL pattern or a servlet. What I meant was that you need to make sure you map your `AbstractRequestLoggingFilter` to your dispatcher, not to the `/*` URL pattern. – László van den Hoek Sep 15 '16 at 11:11
5

There is no easy way to log the payload of the request/response. You can use a java web filter to intercept all the requests and responses and read the JSON data from the stream. But there is one problem, when you will read data from the stream the actual data will be exhausted from stream.

Therefore, you have to implement the wrapper of actual request and response object. Only the copied version of request response will be logged. We have implemented similar solution like follows and it satisfied our requirement:

http://www.wetfeetblog.com/servlet-filer-to-log-request-and-response-details-and-payload/431

http://angelborroy.wordpress.com/2009/03/04/dump-request-and-response-using-javaxservletfilter/

Shamim Ahmmed
  • 8,265
  • 6
  • 25
  • 36