Wednesday, October 24, 2012

Smooth moves with Swing

It's about data rendering in Swing. How to make a smooth rendering of real time data...
The secret seems to be in SwingUtilities.invokeAndWait

This browser does not support Applets.
Use the button to start or stop the applet

Above are two JPanels, displaying, on the left a speed, on the right a heading.
Both are fed by real time data (simulated in this case).
Obviously - and we will not show this code, unless anyone insists - the position of the display (namely the position of the hand) is done when the repaint() is invoked, and its implementation is done by overriding the paintComponent(Graphics) method.
The smoothing is done in a setValue(double) method.
When this method is invoked, the difference between the previous and the next values is splitted in small intervals, between which a repaint() is invoked.
All the difficulty - the problem - is that when a repaint() is invoked, maybe the previous one is not completed yet... This would result in a jerky display, far from being smooth, at the opposite of the expected result.
A solution is to tell Swing to wait, which happens to be shamefully simple... Here is the code for the speed display:
  public void setSpeed(final double d)
  {
    this.speed = d;
    double from = this.prevSpeed; 
    double to = d;
    
    int sign = (from>to)?-1:1;
    prevSpeed = d;
    // Smooth rotation
    for (double s=from; (sign==1 && s<=to) || (sign==-1 && s>=to); s+=(0.1*sign)) // 0.1 is the damping factor
    {
      final double _s = s;
      try
      {
        SwingUtilities.invokeAndWait(new Runnable()
          {
            public void run()
            {
              speed = _s;
              repaint();
            }
          });
      }
      catch (Exception ex)
      {
        ex.printStackTrace();
      }
    }
  }
The paintComponent(Graphics) method uses the speed member to position the hand on the display.
Notice the SwingUtilities.invokeAndWait method that takes a Runnable as a parameter. This Runnable is the one invoking the repaint() method. This way, Swing will do nothing until the repaint is completed, and it is not even necessary to worry about synchronizing anything...

See also SwingUtilities.invokeLater. It allows Swing to perform demanding tasks asynchronously.

Thursday, October 18, 2012

Who just called me?

In Java, when you are in a specific method and you want to know who called you, who invoked the method, this is so simple!
A few lines will do the job:
  private void callee()
  {
    // Who called me
    Throwable t = new Throwable(); 
    StackTraceElement[] elements = t.getStackTrace(); 
    System.out.println("----------------------------------");
    for (StackTraceElement ste : elements)
      System.out.println(ste.toString());
    System.out.println("----------------------------------");
   
    // More stuff goes here... 
  }
Whenever the code above is invoked, like from a button click for example
  JButton bing = new JButton("Hit me!");
  bing.addActionListener(new ActionListener()
        {
          public void actionPerformed(ActionEvent e)
          {
            callee();
          }
        });
An output like that one can be expected:
----------------------------------
tideengineimplementation.gui.TideInternalFrame.resetData(TideInternalFrame.java:3035)
tideengineimplementation.gui.TideInternalFrame.refreshButton_actionPerformed(TideInternalFrame.java:3829)
tideengineimplementation.gui.TideInternalFrame.access$8200(TideInternalFrame.java:140)
tideengineimplementation.gui.TideInternalFrame$35.actionPerformed(TideInternalFrame.java:3002)
javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:272)
java.awt.Component.processMouseEvent(Component.java:6289)
javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
java.awt.Component.processEvent(Component.java:6054)
java.awt.Container.processEvent(Container.java:2041)
java.awt.Component.dispatchEventImpl(Component.java:4652)
java.awt.Container.dispatchEventImpl(Container.java:2099)
java.awt.Component.dispatchEvent(Component.java:4482)
java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577)
java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
java.awt.Container.dispatchEventImpl(Container.java:2085)
java.awt.Window.dispatchEventImpl(Window.java:2478)
java.awt.Component.dispatchEvent(Component.java:4482)
java.awt.EventQueue.dispatchEventImpl(EventQueue.java:644)
java.awt.EventQueue.access$000(EventQueue.java:85)
java.awt.EventQueue$1.run(EventQueue.java:603)
java.awt.EventQueue$1.run(EventQueue.java:601)
java.security.AccessController.doPrivileged(Native Method)
java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
java.awt.EventQueue$2.run(EventQueue.java:617)
java.awt.EventQueue$2.run(EventQueue.java:615)
java.security.AccessController.doPrivileged(Native Method)
java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
java.awt.EventQueue.dispatchEvent(EventQueue.java:614)
java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
----------------------------------
Easy!

