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.

Tuesday, January 7, 2014

Master Java's close() method

I have been developing a Java EE Web application recently and I have used combination of java.io.InputStream and java.io.OutputStream classes. I had some problems with its close() method, so I did a little research and I found out some interesting things. Let's check them out.
There are also two family classes for working with characters - java.io.Reader and java.io.Writer. All this classes implement one common method (already mentioned) called public void close() throws IOException, which is real piece of art and nightmare, because it must be called to free resources, but it also throws checked IOException, so it requires additional handling. So if you do everything by book this masterpiece would come out:
public static void main(String[] args)
{
    String fileLocation = "/docs/README.txt";
    FileInputStream fis = null;
    
    try
    {
      fis = new FileInputStream(fileLocation);
      
      int read = 0;
      byte[] buffer = new byte[8192];
      
      while((read = fis.read(buffer)) > -1)
      {
        System.out.print(new String(buffer, 0, read));
      }
    }
    
    catch(IOException e)
    {
      Logger.getGlobal().log(Level.SEVERE, "Failed to read file at: " + fileLocation, e);
    }
    
    finally
    {
      try
      {
        if (fis != null)
        {
          fis.close();
        }
      }
      
      catch(IOException e)
      {
        Logger.getGlobal().log(Level.SEVERE, "Failed to close stream reading file at: " + fileLocation, e);
      }
    }
  }
I think it is quite obvious why I call it masterpiece - there is more error handling code than logic. Furthermore imagine the amount of code, if there would be an OutputStream object.
The same problem is with java.sql classes, such as java.sql.Connection, java.sql.PreparedStatement,… So what can we do? Well as research shows, it depends on the version of Java you are running.

JavaSe 7


JavaSe7 introduced java.lang.AutoClosable interface which is implemented by all streaming java.io classes and java.sql classes. The documentation states: Closes this resource, relinquishing any underlying resources. This method is invoked automatically on objects managed by the try-with-resources statement. Nice so the correct code then is:
  public static void main(String[] args)
  {
    String fileLocation = "/docs/README.txt";
    
    try(FileInputStream fis = new FileInputStream(fileLocation);)
    { 
      int read = 0;
      byte[] buffer = new byte[8192];
      
      while((read = fis.read(buffer)) > -1)
      {
        System.out.print(new String(buffer, 0, read));
      }
    }
    
    catch(IOException e)
    {
      Logger.getGlobal().log(Level.SEVERE, "Failed to read file at: " + fileLocation, e);
    }
  } 
Fancy isn't it? Yes it is, but WARNING: if you use this JavaSe7 feature set your project's Source/binary format in IDE to JDK7. Without this, this code may be run on lower versions of Java and wonderful bug is created. Again note, you can use this feature for java.sql classes too.
Update: on 22.06.2014 I noticed a small but important mistake in the example above: a FileInputStream instance (fis) was not inside brackets at try keyword. If you want to use try-with-resources then all AutoClosable instances must be inside brackets at try keyword, as is now correctly displayed in the example above.

JavaSe 5 and JavaSe6


Java 5 and 6 java.io streaming classes implement java.io.Closeable interface. There are two solutions available: an Apache Commons IO library or implementation of custom solution.
The Apache Commons IO library has IOUtils class which has numerous closeQuietly methods implemented - implementation of them is quite simple:
public static void closeQuietly(final OutputStream output)
{
  closeQuietly((Closeable)output);
}

public static void closeQuietly(final Closeable closeable) 
{
  try 
  {
    if (closeable != null)
    {
      closeable.close();
    }
  } 

  catch (final IOException joe)
  {
    // ignore
   }    
  }
}
The Commons IO library is really a handy tool, but there is something to be considered - the catch statement is empty - this bad practice is also known as exception swallowing - well in the presented scenario there is really not much that can be done, but I would at least attach a Logger on the finest/trace level.
I have used many APIs which take InputStream and produce something in the OutputStream. In some cases there was also a need to redirect OutputStream to InputStream via PipedInputStream PipedOutputStream combo - so four closeQuietly calls - no thank you. This is a feature I miss in Apache's library. So let's try to make something for us, lazy developers.
// Package
package ioutils;

// Imported classes
import java.io.Closeable;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * An utility class for working with java.io
 * @author Leon Dobnik
 */
public abstract class IoUtils
{
  /**
   * Closes any java.io.* object which implements java.io.Closeable interface
   * @param closeable closeable object to close
   * @see java.io.Closeable
   */
  public static void closeQuietly(final Closeable closeable)
  {
    if (closeable != null)
    {
      try
      {
        closeable.close();
      }
      
      catch(IOException e)
      {
        Logger.global.log(Level.FINEST, "Failed to close Closeable " + closeable.getClass().getCanonicalName(), e);
      }
    }
  }
  
