users@jersey.java.net

Re: [Jersey] [jersey] How can I override ContainerResponse's write() method?

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 09 Mar 2009 16:25:22 +0100

On Mar 6, 2009, at 3:26 AM, John Huang wrote:

> The reason I want to override the ContainerResponse's write() method
> is if the request to the resource is included by our existing web
> app framework, we don't want to commit anything to the outputstream,
> since doing it will throw the "response already committed" exception.
>
> I tried creating a ContainerResponseFilter, and return a sub class
> of ContainerResponse in filter(...) method, but since
> ContainerResponse doesn't have defaut constructor, I couldn't extend
> it.
>

That is a bug, could you log an issue?


> What should be the right way to do it?
>

Another way you could so this is in your ContainerResponseFilter is to
set the ContainerResponseWriter. At the end of the email i have
attached the code of the GZIP filter that uses ContainerResponseWriter.

It will allow you to utilize a "dummy" output stream.

I am not sure if this is what you really require, for example, you may
not require that an entity is serialized.

How is the existing web app framework processing the response? is that
inside an existing resource method? in such cases what is being
returned, and why is anything being returned in such cases?

Perhaps if i understand better the relationship between Jersey and
your existing web app framework i might be able to propose a better
solution.

Paul.

public class GZIPContentEncodingFilter implements
ContainerRequestFilter, ContainerResponseFilter {

     public ContainerRequest filter(ContainerRequest request) {
         if
(request
.getRequestHeaders().containsKey(HttpHeaders.CONTENT_ENCODING)) {
             if
(request
.getRequestHeaders
().getFirst(HttpHeaders.CONTENT_ENCODING).trim().equals("gzip")) {
                  
request.getRequestHeaders().remove(HttpHeaders.CONTENT_ENCODING);
                 try {
                     request.setEntityInputStream(
                             new
GZIPInputStream(request.getEntityInputStream()));
                 } catch (IOException ex) {
                     throw new ContainerException(ex);
                 }
             }
         }
         return request;
     }

     private static final class Adapter implements
ContainerResponseWriter {
         private final ContainerResponseWriter crw;

         private GZIPOutputStream gos;

         Adapter(ContainerResponseWriter crw) {
             this.crw = crw;
         }

         public OutputStream writeStatusAndHeaders(long contentLength,
ContainerResponse response) throws IOException {
            gos = new GZIPOutputStream(crw.writeStatusAndHeaders(-1,
response));
            return gos;
         }

         public void finish() throws IOException {
             gos.finish();
         }
     }

     public ContainerResponse filter(ContainerRequest request,
ContainerResponse response) {
         if (response.getEntity() != null &&
                  
request.getRequestHeaders().containsKey(HttpHeaders.ACCEPT_ENCODING) &&
                 !
response.getHttpHeaders().containsKey(HttpHeaders.CONTENT_ENCODING)) {
             if
(request
.getRequestHeaders
().getFirst(HttpHeaders.ACCEPT_ENCODING).contains("gzip")) {
                  
response.getHttpHeaders().add(HttpHeaders.CONTENT_ENCODING, "gzip");
                 response.setContainerResponseWriter(
                         new
Adapter(response.getContainerResponseWriter()));
             }
         }
         return response;
     }
}