Wednesday, October 10, 2012

serialVersionUID

Serialization is a powerful mechanism available in Java. It is - among many others - used by RMI (Remote Method Invocation), that can establish a communication between different JVMs.
A problem can appear when the class definition available on JVM#1 is not the same as the one available on JVM#2.
When defining a class implementing the java.io.Serializable interface, modern compilers will often reproach you with not correctly defining a final static long serialVersionUID.
We are briefly going to touch base on that, trying to explain what that means and what this is all about.

There is nothing like a good example to illustrate this kind of things. I hope you will like the following one.
Let us define a Serializable class:
public class Description
  implements Serializable
{
  @SuppressWarnings("compatibility:5602934367223767090")
  private static final long serialVersionUID = 1L;

  private String stringDataOne;
  private String stringDataTwo;
//private double numericData;
  private float numericData;

  public void setStringDataOne(String s)
  {
    this.stringDataOne = s;
  }

  public void setStringDataTwo(String s)
  {
    this.stringDataTwo = s;
  }

  public String getStringDataOne()
  {
    return this.stringDataOne;
  }

  public String getStringDataTwo()
  {
    return this.stringDataTwo;
  }

  public void setNumericData(float dummyNumber)
//public void setNumericData(double dummyNumber)
  {
    this.numericData = dummyNumber;
  }

  public float getNumericData()
//public double getNumericData()
  {
    return numericData;
  }
  
  @Override
  public String toString()
  {
    return new StringBuffer("One  : ").append(this.stringDataOne)
                  .append("\nTwo  : ").append(this.stringDataTwo)
                  .append("\nNum  : " + NumberFormat.getInstance().format(numericData)).toString();
  }
}
Notice the final static long serialVersionUID = 1;. We'll talk about it shortly.
This class being defined, we are going to:
  1. Serialize an instance of it into a file
  2. De-serialize this instance from the file