  /**
   * Closes multiple java.io.* objects that implement java.io.Closeable interface
   * @param closeables to close 
   * @see java.io.Closeable
   */
  public static void closeQuietly(Closeable... closeables)
  {
    for (Closeable closeable : closeables)
    {
      closeQuietly(closeable);
    }
  }
}

 public static void main(String[] args)
  {
    
    String fileLocation = "C:\\source.file";
    String fileDestination = "C:\\destination.file";
    
    FileInputStream fis = null;
    FileOutputStream fos = null;
            
    try
    {
      fis = new FileInputStream(fileLocation);
      fos = new FileOutputStream(fileDestination);
      
      int read = 0;
      byte[] buffer = new byte[8192];
      
      while((read = fis.read(buffer)) > -1)
      {
        fos.write(buffer, 0, read);
      }
      
      fos.flush();
    }
    
    catch(IOException e)
    {
      Logger.global.log(Level.SEVERE, "Failed to read file at: " + fileLocation, e);
    }
    
    IoUtils.closeQuietly(fis, fos); // Nice and shiny close :)
  }
So to make your own IoUtils class you need to implement just one method - closeQuietly(Closeable closeable). If you want to pass an unlimited number of parameters in single call, add an overloaded method  with Cloneable… cloneable parameter. The demonstration function copies one file into another (Note: I know that there are Buffered* Stream classes, but that's not the point of this post).
Unfortunately the Closeable interface in available only for java.io classes, so for java.sql classes you need to write custom closeQuietly methods for each class (java.io.Connection, java.io.Statement, …)

Java Se 1.4 


Well if you still use this ancient relic of the past, ready yourself for the implementation marathon - there is no Closeable interface - so for every class that is to be closed quietly a method called closeQuietly must be implemented (of course you can name it fancyClose or helloKittyClose if you want) - one for InputStream, one for OutputStream and so on.
There is also no ClassType… parameterName feature - but that does not mean that this ancient relic cannot handle features of JavaSe5 and JavaSe6. It can, but solution and use is not so elegant.
// Package
package ioutils;

// Imported classes
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.logging.Logger;

/**
 * An utility class for working with java.io
 * @author Leon Dobnik
 */
public abstract class IoUtils
{
  /**
   * Closes java.io.InputStream without throwing exception
   * @param is stream to close
   * @see java.io.InputStream
   */
  public static void closeQuietly(final InputStream is)
  {
    internalCloseQuietly((Object)is);
  }
  
  /**
   * Closes java.io.OutputStream without throwing exception
   * @param os stream to close
   */
  public static void closeQuietly(final OutputStream os)
  {
    internalCloseQuietly((Object)os);
  }
  
  /**
   * Invokes close() method on some java object
   * @param o instance of which close() method may be invoked
   */
  private static void internalCloseQuietly(final Object o)
  {
    if (o != null)
    {
      try
      {
        Method closeMethod = o.getClass().getMethod("close", null);
        
        if (closeMethod != null)
        {
          closeMethod.invoke(o, null);
        }
      }
      
      catch(Exception e) // In real world, catch specific exceptions...
      {
        Logger.global.finest("Failed to call close() method on: " + o.getClass().getName());
      }  
    }  
  }      
  
  /**
   * Closes quietly multiple objects that implement close() method. If object does
   * not have close() method it will be ignored.
   * @param objects 
   */
  public static void closeQuielty(final Object[] objects)
  {
    if (objects != null)
    {  
      for (int i = 0; i < objects.length; i++)
      {
        internalCloseQuietly(objects[i]);
      }
    }  
  }
}
  public static void main(String[] args)
  {
    
    String fileLocation = "C:\\fileSource.txt";
    String fileDestination = "C:\\fileDestination.txt";
    
    FileInputStream fis = null;
    FileOutputStream fos = null;
            
    try
    {
      fis = new FileInputStream(fileLocation);
      fos = new FileOutputStream(fileDestination);
      
      int read = 0;
      byte[] buffer = new byte[8192];
      
      while((read = fis.read(buffer)) > -1)
      {
        fos.write(buffer, 0, read);
      }
      
      fos.flush();
    }
    
    catch(IOException e)
    {
      Logger.global.log(Level.SEVERE, "Failed to read file at: " + fileLocation, e);
    }
    
    IoUtils.closeQuielty(new Object[]{fis, fos}); // Nice and shiny close :)
  }
So in case of this relic a solution is to use Reflection API for invoking close() method on objects and writing public wrapper methods for supported types. The method closeQuietly(final Object[] objects) is an option if you want to close multiple objects in one call, but it is your decision if it meets coding standards of your organisation.

Any comments are welcome.