Solved

JAVA Filter and GZIPOutputStream

Posted on 2010-11-19
35
910 Views
Last Modified: 2012-05-10
I have found a jar file that is very useful to compress the html data before sending it to the client. In this way the reponse time can be significantly improve.

The jar file  and the explanation can be found at:
http://onjava.com/pub/a/onjava/2003/11/19/filters.html?page=1

I am trying to understand what is going on in GZIPFilter.java, GZIPResponseWrapper.java and GZIPResponseStream.java.

Here is an extract from GZIPFilter.java:

GZIPResponseWrapper gzipresponsewrapper = new GZIPResponseWrapper(httpservletresponse);
filterchain.doFilter(servletrequest, gzipresponsewrapper);
gzipresponsewrapper.finishResponse();

Open in new window


I would like to understand how and who is calling all the methods and in what sequence in the following classes: GZIPResponseWrapper.java and GZIPResponseStream.java.

Code for GZIPResponseWrapper.java

 

package com.jspbook;

import java.io.*;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

 
public class GZIPResponseWrapper extends HttpServletResponseWrapper
{

    public GZIPResponseWrapper(HttpServletResponse httpservletresponse)
    {
        super(httpservletresponse);
        origResponse = null;
        stream = null;
        writer = null;
        origResponse = httpservletresponse;
    }

    public ServletOutputStream createOutputStream()
        throws IOException
    {
        return new GZIPResponseStream(origResponse);
    }

    public void finishResponse()
    {
        try
        {
            if(writer != null)
                writer.close();
            else
            if(stream != null)
                stream.close();
        }
        catch(IOException ioexception) { }
    }

    public void flushBuffer()
        throws IOException
    {
        stream.flush();
    }

    public ServletOutputStream getOutputStream()
        throws IOException
    {
        if(writer != null)
            throw new IllegalStateException("getWriter() has already been called!");
        if(stream == null)
            stream = createOutputStream();
        return stream;
    }

    public PrintWriter getWriter()
        throws IOException
    {
        if(writer != null)
            return writer;
        if(stream != null)
        {
            throw new IllegalStateException("getOutputStream() has already been called!");
        } else
        {
            stream = createOutputStream();
            writer = new PrintWriter(new OutputStreamWriter(stream, "UTF-8"));
            return writer;
        }
    }

    public void setContentLength(int i)
    {
    }

    protected HttpServletResponse origResponse;
    protected ServletOutputStream stream;
    protected PrintWriter writer;
}

Open in new window


code for GZIPResponseStream.java

 
package com.jspbook;

import java.io.*;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

public class GZIPResponseStream extends ServletOutputStream
{

    public GZIPResponseStream(HttpServletResponse httpservletresponse)
        throws IOException
    {
        baos = null;
        gzipstream = null;
        closed = false;
        response = null;
        output = null;
        closed = false;
        response = httpservletresponse;
        output = httpservletresponse.getOutputStream();
        baos = new ByteArrayOutputStream();
        gzipstream = new GZIPOutputStream(baos);
    }

    public void close()
        throws IOException
    {
        if(closed)
        {
            throw new IOException("This output stream has already been closed");
        } else
        {
            gzipstream.finish();
            byte abyte0[] = baos.toByteArray();
            response.addHeader("Content-Length", Integer.toString(abyte0.length));
            response.addHeader("Content-Encoding", "gzip");
            output.write(abyte0);
            output.flush();
            output.close();
            closed = true;
            return;
        }
    }

    public void flush()
        throws IOException
    {
        if(closed)
        {
            throw new IOException("Cannot flush a closed output stream");
        } else
        {
            gzipstream.flush();
            return;
        }
    }

    public void write(int i)
        throws IOException
    {
        if(closed)
        {
            throw new IOException("Cannot write to a closed output stream");
        } else
        {
            gzipstream.write((byte)i);
            return;
        }
    }

    public void write(byte abyte0[])
        throws IOException
    {
        write(abyte0, 0, abyte0.length);
    }

