Monday, February 18, 2013

Minor Gotchas from migration to Java 7

After several years of pushing, we are finally starting to pull our application out of the dark ages  in terms of software levels and one of those steps is upgrading our Java version to Java 7. For the most part, this has been fairly painless, but there have been a couple surprises:
  • Test cases that had been running successfully for years started failing when we switched to Java 7.  It turns out that we had some test cases that depended on previous test cases within the same class.  This is bad on two fronts, 1) the test cases should each be independent and 2) the execution order of test cases within a test class is not guaranteed, although, up to now(before Java 7), the order was the order found in the source code.  I found this link that helped explain the inconsistent ordering I was seeing within Eclipse.  This is not a problem with Java 7 but rather with our test cases.   Just  something that cropped up when we started running with Java 7

  • Our Swing clients began throwing ClassCastExceptions, and this is code that has been in place for over 10 years, dating back to Java 1.4   Reading the javadocs helped explain the problem, but I decided to research a bit more to find out exactly why this was happening now.   We were adding entries to a TreeSet to hold forward and backward traversal keys for the FocusManager, putting KeyStroke objects into the TreeSet.   The javadoc clearly states that the objects put in the TreeSet (or TreeMap underneath) must be Comparable or you need to create the TreeSet with a Comparator for ordering the objects. We were doing neither,  and not getting exceptions.  Digging into the java source code,  I found that starting in Java 7, the TreeMap class has starting enforcing this 'requirement', where the earlier versions of the class had that code commented out, thus not really requiring the comparator.    The fix was easy, I created a KeyStrokeComparator and passed that to the TreeSet constructor.

  • I also noticed that our java jar signing had started logging a warning about the certificate not being valid.   Wanting to keep the build clean and not have these warnings, I did some searches and found several postings related to Java 7 and the removal of the MD2withRSA algorithm from the code signing certificates.   I worked with support from Verisign to help with the removal of that algorithm from our certificate chain and the warning went away!  Unfortunately, that was not the end of the code signing problems.   

  • Next, our web start clients would no longer start successfully, instead throwing an exception with the all-too-familiar  'not all jars signed with the same certificate' error message frequently encountered by web start programs, at least during development!  I've written another blog post about how to help debug through this and figured it was just 'one of the usual suspect jars' that we have problems with, but nope, that wasn't it.   Knowing that all this happened since the certificate was updated caused me to review all of our signed jars to look for clues.   All the jars had been signed with the same certificate, but the 3rd party jars were signed BEFORE the chain entry was remove, whereas our application code was signed as part of the build process, AFTER the certificate was changed.   This led me to believe that even though the jars were signed with the same certificate, that there must be some difference between the jars signed before and after the change to the certificate.   

  • When jars are signed,  entries are generated in the MANIFEST.MF file inside the jar, one entry for each class in the jar.  These entries contain the name of the class along with some signing algorithm information and after reviewing the MANIFEST.MF files,  I found the difference.  The 3rd party jars signed before the change included a SHA1-Digest entry for each class but our jars signed from the current build contained entries with SHA-256-Digest.   Re-signing all of our 3rd party jars with the updated certificate resolved most of the problems.   We had a minor problem in our re-signing process, where we over-wrote the existing MANIFEST.MF with our own generated version and this caused problems for a couple of jars that contained additional service provider information in the manifest file.
All in a days work!  Just Happy to be current on the Java level.  Next up, migrating to EJB3 and Hibernate 3 or 4.

Hope this helps!