4

I have controllers that return JSON to the client. The controllers methods are marked using mvc annotation such as:

@RequestMapping("/delete.me")
public @ResponseBody Map<String, Object> delete(HttpServletRequest request, @RequestParam("ids[]") Integer[] ids) {

Spring knows to return JSON since Jackson is on the class path and the client is requesting a JSON response. I would like to log the response of these requests and all other controllers. In the past I have used an interceptor to do this. However, I got the response body from the ModelAndView. How can I get the response body in the inteceptor now that I'm using @ResponseBody? Specifically, how can I get the response body in this method?

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
James
  • 2,876
  • 18
  • 72
  • 116
  • How about an approach suggested here - http://stackoverflow.com/questions/3242236/capture-and-log-the-response-body – Biju Kunjummen Jan 16 '13 at 02:43
  • or here http://stackoverflow.com/questions/701681/how-can-i-read-an-httpservletreponses-output-stream – arahant Jan 16 '13 at 04:08
  • 1
    Thanks for the alternatives. Is there no way to do this using a Spring HandlerInterceptorAdapter? – James Jan 28 '13 at 15:27

1 Answers1

5

You can log everything by using CustomizableTraceInterceptor you can either set it in your application context xml config and use AOP: (log level Trace)

    <bean id="customizableTraceInterceptor"  
        class="org.springframework.aop.interceptor.CustomizableTraceInterceptor">  
        <property name="exitMessage" value="Leaving $[methodName](): $[returnValue]" />  
    </bean>  

or you can completly customize it by implementing it in Java and use the method setExitMessage():

public class TraceInterceptor extends CustomizableTraceInterceptor {

    private Logger log = LoggerFactory.getLogger("blabla");

    @Override
    protected void writeToLog(Log logger, String message, Throwable ex) {
        //Write debug info when exception is thrown
        if (ex != null) {
            log.debug(message, ex);
        }
          ....
    }

    @Override
    protected boolean isInterceptorEnabled(MethodInvocation invocation, Log logger) {
        return true;
    }

    @Override
    public void setExitMessage(String exitMessage) {
            .... //Use PlaceHolders
    }
}

and use the placeholders such as '$[returnValue]'. You can find the complete list in the spring api documentation.

EDIT: Also, if you want to get the value of your @ResponseBody in another interceptor, I think it's not possible until version > 3.1.1. Check this issue: https://jira.springsource.org/browse/SPR-9226

Rigg802
  • 2,666
  • 1
  • 16
  • 14