Saturday, January 18, 2014

GlassFish 4.0 GZIP bug

I have been developing a web application in PrimeFaces. Due limited resources (private project) our testing server (demonstration purposes) is hosted by team member on ADSL line. As you may know the limit of ADSL line is 8 mbit for download and 0.768 mbit for upload. The PrimeFaces application is running good on our development machines, but terribly when accessed on testing GlassFish 4.0 Server from the internet - responses (monitored via Developer tools in Chrome) vary from 1 to 4 seconds, sometimes even worse. When GlassFish is accessed from LAN response time is normal - from 80 to 250 ms. I must mention that page displays only a simple form with 7 JSF p:outputLabel and p:inputText elements.
Clearly 4 seconds isn't acceptable response time for a such simple web page. So I started investigating what was causing it. I used Chrome's DeveloperTools and its Network tab where requests and responses are displayed - the data displayed there spoke for themselves: most of the response time was taken by transfer of CSS and JavaScript files. I also checked request and response headers and figured out that server is not using compression (GZIP) although browser requested it.

GZIP Compression BUG


I have logged in into the GlassFish' administration console, activated GZIP compression, restarted GlassFish and for the god sake my application's GUI felt apart. I opened Chrome's Developer Tools and saw following result:
All responses were successfully received, but there was something wrong with the JavaScript files - a bunch of errors like Uncaught Syntax Error: Unexpected identifier and Uncaught ReferenceError: $ is not defined. My first thought was "PrimeFaces is the suspect", but after deploying on second GlassFish server I found out that it must be something with GlassFish 4 and settings that I changed - compression. So I started checking what caused an error - I clicked onto the first error displayed in the upper picture and look what a mess GlassFish's compression did:
it is a jQuery question mark mania. I started googling about this issue and found the following reported bug: https://java.net/jira/browse/GLASSFISH-20726. The solution is simple: you just have to download file nucleus-grizzly-all.jar attached to the first post and copy it into the glassfish4/glassfish/modules directory, where glassfish4 is your root GlassFish4 installation directory. The link also states that this issue will be fixed in GlassFish 4.1 which is planned for summer 2014.
Let me return to our testing GlassFish 4 server on the ADSL line - enabling GZIP has given server wings. The response time now vary between 150 and 250 ms what is significant improvement. You must also take into the account that server is running on 4 or 5 years old dual core processor, Linux OS and runs MySql database. When testing on development GlassFish results responses are much butter.

Enable GZIP compression on GlassFish 4.0


If you try to GZIP already size optimised / compressed file such as MP3 / MP4 file there will achieve close to zero difference in the file size after compression. Furthermore on some files you can achieve only minor file size change - for example shrink 800 KB PDF to 720 KB. In case of web development we are mostly dealing with different types of text files (XML, JSON, CSS, JavaScript). On these files GZIP works like charm - you can compress 60 MB file into astonishing 378 KB. So in case of 60 MB file you save more than 59 MB of bandwidth - that is a really huge improvement. Especially if you are developing a mobile application where every KB counts (cellular network) GZIP compression is a must. If you want to test how much bandwidth or space you can save check this link and perhaps this to write your own Java test case.
The compression is disabled by default on GlassFish 4.0 server. I do not understand reason for a such decision, because we are in year 2014 and not at the beginning of the stone age. So enable GZIP compression by logging in into GlassFish's administration console (http://localhost:4848 by default) and navigate in the left menu: Configurations / server-config / HTTP Service / HTTP Listeners / http-listener-1 (by default GlassFish has three listeners: one for HTTP, one for HTTPS and one for administration).
Under the heading Edit HTTP Listener click on the Advanced link.
After clicking on Advanced link you can see two new tabs - HTTP and File Cache. Click on the HTTP tab.
Now you can scroll down to the label called Compression. You have dropdown list where you can select the compression method: on (meaning that compression will be used when it is requested via HTTP headers) and force (meaning that compression will be always used). I think the most appropriate setting is on, because you are still compatible with relics which does not support GZIP. Click Save and restart GlassFish4.
There are also other compression settings you might be interested: Compressible Mime Types, Compression Minimum size and No-Compression User Agents - the explanation of these settings is under input fields.
For the end as always: comments, better solutions are welcome.

1 comment: