14

As stated in title, what does it mean that HttpServletResponse is committed?

I have some request interceptor, extending HandlerInterceptorAdapter, that overrides postHandle method. Post handle method takes parameter final HttpServletResponse response. In method body there is an if statement checking if response.isCommitted(), what exactly does that check?

private static final String voidResponse = "null";

@Override
    public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler,
            final ModelAndView modelAndView) throws IOException {
        if (!response.isCommitted()) {
            if (DefaultServletHttpRequestHandler.class == handler.getClass()) {
                return;
            }
            response.setStatus(200);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json");
            try (final Writer writer = response.getWriter()) {
                writer.write(voidResponse);
            }
            log.info("void method called, respond with 200 and null");

            response.flushBuffer();
        }
    }
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
Akka Jaworek
  • 1,970
  • 4
  • 21
  • 47

2 Answers2

15

ServlerResponse.isCommited() checks if the response has been already committed to the client or not (Means the servlet output stream has been opened to writing the response content).

The committed response holds the HTTP Status and Headers and you can't modify it. It's important also to note that in this case the response content has NOT been written yet, as the headers and status are committed before the content itself.

In such examples as yours the check is required to prevent situations when the response has already been commited but someone is trying to modify it, in which case you will get an IllegalStateException stating that response has already been committed.

UPDATE: I see that you are using Spring controllers. The story differs a bit here.

  • Case 1: If you are using @ResponseBody in your controller method or returning ResponseEntity Spring writes to and commits the response before the postHandle() is called, which makes it impossible to change the response later. That said in this case response.isCommited() statement will always return true and you are not able to modify the response.
  • Case 2: If you don't have the above mentioned annotation and don't return ResponseEntity or controller returns NULL the postHandle() method of interceptor is called after the controller method has been processed, but the response has not been committed yet. This means you can modify the response as you want (e.g. return 200 OK).
vtor
  • 8,989
  • 7
  • 51
  • 67
  • the point of this interceptor is to modify response when client calls a void method or when called method returns null instead of object from method signature, in this case it modifys response status to 200 and returns json with "null". i will edit post with method body to show what i mean. – Akka Jaworek Sep 27 '16 at 13:55
  • @AkkaJaworek I've updated my answer please check. It explains your problem. Hope that helps. – vtor Sep 27 '16 at 14:11
  • thanks, thios is almost the case, i have controller methods that are suposed to return ``ResponseEntity`` however in some cases it can return null. If i understand you correctly in this case it would be: ``return ResponseEntity;`` <- response is comminted; ``return null;``<-response is not commited. Void methods fall in case 2 as well, since they dont return ``ResponseEntity``, correct? – Akka Jaworek Sep 27 '16 at 14:20
  • @AkkaJaworek Yes that's correct, void methods do not return ResponseEntity therefore the response is not being committed after controller method execution. The rest of your assumptions are also correct. – vtor Sep 27 '16 at 15:07
2

It is response committed not request. It means response already sent to output stream/client.

Sundararaj Govindasamy
  • 8,180
  • 5
  • 44
  • 77
  • of course i ment response, bad copy-paste, however how does that relates to what controllers endpoint returns? from what i've tested when controller returns ``null``, response is not commited and when it returns object of type from method signature, response is already commited, is this always the case (when endpoint returns null -> response not commited)? – Akka Jaworek Sep 27 '16 at 13:41
  • That shouldn't be a case. Not sure what do you refer as controllers, however it's up to the servlet/framework you are using which commits the response and how it delegates the request to your interceptor. The returned response content can be NULL and the response is still commited (as you see the status code probably). – vtor Sep 27 '16 at 13:45
  • the point of this interceptor is to intercept all calls to controllers void methods and since void method does not return anything by itself, this should modify the response to return status 200 with json containing "null". The same rule should apply to methods returning null. As far as i tested this solution works, however i want to understand why. btw. its Spring framework – Akka Jaworek Sep 27 '16 at 13:51