Serializer
public class WriteObject
{
  public static void main(String[] args)
  {
    Description dataObject = new Description();
    dataObject.setStringDataOne("First line of data");
    dataObject.setStringDataTwo("Second line, as expected");
    dataObject.setNumericData(12345);

    try
    {
      FileOutputStream fout = new FileOutputStream("description.ser");
      ObjectOutputStream oos = new ObjectOutputStream(fout);
      oos.writeObject(dataObject);
      oos.close();
      System.out.println("Done");
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
}
Serializer at work:
 Done
De-serializer
public class ReadObject
{
  public static void main(String[] args)
  {
    Description restoredObject;

    try
    {
      FileInputStream fin = new FileInputStream("description.ser");
      ObjectInputStream ois = new ObjectInputStream(fin);
      restoredObject = (Description) ois.readObject();
      ois.close();

      System.out.println(restoredObject);
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
}
De-serializer at work:
 One  : First line of data
 Two  : Second line, as expected
 Num  : 12,345
This is what happens when everything goes well.
Now, let's modify the Serializable class, let's change the float numeric data to a double (member, getter, setter), and without re-serializing it, let's try to de-serialize it:
java.io.InvalidClassException: serialversionui.Description; incompatible types for field numericData
 at java.io.ObjectStreamClass.matchFields(ObjectStreamClass.java:2210)
 at java.io.ObjectStreamClass.getReflector(ObjectStreamClass.java:2105)
 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:602)
 at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
 at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
 at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
 at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
 at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
 at serialversionui.ReadObject.main(ReadObject.java:17)
Basically, it says it cannot cast a Description to a Description...
If the serialVersionUID had been modified when changing the float to a double - like from 1 to 2 for example
  private static final long serialVersionUID = 2L;
you would have seen the following message:
java.io.InvalidClassException: serialversionui.Description; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:562)
 at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
 at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
 at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
 at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
 at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
 at serialversionui.ReadObject.main(ReadObject.java:17)
It does not work any better, but it returns useful information to communicate with the development teams.

Java recommends a way to come up with the appropriate value for the serialVersionUID. This is the reason for the @SuppressWarnings annotation in the code snippets available above. Find it here.

Tuesday, October 09, 2012

Serializing data

Let's say you are developing Java code, and you have large objects - Maps and Lists - to read through in order to compute some result.
The problem, illustrating the point, was to load in memory all the data and coefficients for a Tidal Computation. Before you start doing any work, you have to read those data from somewhere, load them into your working memory, so they are available when you need them.
Several technologies are available to achieve this goal, the question here is to know which one to go for. Many different data storage techniques could be used. We will compare here XML, Java Serialization, and json (Java Script Object Notation). Notice that we are not here talking about Databases, which is certainly a possible approach. The rationale was to keep the solution as light and self-contained as possible, the data are to be read only (and not modified by any mean). We felt that in that case, the Database approach was overkilling.
XML itself can be approached in different ways, DOM, SAX, or StAX. As we don't wish here to modify any of the data to load, we will use SAX (Simple API for XML).
All the required data are stored into some files, which have to be loaded into objects at runtime.
So, to recapitulate before we get started, we will restrict our comparison to those three approaches:
  • XML, using a SAX parser to load the data
  • Java Serialization/Deserialization
  • Json Serialization/Deserialization
In order to compare what is comparable (apples to apples), we stored the data files into an archive, a zip in this case.
Those data were then deserialized into the exact same objects.
The archive containing the XML data is 1,546,860 bytes big.
The archive containing the Java Serialized (.ser) data is 1,772,159 bytes big.
The archive containing the json data is 2,543,174 bytes big.
We iterated 5 times on the same deserializations, and then did an average.

Here is the code:
  public static void main(String[] args) throws Exception
  {
    long[] elapsed = { 0L, 0L, 0L };
    long before = 0L, after = 0L;
    BackEndTideComputer.setVerbose(false);
    for (int i=0; i<5; i++)
    {
      before = System.currentTimeMillis();
      BackEndTideComputer.connect(BackEndTideComputer.XML_OPTION);
      after = System.currentTimeMillis();
      elapsed[0] += (after - before);
      BackEndTideComputer.disconnect();
      
      before = System.currentTimeMillis();
      BackEndTideComputer.connect(BackEndTideComputer.JAVA_SERIALIZED_OPTION);
      after = System.currentTimeMillis();
      elapsed[1] += (after - before);
      BackEndTideComputer.disconnect();
  
      before = System.currentTimeMillis();
      BackEndTideComputer.connect(BackEndTideComputer.JSON_SERIALIZED_OPTION);
      after = System.currentTimeMillis();
      elapsed[2] += (after - before);
      BackEndTideComputer.disconnect();
    }
    System.out.println("XML:" + Long.toString(elapsed[0] / 5) + " ms" +
                     "  JavaSer:" + Long.toString(elapsed[1] / 5) + " ms" +
                     "  json:" + Long.toString(elapsed[2] / 5) + " ms");
  }
... and here are the results:
 XML:3540 ms  JavaSer:5455 ms  json:4225 ms
If we tune those results to take the data file size in account, by rendering the milliseconds per megabyte, we come up with the following table:

XMLserjson
archive size in bytes1,546,860 1,772,159 2,543,174
elapsed time in ms3,5405,4554,225
average ms/Mb234032281742
The first to cross the line in the SAX XML Parser (I used the one from Oracle).
The best average award (ms/Mb) goes to json (I used Gson, the json parser from Google), but notice that that data we started from are the bigest.
Surprisingly, the red lantern remains the Java Serialization...

A note about JAX-B
We've not talked about JAX-B here, which stands for Java API for XML Binding. It sounds like it could deserve its place in this article... But it actually does not. The JAX-B process starts from an XML Schema, which we don't have in this case (OK, we could have built one. But we did not). This article talks about it.

So, we've been able to compare three approaches, and the "native" one seems to be the worse, which is a bit of a surprise.
This is probably enough to have a better idea of what technology to use to address this kind of problem, but as a bonus, let us take a look at the amount of code required to put them at work.

Java Deserializer

  public static <T> T loadObject(InputStream resource, Class<T> cl) throws Exception 
  {
    T tideObject = null;
    try
    {
      ObjectInputStream ois = new ObjectInputStream(resource);
      tideObject = (T)ois.readObject();
      ois.close();
    }
    catch (Exception ex)
    {
      throw ex;
    }
    return tideObject;
  }

JSON deserializer

  public static <T> T loadObject(InputStream resource, Class<T> cl) throws Exception 
  {
    T tideObject = null;
    try
    {
      BufferedReader br = new BufferedReader(new InputStreamReader(resource));
      StringBuffer sb = new StringBuffer();
      String line = "";
      boolean go = true;
      while (go)
      {
        line = br.readLine();
        if (line == null)
          go = false;
        else
          sb.append(line);
      }
      br.close();
      if (gson == null)
        gson = new GsonBuilder().setPrettyPrinting().create();
      tideObject = gson.fromJson(sb.toString(), cl);        
    }
    catch (Exception ex)
    {
      throw ex;
    }
    return tideObject;
  }

XML SAX Handler

Here is the code starting the SAX process
  public static Map getStationData() throws Exception
  {
    Map stationData = new HashMap();
    StationFinder sf = new StationFinder(stationData);
    try
    {
      SAXParserFactory factory = SAXParserFactory.newInstance();
      SAXParser saxParser = factory.newSAXParser();      
      InputSource is = BackEndTideComputer.getZipInputSource(ARCHIVE_STREAM, STATIONS_ENTRY);
      saxParser.parse(is, sf);       
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
    
    return stationData;
  }
Notice that this code invokes a custom handler, named StationFinder:
  public static class StationFinder extends DefaultHandler
  {
    private String stationName = "";
    private TideStation ts = null;
    private Map stationMap = null;
    
    public void setStationName(String sn)
    {
      this.stationName = sn;
    }
    
    public StationFinder()
    {
    }

    public StationFinder(Map map)
    {
      this.stationMap = map;
    }
    
    public TideStation getTideStation()
    {
      return ts;
    }

    private boolean foundStation        = false;
    private boolean foundNameCollection = false;
    private boolean foundStationData    = false;
    
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes)
      throws SAXException
    {
//    super.startElement(uri, localName, qName, attributes);
      if (!foundStation && "station".equals(qName))
      {
        String name = attributes.getValue("name");
        if (name.contains(this.stationName))
        {
          foundStation = true;
          ts = new TideStation();
          ts.setFullName(name);
        }
      }
      else if (foundStation)
      {
        if ("name-collection".equals(qName))
        {
          foundNameCollection = true;
        }
        else if ("name-part".equals(qName) && foundNameCollection)
        {
          ts.getNameParts().add(attributes.getValue("name"));
        }
        else if ("position".equals(qName))
        {
          ts.setLatitude(Double.parseDouble(attributes.getValue("latitude")));
          ts.setLongitude(Double.parseDouble(attributes.getValue("longitude")));
        }
        else if ("time-zone".equals(qName))
        {
          ts.setTimeZone(attributes.getValue("name"));
          ts.setTimeOffset(attributes.getValue("offset"));
        }
        else if ("base-height".equals(qName))
        {
          ts.setBaseHeight(Double.parseDouble(attributes.getValue("value")));
          ts.setUnit(attributes.getValue("unit"));
        }
        else if ("station-data".equals(qName))
        {
          foundStationData = true;
        }
        else if (foundStationData && "harmonic-coeff".equals(qName))
        {
          String name = attributes.getValue("name");
          double amplitude = Double.parseDouble(attributes.getValue("amplitude"));
          double epoch     = Double.parseDouble(attributes.getValue("epoch")) * TideUtilities.COEFF_FOR_EPOCH;
          Harmonic h = new Harmonic(name, amplitude, epoch);
          ts.getHarmonics().add(h);
        }
      }
    }
The code snippets speak for themselves... SAX is the most demanding, by far. Also notice that it requires a full knowledge of the data to parse. Java and Json de-serialization do not. As long as the data have been correctly serialized, they will be correctly de-serialized (which brings up the discussion about the famous serialVersionUID in Java..., it's another story).

All the code, including the archives containing the data, is available from Google Code. The specific class displayed above is right here.

Wednesday, October 03, 2012

Functional Programming in Java

Functional Programming brings new and interesting paradigms to Java code development.
I am not saying that functional programming is a new concept, OK?
Several of those languages (Scala, Clojure) run on top of a Java VM, but Java itself is NOT as functional programming language..., how is that possible, there must be a way!
One of the aspects of the functional programming languages is this possibility to use a pointer on a function as a parameter. Here is a possible approach, even easier to access since the diamond notation has been implemented in the recent versions of the Java language.
We are going to use a simple example as an illustration. We will choose the function to execute, based on the value of a parameter. What we want to do here is to greet someone in the language passed as a parameter.
Note:
Only for the clarity of the code, we are not using here the usual Java convention for the diamond notation (T for Type, E for Element, K for Key, V for Value, N for Number, S, U, V, etc, for 2nd, 3rd, 4th,... types).

Let us consider a first Java interface defined as follow:
 package functions;

 public interface FunctionOneArgReturnVoid<SomeType>
 {
   public void execute(SomeType a);
 }
And let us write the following implementation:
 package functions;

 public class ImplementationSampleOne
 {
   FunctionOneArgReturnVoid<String> funcEnglish = 
                      new FunctionOneArgReturnVoid<String>()
    {
      public void execute(String s)
      {
        System.out.println("Hello " + s + "!");
      }
    };
   FunctionOneArgReturnVoid<String> funcFrench  = 
                      new FunctionOneArgReturnVoid<String>()
    {
      public void execute(String s)
      {
        System.out.println("Bonjour " + s + " !");
      }
    };

   public FunctionOneArgReturnVoid<String> getFunction(String lng)
   {   
     if ("FR".equalsIgnoreCase(lng))
       return funcFrench;
     else
       return funcEnglish;
   } 

   public void execute(FunctionOneArgReturnVoid<String> func, String arg)
   {
     func.execute(arg); 
   }

   public static void main(String[] args)
   {
     String lng = "EN";
     if (args.length > 0)
       lng = args[0]; 

     ImplementationSampleOne impl = new ImplementationSampleOne();
     impl.execute(impl.getFunction(lng), "Joe Shmow");
   }
 }
See the two implementations of the FunctionOneArgReturnVoid interface, and the way they are invoked in the main method.
The typography rules are not the same in English and French. In French you need a space before a '!'.
The execution would look like this:
 Prompt> java functions.ImplementationSampleOne "FR"
 Bonjour Joe Shmow !

 Prompt> java functions.ImplementationSampleOne "EN"
 Hello Joe Shmow!
The return type can be also described by an interface:
 package functions;

 public interface FunctionTwoArgsReturnType<SomeTypeOne, 
                                            SomeTypeTwo, 
                                            ReturnType>
 {
   public ReturnType execute(SomeTypeOne a, SomeTypeTwo b);
 }
The interface implementation would look like this:
  FunctionTwoArgsReturnType<String, String, String> funcEnglish = 
                 new FunctionTwoArgsReturnType<String, String, String>()
   {
     public String execute(String a, String b)
     {
       return "Hello " + a + ", from " + b + "!";
     }
   };
  FunctionTwoArgsReturnType<String, String, String> funcFrench  = 
                 new FunctionTwoArgsReturnType<String, String, String>()
   {
     public String execute(String a, String b)
     {
       String s = "Bonjour " + a + ", de la part ";
       if (b.toUpperCase().toCharArray()[0] == 'A' ||
           b.toUpperCase().toCharArray()[0] == 'E' ||
           b.toUpperCase().toCharArray()[0] == 'I' ||
           b.toUpperCase().toCharArray()[0] == 'O' ||
           b.toUpperCase().toCharArray()[0] == 'U' ||
           b.toUpperCase().toCharArray()[0] == 'Y')
         s += ("d'" + b);
       else
         s += ("de " + b);
       s += " !";
       return s;
     }
   };
The main like that:
  public static void main(String[] args)
  {
    String lng = "EN";
    if (args.length > 0)
      lng = args[0];

    ImplementationSampleTwo impl = new ImplementationSampleTwo();
    String greeting = impl.execute(impl.getFunction(lng), "Joe Shmow", "Olivier");
    System.out.println(greeting);
    greeting = impl.execute(impl.getFunction(lng), "Joe Shmow", "Mr X");
    System.out.println(greeting);
  }
The output would become
 Prompt> java functions.ImplementationSampleTwo "EN"
 Hello Joe Shmow, from Olivier!
 Hello Joe Shmow, from Mr X!

 Prompt> java functions.ImplementationSampleTwo "FR"
 Bonjour Joe Shmow, de la part d'Olivier !
 Bonjour Joe Shmow, de la part de Mr X !
The complexity is isolated in the implementation of the function. The code using it does not need to know anything about it.

This possibility of using pointers on functions does not make Java a functional programming language, but this is a first step towards it.