    public void write(byte abyte0[], int i, int j)
        throws IOException
    {
        if(closed)
        {
            throw new IOException("Cannot write to a closed output stream");
        } else
        {
            gzipstream.write(abyte0, i, j);
            return;
        }
    }

    public boolean closed()
    {
        return closed;
    }

    public void reset()
    {
    }

    protected ByteArrayOutputStream baos;
    protected GZIPOutputStream gzipstream;
    protected boolean closed;
    protected HttpServletResponse response;
    protected ServletOutputStream output;
}

Open in new window


0
Comment
Question by:javaCaravan0
  • 17
  • 17
35 Comments
 
LVL 27

Expert Comment

by:rrz
ID: 34174225
The Servlet container(Tomcat?)  sees the Filter registered in the web app's web.xml file.  When it receives a request that matches a url pattern listed it calls the doFilter method of the Filter.
public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain)

Open in new window

   The wrapper is created. The wrapper is subsistuted for the original response object.
filterchain.doFilter(servletrequest, gzipresponsewrapper);

Open in new window

 
If there are any other Filters mapped to the requested url pattern, then they are called. The requested JSP or Servlet is executed and the wrapped response is sent to the client.  Finally the control returns to the Filter. To clean up.
gzipresponsewrapper.finishResponse();

Open in new window

0
 

Author Comment

by:javaCaravan0
ID: 34174384
........ The wrapper is created. The wrapper is subsistuted for the original response object.

Thanks for the reply. Please explaine the following:

following line is instantiating the GZIPResponseWrapper class.

GZIPResponseWrapper gzipresponsewrapper = new GZIPResponseWrapper(httpservletresponse);
 
I would like to understand how and who is calling all the methods and in what sequence in the following classes: GZIPResponseWrapper.java and GZIPResponseStream.java.



 
 
0
 
LVL 27

Expert Comment

by:rrz
ID: 34174391
I think I got that last part wrong. According to figure 1  at
http://www.ibm.com/developerworks/java/library/j-tomcat2/  
I should have posted
If there are any other Filters mapped to the requested url pattern, then they are called. The requested JSP or Servlet is executed and the response is wrapped.  The control returns to the Filter to clean up. Finally the response is sent to the client.
0
 

Author Comment

by:javaCaravan0
ID: 34174638
rrz@871311:

sorry, may be my question isn't clear.

following line is instantiating the GZIPResponseWrapper class.

GZIPResponseWrapper gzipresponsewrapper = new GZIPResponseWrapper(httpservletresponse);

I want to know how are the methods in GZIPResponseWrapper class are being executed. I see that the contructor will be executed. How are the other methods in the class are being execute e.g.
public void flushBuffer()
public ServletOutputStream getOutputStream()
public PrintWriter getWriter()
public void setContentLength(int i)

and how are the following methods in  GZIPResponseStream.java are being executed:

public void close()
public void flush()
the three overloaded methods:
public void write()
public boolean closed()
And the following lines of code:
        baos = new ByteArrayOutputStream();
baos is null, how is gzipstream getting the contents?
        gzipstream = new GZIPOutputStream(baos);
0
 
LVL 27

Expert Comment

by:rrz
ID: 34174758
GZIPResponseWrapper  extends HttpServletResponseWrapper.
HttpServletResponseWrapper  extends ServletResponseWrapper.
ServletResponseWrapper  implements ServletResponse.  
When your resource(JSP or Servlet) has some output,  it calls getWriter or print or getOutputStream or flushBuffer or whatever.
Your resource doesn't know anything about the wrapping. It is just creating a response and sending down the line.  
GZIPResponseStream extends ServletOutputStream.
ServletOutputStream  extends java.io.OutputStream.  
GZIPResponseStream has to have the write methods to be a OutputStream.
It's constructor
public GZIPResponseStream(HttpServletResponse response)  
accepts the original response.  
So, when your resource asks for a outputstream  the wrapper calls
  public ServletOutputStream createOutputStream() throws IOException {
    return (new GZIPResponseStream(origResponse));
  }  
