users@jersey.java.net

Getting at the bytes of a response

From: Brian Gilstrap <brian_at_ociweb.com>
Date: Mon, 25 Jan 2010 22:26:35 -0600

Hello,

I'm attempting to implement ETags using a ContainerRequestFilter and a ContainerResponseFilter. At first, all seemed to be well, with code like this for the response filter:

public class EtagContainerResponseFilter extends Caching implements ContainerResponseFilter {
    public ContainerResponse filter(final ContainerRequest request, final ContainerResponse response) {
        // We only cache an ETag if the response is 200
        if (response.getStatus() == 200) {
            URI requestURI = request.getRequestUri();
            String uriString = requestURI.toString();
            MultivaluedMap<String, Object> httpHeaders = response.getHttpHeaders();
            MediaType contentType = (MediaType) httpHeaders.getFirst(CONTENT_TYPE);

            Object responseEntity = response.getEntity();
            if (responseEntity instanceof Serializable) {
                Serializable entity = (Serializable) response.getEntity();
                // calculate and cache the etag for this response entity
            }
            else {
                // TODO - logging
                System.err.println( "Not caching '" + requestURI.toString() + "' - not serializable..." );
            }
        }
        return response;
    }
}

But I am using mappers for things like a List<Foo>. I was surprised that the responseEntity is a List<Foo> in the response. This poses a problem since my Foo class is not Serializable.

I could, of course, demand that all things inside lists and such be serializable. But I suspect that is error-prone (what happens when object serialization changes but the way that object is rendered into the specified media type doesn't change, for example). Plus, it means I have to force the rest of my code to make my model objects (Foo objects in this case) Serializable when they otherwise wouldn't need to be so.

What I would really like to be able to do is to get ahold of the bytes written out (or getting ready to be written out) and use that to calculate my ETag. I'm hoping I've taken the wrong approach and you can point me at a fairly simple way to do this.

Thanks!
Brian