4

This may be a little confusing but I having some trouble. My goal is to take an input HTML document and then process that document and use the HTML data to output a image document. For example, a user will request a URL, with some action=png in the querystring and then the filter will get invoked for the URL and output image document.

I have tried everything but in my environment (Websphere), I am only able to output of one type. If the input type is text/html then I can only output a text document, I can't seem to output a binary document. Why? Because I get an illegal state exception each time.

[1/29/09 17:59:57:576 EST] 00000020 SystemErr R java.lang.IllegalStateException: SRVE0209E: Writer already obtained [1/29/09 17:59:57:576 EST] 00000020 SystemErr R at com.ibm.ws.webcontainer.srt.SRTServletResponse.getOutputStream(SRTServletResponse.java:505)

I am using pseudo code not to reveal all of my code:

<filter>
    <filter-name>TestFilter</filter-name>
    <filter-class>
        com.util.TestFilter
    </filter-class>
</filter>

<filter-mapping>
    <filter-name>TestFilter</filter-name>
    <url-pattern>/index_test2.html</url-pattern>
</filter-mapping>

The Wrapper Class code is essentially this:

public class ContentCaptureServletResponse extends HttpServletResponseWrapper { 
    private ByteArrayOutputStream contentBuffer;
    private PrintWriter writer; 
    public PrintWriter getWriter() throws IOException {
        if (writer == null) {
            contentBuffer = new ByteArrayOutputStream();
            writer = new PrintWriter(contentBuffer);
        }       
        return writer;
    }   
    public String getContent(){
        try {
            writer = getWriter();
        } catch (IOException e) {           
            e.printStackTrace();
        }
        writer.flush();
        String xhtmlContent = new String(contentBuffer.toByteArray());                 
        System.out.println(xhtmlContent);                
        return xhtmlContent; 
    }
}

And the filter code is this:

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        final String renderType = request.getParameter("R"); 
        final String renderClassName = request.getParameter("C");
        if ((renderType != null) && (renderClassName != null)) {
            try {
                this.setFilterChain(filterChain);
                response.setContentType("image/png");
                PrintWriter out = response.getWriter();                             
                // I call getWriter but not BOTH!
                //response.getOutputStream();               
                response.getWriter();

                // Build up the HTML document into a string.
                    CaptureResponse capContent = new CaptureResponse(response);            
                this.mainFilterChain.doFilter(req, );
                String myString = capHtmlContent.getContent();

                // What I really want to do here is output an output stream
                // so I can write a binary image
                processStr(myString);
                response.getOutputStream();             
                response.write(binaryimage)

            } catch (Exception e) {            
                e.printStackTrace();
            }
            // No data will be output to the user.
        } else {
            filterChain.doFilter(request, response);
        }  // End of if-else        
    } // End of the method.

The code works if I want to take some input html text document. I am assuming because of the open printwriter stream. But I am having trouble going to a different format. Basically, because I can't call response.getOutputStream()

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Berlin Brown
  • 11,504
  • 37
  • 135
  • 203
  • I think I might have figured it out. I can use 'response.getOutputstream'. But I had code where the browser would not rebuild the page so it looked like I was a getting a zero response. Basically, my approach will work. – Berlin Brown Jan 30 '09 at 00:02
  • Can you explain why you need to use response.getWriter()? – Zach Scrivena Jan 30 '09 at 00:07
  • Actually, I may be a little lost. It looks like this may be a bug with Websphere 6.1/RAD7. On response.getWriter(), I thought I needed it because when I use it, the code worked properly. – Berlin Brown Jan 30 '09 at 00:49
  • Why are you calling getWriter twice. Just call getOutputStream and once. – Adeel Ansari Jan 30 '09 at 02:32
  • "My goal is to take an input HTML document and then process that document and use the HTML data to output a image document." -- So you mean you want to produce a picture of a web page? Or process the contents of the HTML in some other way to make the image? Or is the description wrong? – Marcus Downing Jan 30 '09 at 03:25

2 Answers2

4

The issue does appear to be that you are opening the response Writer prior to wrapping the response.

It looks like you should be able to do:

this.setFilterChain(filterChain);
CaptureContent capContent = new CaptureResponse(response);
doFilter()
process();
response.setContentType("image/png");
response.getOutputStream().write(imagedata);

You definitely cannot safely open both the Writer and the OutputStream

Joshua DeWald
  • 3,079
  • 20
  • 16
  • Yea, I tried that. And that is what I tought. But for some reason with Websphere, for things to work properly, I had to 'open the print writer' before calling chain.doFilter(wrapper). I guess a print writer needs to be open to join the html content. I ended up using a session attr and redirect. – Berlin Brown Feb 03 '09 at 00:01
  • Because I wouldn't 'collect/join' the html content within the same request. So I just forwarded to a simple servlet which in turn output the binary file. it is strange, but it worked. – Berlin Brown Feb 03 '09 at 00:02
0

I have no experience with Websphere, but one common problem is that you try to manipulate the HTTP header after you already committed to sending the body -- once the webserver started to deliver the content, you cannot update the headers any more since they've already been sent.

Maybe you need to review your documentation and examples. For example, I don't see why you call response.get*() without actually looking at the result. Are you sure this is necessary or is this because you trimmed your code?

Cheers, Volker

Volker Stolz
  • 7,274
  • 1
  • 32
  • 50