Thus the response is gzipped without the resource even knowing about it.

0
 
LVL 27

Expert Comment

by:rrz
ID: 34174992
>And the following lines of code:
>        baos = new ByteArrayOutputStream();
>baos is null, how is gzipstream getting the contents?
>        gzipstream = new GZIPOutputStream(baos);  

baos is not null. It is empty at that point though.
When the resource asks for a outputstream it goes to the wrapper
  public ServletOutputStream createOutputStream() throws IOException {
    return (new GZIPResponseStream(origResponse));
  }

Open in new window


So the output is being written to  gzipstream.
When the container finally sends the response to the client, it calls close() on the outputstream.
public void close() throws IOException {
    if (closed) {
      throw new IOException("This output stream has already been closed");
    }
    gzipstream.finish();

    byte[] bytes = baos.toByteArray();


    response.addHeader("Content-Length", 
                       Integer.toString(bytes.length)); 
    response.addHeader("Content-Encoding", "gzip");
    output.write(bytes);
    output.flush();
    output.close();
    closed = true;
  }

Open in new window


Thus baos is put into the array "bytes" and it is written to the original output.
0
 

Author Comment

by:javaCaravan0
ID: 34175198
Thank you.

and what's about the three overloaded write methods. How are they get executed.
0
 
LVL 27

Expert Comment

by:rrz
ID: 34175275
The JSP or servlet that is creating the response calls write or print when it has output. Generally just one write method is used.
0
 
LVL 92

Expert Comment

by:objects
ID: 34177191
> I have found a jar file that is very useful to compress the html data before sending it to the client. In this way the reponse time can be significantly improve.

that would be more efficiently handled by the container
0
 

Author Comment

by:javaCaravan0
ID: 34179593


rrz@871311:

  Thank you for such a detailed explanation.

When you say:
     >> When the container finally sends the response to the client, it calls close() on the outputstream
Questions: Does the close method get called after sending the response to the client or before sending the response to the client. From the code, it seems that its called before sending the resposne to the client.  
   >> When your resource(JSP or Servlet) has some output,  it calls getWriter or print or getOutputStream or flushBuffer or whatever.

Question: Do we know which method will be called by the resource or the resource can call any of the getWriter or print or getOutputStream or flushBuffer methods. I would like to include only the ones that we needed.

   >> The JSP or servlet that is creating the response calls write or print when it has output. Generally just one write method is used.

Queston: Do I need to overload all write method on only one abstract wrtie(int b) method of ServletOutputStream.

Thank you
0
 
LVL 27

Expert Comment

by:rrz
ID: 34180219
Questions: Does the close method get called after sending the response to the client or before sending the response to the client.  
After your resource creates its output, the control goes back to the Filter. The Filter calls,
wrappedResponse.finishResponse();

Open in new window

 
in the finishResponse method, the wrapper calls  stream.close()  But stream is actually a GZIPResponseStream object. It overrides the OutputStream close method. I posted it above.  It adds the encoding header and writes "bytes"  to the actual stream and flushes it. That is when the response is sent to the client. Then the stream is closed.

Question: Do we know which method will be called by the resource or the resource can call any of the getWriter or print or getOutputStream or flushBuffer methods.  
It depends on the resource. For instance, you could write a JSP that just calls the out.print method. Or you could write a Servlet that calls the response.getWriter method and println methods.  

Queston: Do I need to overload all write method on only one abstract wrtie(int b) method of ServletOutputStream.
I think you mean override. OutputStream and ServletOutputStream are abstract classes. GZIPResponseStream is a concrete class that extends ServletOutputStream.  See  
Java Language Specification
It must implement all abstract methods in ServletOutputStream.
0
 

Author Comment

by:javaCaravan0
ID: 34184753
rrz@871311:

Thank you very much for such a great explanation.
I would like to summarize what I have understood and please correct me if my explanation has any mistakes.

