Results 1 to 5 of 5
  1. #1
    sumved.shami is offline Member
    Join Date
    Aug 2009
    Posts
    1
    Rep Power
    0

    Default How to get content from HttpServletResponse

    Hi All

    I have written a filter on top of a Servlet. After doFilter() method, I want to get the content from the response object and save it inside cache. The content in the response is set by PrintWriter.println(xmlContent).

    Here is the code snippet:

    Java Code:
    public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain)
                throws IOException, ServletException {
     
            if (debug) {
                log("ServletContainerFilter:doFilter()");
            }
     
            RequestWrapper wrappedRequest = new RequestWrapper((HttpServletRequest) request);
            ResponseWrapper wrappedResponse = new ResponseWrapper((HttpServletResponse) response);
     
            if (!doBeforeProcessing(wrappedRequest, wrappedResponse)) {
                Throwable problem = null;
     
                try {
                    
                    chain.doFilter(wrappedRequest, wrappedResponse);
                    doAfterProcessing(wrappedRequest, wrappedResponse);
                } catch (Throwable t) {
                    // If an exception is thrown somewhere down the filter chain,
                    // we still want to execute our after processing, and then
                    // rethrow the problem after that.
                    problem = t;
                    t.printStackTrace();
                    // If there was a problem, we want to rethrow it if it is
                    // a known type, otherwise log it.
                    if (problem != null) {
                        if (problem instanceof ServletException) {
                            throw (ServletException) problem;
                        }
                        if (problem instanceof IOException) {
                            throw (IOException) problem;
                        }
                        sendProcessingError(problem, response);
                    }
                }
            }
            return;
        }
     
        private void doAfterProcessing(HttpServletRequestWrapper request, HttpServletResponseWrapper response)
                throws IOException, ServletException {
            if (debug) {
                log("ServletContainerFilter:DoAfterProcessing");
            }
            CacheManager cacheManager = CacheManager.getInstance();
            String xmlContent = response.getContent();
            
            System.out.println("XML Content just before saving in cache:\n" + xmlContent);
            cacheManager.save(getAbsoluteUrl(request), xmlContent);
        }
    Please look at this line in the code snippet:
    String xmlContent = response.getContent();

    Right now, getContent() method is not available in HttpServletResponseWrapper class. But, I want a work around for this.

    Thanks for showing your interest in this post.

    Regards,
    Sumved Shami

  2. #2
    travishein's Avatar
    travishein is offline Senior Member
    Join Date
    Sep 2009
    Location
    Canada
    Posts
    684
    Rep Power
    5

    Default

    Right, because the response will want to write things to its output stream as the stuff happens, the default HttpServletResponseWrapper doesn't do this. What I usually do for these situations is create my own response wrapper that extends the HttpServletResponseWrapper. and override the getOutputStream (and getWriter()) methods, where they instead write to my own output stream in the filter. And after a while, I made this generic one that is reuseable couple of classes.


    Java Code:
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.lang.reflect.Constructor;
    
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;
    
    
    /**
     * A response wrapper to be used when we want our own custom servlet output stream.
     *
     */
    public class OutputStreamResponseWrapper extends HttpServletResponseWrapper {
      protected HttpServletResponse origResponse = null;
      protected OutputStream realOutputStream = null;
      protected ServletOutputStream stream = null;
      protected PrintWriter writer = null;
    
      Class<? extends OutputStream> outputStreamClass;
      
      public OutputStreamResponseWrapper(HttpServletResponse response, 
          Class<? extends OutputStream> outputStreamClass) {
        super(response);
        origResponse = response;
        this.outputStreamClass = outputStreamClass;
      }
    
      public ServletOutputStream createOutputStream() throws IOException {
        try {
          Constructor<?> c = outputStreamClass.getConstructor(new Class[] {HttpServletResponse.class});
          realOutputStream = (OutputStream) c.newInstance(origResponse);
          return new ServletOutputStreamWrapper(realOutputStream);
        }
        catch (Exception ex) {
          throw new IOException("Unable to construct servlet output stream: " + ex.getMessage(), ex);
        }
      }
    
      public void finishResponse() {
        try {
          if (writer != null) {
            writer.close();
          } else {
            if (stream != null) {
              stream.close();
            }
          }
        } catch (IOException e) {}
      }
    
      @Override
      public void flushBuffer() throws IOException {
        stream.flush();
      }
    
      @Override
      public ServletOutputStream getOutputStream() throws IOException {
        if (writer != null) {
          throw new IllegalStateException("getOutputStream() has already been called!");
        }
    
        if (stream == null) {
          stream = createOutputStream();
        }
        return stream;
      }
    
      @Override
      public PrintWriter getWriter() throws IOException {
        if (writer != null) {
          return (writer);
        }
    
        if (stream != null) {
          throw new IllegalStateException("getOutputStream() has already been called!");
        }
    
       stream = createOutputStream();
       writer = new PrintWriter(new OutputStreamWriter(stream, "UTF-8"));
       return (writer);
      }
    
      @Override
      public void setContentLength(int length) {}
    
      /**
       * Gets the underlying instance of the output stream.
       * @return
       */
      public OutputStream getRealOutputStream() {
        return realOutputStream;
      }
    }
    Where I needed to wrap the ServletOutputStream (its an abstract class in servlet api),, in order to allow me to pass in any arbitrary OutputStream kind of class.

    Java Code:
    import java.io.IOException;
    import java.io.OutputStream;
    
    import javax.servlet.ServletOutputStream;
    
    /**
     * A wrapper to provide a concrete implementation of the servlet output stream, so we can wrap other streams.
     * Such as in a filter wrapping a servlet response.
     * @author thein
     *
     */
    public class ServletOutputStreamWrapper extends ServletOutputStream {
    
      OutputStream _out;
      boolean closed = false;
      
      public ServletOutputStreamWrapper(OutputStream realStream) {
        this._out = realStream;
      }
      
      @Override
      public void close() throws IOException {
        if (closed) {
          throw new IOException("This output stream has already been closed");
        }
        _out.flush();
        _out.close();
    
        closed = true;
      }
    
      @Override
      public void flush() throws IOException {
        if (closed) {
          throw new IOException("Cannot flush a closed output stream");
        }
        _out.flush();
      }
    
      @Override
      public void write(int b) throws IOException {
        if (closed) {
          throw new IOException("Cannot write to a closed output stream");
        }
        _out.write((byte) b);
      }
    
      @Override
      public void write(byte b[]) throws IOException {
        write(b, 0, b.length);
      }
    
      @Override
      public void write(byte b[], int off, int len) throws IOException {
        // System.out.println("writing...");
        if (closed) {
          throw new IOException("Cannot write to a closed output stream");
        }
        _out.write(b, off, len);
      }
      
    }
    So in your case, you would invoke this with something like :

    Java Code:
    public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain)
                throws IOException, ServletException {
     
      OutputStreamResponseWrapper wrappedResponse = new OutputStreamResponseWrapper((HttpServletResponse) response, ByteArrayOutputStream.class);
            
                    chain.doFilter(request, wrappedResponse);
    
                    ByteArrayOutputStream baos = (ByteArrayOutputStream) wrappedResponse.getRealOutputStream();
                    // and make use of this
                    String content = baos.toString();
    where here I just used a ByteArrayOutputStream as the buffer to capture the stuff the servlet generated.
    Note this only really works if the content generated from the servlet is relatively small.

    and because the filter here has intercepted the entire output from the servlet it, we need to write the content (or the eventual modified by this filter post processing content) - out to the original response output stream right.
    Last edited by travishein; 09-27-2009 at 04:24 AM.

  3. #3
    abe
    abe is offline Member
    Join Date
    Feb 2010
    Posts
    1
    Rep Power
    0

    Default

    thx for this solution, but I have a problem with that code:

    ByteArrayOutputStream has no construcotor for HttpServletResponse or ServletOutputStream

    Java Code:
    new ByteArrayOutputStream(os); // is not working

  4. #4
    spyhunter is offline Member
    Join Date
    Aug 2011
    Posts
    1
    Rep Power
    0

    Default It's not working for me...

    Throws an exception from
    java.io.IOException: Unable to construct servlet output stream: java.io.ByteArrayOutputStream.<init>(javax.servlet .http.HttpServletResponse)
    followed by
    Caused by: java.lang.NoSuchMethodException: java.io.ByteArrayOutputStream.<init>(javax.servlet .http.HttpServletResponse)
    at java.lang.Class.getConstructor0(Class.java:2706)
    at java.lang.Class.getConstructor(Class.java:1657)
    at mynamespace.OutputStreamResponseWrapper.createOutp utStream(OutputStreamResponseWrapper.java:42)

  5. #5
    f1gh is offline Member
    Join Date
    Nov 2010
    Posts
    46
    Rep Power
    0

    Default Re: How to get content from HttpServletResponse

    Quote Originally Posted by abe View Post
    thx for this solution, but I have a problem with that code:

    ByteArrayOutputStream has no construcotor for HttpServletResponse or ServletOutputStream

    Java Code:
    new ByteArrayOutputStream(os); // is not working
    If i understand correctly, objective is not to send a HttpServletResponse or ServletOutputStream but a generic OutputStream to the constructor for your implementation of the HttpServletResponseWrapper. I could be wrong, but that is how i followed the reply to OP's post from TravisHein.

    Thanks.

Similar Threads

  1. Replies: 2
    Last Post: 05-30-2009, 10:42 AM
  2. Can not see the content of the url
    By neeraj.singh in forum Java 2D
    Replies: 0
    Last Post: 02-17-2009, 01:44 PM
  3. help with button content
    By yahyaaa in forum New To Java
    Replies: 4
    Last Post: 09-20-2008, 10:53 PM
  4. Two content panes in one GUI?
    By Leprechaun in forum New To Java
    Replies: 1
    Last Post: 01-31-2008, 04:02 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •