9

I'd like to add a cookie to an HttpServletResponse after its content (usually HTML) has been rendered.

As mentioned here (http://osdir.com/ml/java.jasig.uportal/2005-10/msg00276.html), and here (Adding a cookie to the response in Java after the header has been flushed?), this is possible by buffering up the response so it won't get flushed and sent to client (since after headers are sent to client, response is committed, and no more headers, namely cookie headers, can be sent to client).

Assuming this is the goal at hand: I gather that a possible way to accomplish this is by use of an HttpServletResponseWrapper, I can override its flushBuffer() method and prevent the actual flushing of headers\content to client:

public class BufferedHttpServletResponse extends HttpServletResponseWrapper {

    public BufferedHttpServletResponse(HttpServletResponse response) {
        super(response);
    }

    public void flushBuffer() {
    }

}

and apply this buffered response in a Filter, for the rest of the filter chain to use:

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    BufferedHttpServletResponse bufferedResponse = new BufferedHttpServletResponse(response);

    chain.doFilter(request, bufferedResponse);

    // ... create Cookie and add it to response ... response.addCookie(newCookie)
    // response.flushBuffer() ?        

}

Question: is the above okay, or is it completely off? Will the response's buffer just keep getting filled with content\headers (and possibly getting re-sized) until after my doFilter() exits, to then be flushed and sent to client by other filters or by the servlet container (Tomcat)? Should I flush the response myself? ... mentioned here (Should one call .close() on HttpServletResponse.getOutputStream()/.getWriter()?) that stream should not be closed, but should response be flushed in this case?

Not necessarily assuming this is the goal at hand: My general problem is that I need to set a cookie for a client browser, but the value of the cookie depends on stuff that happens while rendering the response's content (stuff that happens in a Struts 1.0 Action, and after that in a Velocity template) - I know what cookie value I want to set only after going through the entire (Servlet -> Rendering of HTML) flow.

Enlighten me please. Thanks.

Community
  • 1
  • 1
bloodcell
  • 601
  • 1
  • 9
  • 23

1 Answers1

-2

Looks like nobody is ready to take this one, I will give an attempt to provide at least my view point.

Before I get to your question First, Lets look at the main tasks of the servlet filter.

  • Query the request and act accordingly.
  • Block the request-and-response pair from passing any further.
  • Modify the request headers and data. You do this by providing a customized version of the request.
  • Modify the response headers and data. You do this by providing a customized version of the response.

Source: http://docs.oracle.com/javaee/6/tutorial/doc/bnagb.html

Coming back to your question now, You could modify the response headers by customizing the response a.k.a ResponseWrapper.

Looking at your code, what you're trying to do is modifying the original response instead of modifying the custom response and which (adding cookie to original response) is not OK.

So the proper way of doing it is to add the cookie in your custom something like the below sample.

   private class CustomResponseWrapper extends HttpServletResponseWrapper {

        private Collection<Cookie> myCookies = new ArrayList<Cookie>();

        public CustomResponseWrapper(HttpServletResponse response) {
            super(response);
        }

        @Override
        public void addCookie(Cookie cookie) {
            super.addCookie(cookie);
            myCookies.add(cookie);
        }
    }
Ram G
  • 4,829
  • 1
  • 16
  • 26
  • Thanks for the heads-ups, however I am not trying to capture the cookies created by the rest of the filter chain, if that's the thought behind the above code (I manufacture a single cookie after the filter's .doChain() invocation, and just want to make sure it gets to client). How can I prevent the rest of the filter chain from flushing \ closing the response, so that I can add the cookie? – bloodcell Sep 01 '12 at 12:12
  • also - I'm thinking adding the cookie to the original response or to the wrapping response is the same, since a call to the wrapping response's .addCookie() defaults to calling through to the original response's .addCookie() – bloodcell Sep 01 '12 at 12:17