1. wrapped response object is sent to the servlet
2. servlet either calls  getOutputStream() or getWriter() methods which have been overridden.
3.  getOutputStream() or getWriter()  send an output stream of type GZIP with ByteArrayOutputStream
4. Now whenever servlet wants to write a response, it calls the write method (which we have overridden),  the servlet sends the data which is stored in the byte array of the wrtie method and the wrtie method writes the data to the GZIPOutputStream which is ByteArrayOutputStream
4a. This process of writing to the  GZIPOutputStream continues till Servlet has written all the data to the stream
5. Once all the data has been written, control returns to the filter, and the filter calls finishResponse method.
5a.  finishResponse calls writer.close or stream.close (the close method has been overriden)
6. the data in ByteArrayOutputStream is transferred to the byte array and this array is then written to the original output stream.
7. output.flush() sends the data to the client and then the stream is closed.

Please correct me if I'm wrong anywhere.

You have done a great job and I think you deserve even more that 500 points.

Question:
The entire data is written to the ByteArrayOutputStream and then the same data is written to the original output stream and sent to the client.
This may cause an out of memory issue in my case because some of my JSPs generate an output upto 4 MB and I have more than 300 concurrent users. Is it possible to flush the ByteArrayOutputStream to the original output stream when it reaches to certain limit say 1 MB and the  original output stream flush it to the client but not close the stream since more data will have to come. In this way the out of memory issue can be controlled. If you think it is possible, please explain and if possible provide the code.

Thank you very much.


0
 
LVL 27

Expert Comment

by:rrz
ID: 34184972
>output upto 4 MB    
>more than 300 concurrent users.
 What happen to "objects" idea of using container handler ?

1)yes
2)yes
3)no type is GZIPResponseStream
4)
   >the servlet sends the data which is stored in the byte array of the wrtie method
   no  
   >the wrtie method writes the data to the GZIPOutputStream which is ByteArrayOutputStream
  yes, because GZIPResponseStream sent a ByteArrayOutputStream in the constructor of gzipstream  
4a)yes, but the Servlet could call flush on the output stream. This could be a problem. See below here.
5)yes
5a)yes
6)yes
7)yes

>Is it possible to flush the ByteArrayOutputStream to the original output stream when it reaches to certain limit
I don't think the code will work as written. One reason is that the encoding header is add to the response in the close method. Also I think the flush method  will have to rewritten. Look at the comments at the bottom of the page at
http://onjava.com/pub/a/onjava/2003/11/19/filters.html?page=3  
I might be getting over my head trying to rewrite this code.
If CEHJ or objects are listening, maybe they will help you. You might open another question to get their attention. Be sure to include the Java zone.  
0
 

Author Comment

by:javaCaravan0
ID: 34186774
ok. thank you.

Q1. I undersntad that getOutputStream or getWriter will provide a stream to the resource to write the compressed data to but flush means to empty the stream, what if stream is yet empty (nothing has been written to the stream), does it get called when the default bufferSize is met? When the flushBuffer is called by the resource, where do the contents flushed to by stream.flush()?

Q2. how does the flush() method get invoked and where does gzipstream.flush() send the contents?


0
 
LVL 27

Expert Comment

by:rrz
ID: 34189593
Q1)
> to the resource to write the compressed data  
The resource is writing uncompressed data. The filter calls for compression.
>does it get called when the default bufferSize is met?  
Yes, but it seems to me that the data doesn't get put into the response body buffer until  close is called on GZIPResponseStream.  
>When the flushBuffer is called by the resource, where do the contents flushed to by stream.flush()?
The resource can call flush()  but it goes to the wrapper not the real response.  
Q2) The way I see it,  gzipstream.flush() send the data to baos.  That  is the potential problem I see in this code.
The response body doesn't get flushed(or begin to be autoflushed) until the close method of GZIPResponseStream is called. That is when the byte array "bytes" is written to "output".  

I am not entirely certain about all this. You should do some testing. Or get CEHJ to look at this.
Again
 What happen to "objects" idea of using the container handler ?
0
 

Author Comment

by:javaCaravan0
ID: 34190039
I think "objects"  means to turn the compressio on , on the JBOSS server in server.xml. If this is what he means, then there are reson why I can't do that.

I have deployed the code and it is running fine but for some transactions, I am getting the garbage in browser as show below, any idea why is that?

‹í]}wÚ¸Òÿ>…Ö÷l€†`ÈÛ6 fIH“½!Éȶ{ïsOŽÁ¼56k›¤ÙÝ>Ÿý™ɯ o·IkNly$fF¿ ɪ¸n4òõ66Xž1õ…öQŸ<˽ؘûéøºëϨ2÷‚5§þÈq÷Y÷¨#ŽuŸï³_¦6gÕ=‘t5u'Ž©msèê¾éØÌw˜7qM{ˆÇ·öBͳ €×w͉Ï,ÝNõ!×”_ô;½C‰Jƒ©jtËúŽÁ±ràÇgºýÀ Ý×™ 

Open in new window

0
 
LVL 27

Expert Comment

by:rrz
ID: 34190187
I don't know why you are getting that output. You should ask objects in your other question.
http://www.experts-exchange.com/Programming/Languages/Java/J2EE/JSP/Q_26621234.html  
But its early in his day.
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 

Author Comment

by:javaCaravan0
ID: 34190368
Do I need to direct a question to him or he sees it by default.... if I have to direct my question to him, how can I do that?
0
 
LVL 27

Expert Comment

by:rrz
ID: 34190507
Just comment on that question. He should see it later today. I think he lives in Australia.
0
 

Author Comment

by:javaCaravan0
ID: 34197890
rrz@871311/objects: I really need an help from you guys in finding the root cause for the following issue:

this method sets the threshold. this value come from the web.xml. (it is all about compressing the files, the files are compressed only if the file size is more than or equal to the threshold value)

protected void setBuffer(int threshold) {
        compressionThreshold = threshold;
        buffer = new byte[compressionThreshold];
    }
    

Open in new window


Problem:
   
    if the value is 128 or 9000 it doesn't display all the pages correctly. For some pages, it open the save window prompt, some pages just throw the garbage
    but majority of the pages work.
   
    When the threshold value is set to 100000, all pages start working fine.
    I need to find the reason why its not working with 128 or 9000 but working with 100k, what is the right value for the threshold?
   
    Here are the three write methods:

   public void write(int b) throws IOException {
              
            if (closed)
                throw new IOException("Cannot write to a closed output stream");
    
            if (bufferCount >= buffer.length) {
                flushToGZip();
            }
    
            buffer[bufferCount++] = (byte) b;
    
        }
    
    
        
        public void write(byte b[]) throws IOException {
    
            write(b, 0, b.length);
    
        }
    
    
         
        public void write(byte b[], int off, int len) throws IOException {         
    
            if (closed)
                throw new IOException("Cannot write to a closed output stream");
    
            if (len == 0)
                return;
    
            // Can we write into buffer ?
            if (len <= (buffer.length - bufferCount)) {
                System.arraycopy(b, off, buffer, bufferCount, len);
                bufferCount += len;
                return;
            }
    
            // There is not enough space in buffer. Flush it ...
            flushToGZip();
    
            // ... and try again. Note, that bufferCount = 0 here !
            if (len <= (buffer.length - bufferCount)) {
                System.arraycopy(b, off, buffer, bufferCount, len);
                bufferCount += len;
                return;
            }
    
            // write direct to gzip
            writeToGZip(b, off, len);
      }

Open in new window


here is writeToGZip method

public void writeToGZip(byte b[], int off, int len) throws IOException {      
    
              if (gzipstream == null) {
                   
                  if (response.isCommitted()) {
                   
                      gzipstream = output;
                  } else {
                      response.addHeader("Content-Encoding", "gzip");
                      gzipstream = new GZIPOutputStream(output);
                  }
              }
              gzipstream.write(b, off, len);
      
    }

Open in new window


Here is the  flushToGZip() method:

    public void flushToGZip() throws IOException {           
            writeToGZip(buffer, 0, bufferCount);
            bufferCount = 0;
        }

    }

Open in new window


Here is the output when I run my application with threshold set to 9000:

Debug statement where it works for a page:

09:54:41,393 INFO  [STDOUT] @doFilter
09:54:41,394 INFO  [STDOUT] supports compression
09:54:41,394 INFO  [STDOUT] setCompressionThreshold to 9000
09:54:41,394 INFO  [STDOUT] doFilter gets called with compression
09:54:46,208 INFO  [STDOUT] setContentType to text/html
09:54:46,705 INFO  [STDOUT] createOutputStream gets called
09:54:46,705 INFO  [STDOUT] buffer is set to 9000
09:54:46,705 INFO  [STDOUT] stream is set to compressionFilters.CompressionResponseStream@7e5308 in getWriter
09:54:46,706 INFO  [STDOUT] character encoding is ISO-8859-1
09:54:46,712 INFO  [STDOUT] write, bufferCount = 0 len = 8192 off = 0
09:54:46,712 INFO  [STDOUT] write, bufferCount = 8192 len = 386 off = 0
09:54:46,712 INFO  [STDOUT] close() @ CompressionResponseStream

Debug statement where it prompt a window to save the contents instead of displaying the page:

09:54:51,701 INFO  [STDOUT] @doFilter
09:54:51,702 INFO  [STDOUT] supports compression
09:54:51,702 INFO  [STDOUT] setCompressionThreshold to 9000
09:54:51,702 INFO  [STDOUT] doFilter gets called with compression
09:54:54,340 INFO  [STDOUT] setContentType to text/html
09:54:54,392 INFO  [STDOUT] createOutputStream gets called
09:54:54,393 INFO  [STDOUT] buffer is set to 9000
09:54:54,393 INFO  [STDOUT] stream is set to compressionFilters.CompressionResponseStream@5ffb87 in getWriter
09:54:54,393 INFO  [STDOUT] character encoding is ISO-8859-1
09:54:54,393 INFO  [STDOUT] write, bufferCount = 0 len = 7366 off = 0
09:54:54,393 INFO  [STDOUT] flush() @ CompressionResponseStream
09:54:54,807 INFO  [STDOUT] setContentType to text/html
09:54:54,810 INFO  [STDOUT] setContentType to text/html
09:54:54,908 INFO  [STDOUT] write, bufferCount = 7366 len = 8192 off = 0
09:54:54,909 INFO  [STDOUT] flushToGZip() @ CompressionResponseStream
09:54:54,909 INFO  [STDOUT] flushing out to GZipStream, bufferCount = 7366
09:54:54,909 INFO  [STDOUT] writeToGZip, len = 7366
09:54:54,909 INFO  [STDOUT] new GZIPOutputStream
09:54:54,911 INFO  [STDOUT] write, bufferCount = 8192 len = 8192 off = 0
09:54:54,911 INFO  [STDOUT] flushToGZip() @ CompressionResponseStream
09:54:54,911 INFO  [STDOUT] flushing out to GZipStream, bufferCount = 8192
09:54:54,911 INFO  [STDOUT] writeToGZip, len = 8192
09:54:55,002 INFO  [STDOUT] write, bufferCount = 8192 len = 8192 off = 0
09:54:55,002 INFO  [STDOUT] flushToGZip() @ CompressionResponseStream
09:54:55,002 INFO  [STDOUT] flushing out to GZipStream, bufferCount = 8192
09:54:55,002 INFO  [STDOUT] writeToGZip, len = 8192
09:54:55,005 INFO  [STDOUT] write, bufferCount = 8192 len = 8192 off = 0
09:54:55,005 INFO  [STDOUT] flushToGZip() @ CompressionResponseStream
09:54:55,006 INFO  [STDOUT] flushing out to GZipStream, bufferCount = 8192
09:54:55,006 INFO  [STDOUT] writeToGZip, len = 8192
09:54:55,019 INFO  [STDOUT] write, bufferCount = 8192 len = 8192 off = 0
09:54:55,019 INFO  [STDOUT] flushToGZip() @ CompressionResponseStream
09:54:55,020 INFO  [STDOUT] flushing out to GZipStream, bufferCount = 8192
09:54:55,020 INFO  [STDOUT] writeToGZip, len = 8192
09:54:55,035 INFO  [STDOUT] write, bufferCount = 8192 len = 8192 off = 0
09:54:55,035 INFO  [STDOUT] flushToGZip() @ CompressionResponseStream
09:54:55,035 INFO  [STDOUT] flushing out to GZipStream, bufferCount = 8192
09:54:55,035 INFO  [STDOUT] writeToGZip, len = 8192
09:54:55,058 INFO  [STDOUT] write, bufferCount = 8192 len = 8192 off = 0
09:54:55,058 INFO  [STDOUT] flushToGZip() @ CompressionResponseStream
09:54:55,058 INFO  [STDOUT] flushing out to GZipStream, bufferCount = 8192
09:54:55,059 INFO  [STDOUT] writeToGZip, len = 8192
09:54:55,060 INFO  [STDOUT] write, bufferCount = 8192 len = 8192 off = 0
09:54:55,060 INFO  [STDOUT] flushToGZip() @ CompressionResponseStream
09:54:55,060 INFO  [STDOUT] flushing out to GZipStream, bufferCount = 8192
09:54:55,061 INFO  [STDOUT] writeToGZip, len = 8192
09:54:55,062 INFO  [STDOUT] write, bufferCount = 8192 len = 6 off = 0
09:54:55,062 INFO  [STDOUT] close() @ CompressionResponseStream
09:54:55,062 INFO  [STDOUT] flushToGZip() @ CompressionResponseStream
09:54:55,062 INFO  [STDOUT] flushing out to GZipStream, bufferCount = 8198
09:54:55,062 INFO  [STDOUT] writeToGZip, len = 8198

I'm waiting for your response. Thank you.
0
 

Author Comment

by:javaCaravan0
ID: 34198148
here is the close method:
public void close() throws IOException {
        if (closed)
            throw new IOException("This output stream has already been closed");

        if (gzipstream != null) {
            flushToGZip();
            gzipstream.close();
            gzipstream = null;
        } else {
            if (bufferCount > 0) {
                
                output.write(buffer, 0, bufferCount);
                bufferCount = 0;
            }
        }
        output.close();
        closed = true;
    }

Open in new window



09:54:46,712 INFO  [STDOUT] write, bufferCount = 0 len = 8192 off = 0

it is executing public void write(byte b[], int off, int len) method

the next line is:

09:54:46,712 INFO  [STDOUT] write, bufferCount = 8192 len = 386 off = 0

still it is executing public void write(byte b[], int off, int len) method
but in this method the following statement: if (len <= (buffer.length - bufferCount)) { is now false, so according to the code it shoud be executing
flushToGZip(); method but instead of this it execute the close() method. I don't understand why is that happening?
0
 
LVL 27

Expert Comment

by:rrz
ID: 34198527
I am having trouble following you. Are you using the code at the link in your question at the top ?
Where in the code is the  setBuffer  method ?    
0
 

Author Comment

by:javaCaravan0
ID: 34198699
this is different code. It is from Apache.

here is the setBuffer method:

    protected void setBuffer(int threshold) {
        compressionThreshold = threshold;
        buffer = new byte[compressionThreshold];
        if (debug > 1) {
            System.out.println("buffer is set to "+compressionThreshold);
        }
    }

Open in new window


I've removed the debug statements from the other code before sending it across.
0
 
LVL 27

Expert Comment

by:rrz
ID: 34198866
>this is different code. It is from Apache.  
Please give us link.  I have to look at it.
0
 

Author Comment

by:javaCaravan0
ID: 34198947
Download site: http://tomcat.apache.org/download-60.cgi

CompressionFilter.java
CompressionServletResponseWrapper.java
CompressionResponseStream.java

0
 
LVL 27

Expert Comment

by:rrz
ID: 34199237
That link takes us to Tomcat download. Are you saying the code is aprt of Tomcat ?
0
 

Author Comment

by:javaCaravan0
ID: 34199511
yes, if you download the zip file from Source Code Distributions you will find the java files there.
0
 
LVL 27

Expert Comment

by:rrz
ID: 34207278
I am trying to find time this morning. Working...
0
 

Author Comment

by:javaCaravan0
ID: 34207322
thank you rrz@871311. We decided to use this as we use Apache across our business.
You input will be great... I really want to understand the code.
0
 
LVL 27

Expert Comment

by:rrz
ID: 34209258
>I really want to understand the code  
Me too. I went around in circles with it. But I didn't seem to have problem with it.
>For some pages, it open the save window prompt, some pages just throw the garbage but majority of the pages work.    
What kind of garbage ? You mean like a encoding problem ?  
0
 

Author Comment

by:javaCaravan0
ID: 34212116

1.  Below is an abstract from my "11/23/10 08:52 AM" comments, please refer above for more details, can you explain why close() methid is executed instead of flushToGZip() ?

09:54:46,712 INFO  [STDOUT] write, bufferCount = 0 len = 8192 off = 0

it is executing public void write(byte b[], int off, int len) method

the next line is:

09:54:46,712 INFO  [STDOUT] write, bufferCount = 8192 len = 386 off = 0

still it is executing public void write(byte b[], int off, int len) method
but in this method the following statement: if (len <= (buffer.length - bufferCount)) { is now false, so according to the code it shoud be executing
flushToGZip(); method but instead of this it execute the close() method. I don't understand why is that happening?

--------------------------
2. the problem is happening when we use JBOSS 4.3, now we have tried the code with JBOSS 4.0.3 and it is working fine.

My mission is to understand the code (few places which I don't understand) and make it working for JBOSS 4.3

3. Where can I go (webSite, book etc.) which explains how the container calls the HttpServletResponse and the methods from other classes, in what sequence......
0
 
LVL 27

Expert Comment

by:rrz
ID: 34214166
>it shoud be executing flushToGZip(); method but instead of this it execute the close() method.
I am not seeing that.  I have
.
.
.
write, bufferCount = 96256 len = 2048 off = 0
write, bufferCount = 98304 len = 2048 off = 0
flushToGZip() @ CompressionResponseStream
flushing out to GZipStream, bufferCount = 98304
writeToGZip, len = 98304
write, bufferCount = 2048 len = 2048 off = 0
write, bufferCount = 4096 len = 2048 off = 0
.
.
.
.
write, bufferCount = 73728 len = 2048 off = 0
write, bufferCount = 75776 len = 1576 off = 0
close() @ CompressionResponseStream
flushToGZip() @ CompressionResponseStream
flushing out to GZipStream, bufferCount = 77352
writeToGZip, len = 77352

I see close() being called only at the end.   I not using JBOSS .  I am using Tomcat 7

2) I looked at the Java Servlet Specification. It doesn't help. So I guess it depends on each implementation.
0
 

Author Comment

by:javaCaravan0
ID: 34217990
rrz@871311:  You have helped me a lot in understanding the original code. I'll be closing this question and reward you the points.

I'll be opening an other qeustion to discuss the code from Tomcat. I think the discussion will be very interesting, you deserve separate points for that discussion.
0
 
LVL 27

Accepted Solution

by:
rrz earned 500 total points
ID: 34218804
>I'll be opening an other qeustion to discuss the code from Tomcat  
In order to get the attention of the maximum number of experts, you should add the Java and the Tomcat zones to that question.  
>you deserve separate points for that discussion.  
No, the points for this question will be fine.  
0
 

Author Comment

by:javaCaravan0
ID: 34361873
I'll close it next week.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now