Wednesday 21 November 2012

Tomcat 7.0.32, IE & javascript comments


UPDATE: this is fixed in 7.0.33


A funny one this & one that took a while to track down.
First off the bug does not show itself in firefox or chrome (proper browsers), just IE, but sadly we have to get them all to work.

My development system was running perfectly in all tested browsers but then my tester reported an issue where a page was just displaying a blank page.

We blamed the data, his version of IE, which was 8 & I am on IE 9.

Eventually we struck on the tomcat versions. I was running 7.0.29 & he was running what is currently the latest tomcat 7.0.32

So looking further I worked out that if I swapped over the jasper jars I could get 7.0.32 to work. The issue turns out to be the javascript comments. If there is an uneven number of dashes next to the percent then the page will fail.

 So this is good.
 <%-- a good javascript comment --%>;  

& this will fail
 <%--- a dodgy javascript copmment in tomcat 7.0.32 --%>  

clock changing - Is this a Long, Short or a Normal day

Time is always a thorn in the side of developers.

In my latest project I needed to know the number of hours in a day and I could find no easy method on existing classes to determine if the day was a clock change day. I thought the great Joda date time classes would have helped but I could not find the one I needed so I wrote this.

 public enum ClockChangeInfo {  
  LONG_DAY(90000000, 25), SHORT_DAY(82800000, 23), NORMAL_DAY(86400000, 24), INDETERMINATE(0, 0);  
  private int mMsecs;  
  private int mHrs;  
  private static final Map<Integer, ClockChangeInfo> MSEC = new HashMap<Integer, ClockChangeInfo>();  
  static {  
   for (ClockChangeInfo cci : values()) {  
    MSEC.put(new Integer(cci.mMsecs), cci);  
   }  
  }  
  ClockChangeInfo(int aMsecs, int aHrs) {  
   mMsecs = aMsecs;  
   mHrs = aHrs;  
  }  
  public int getHrs(ClockChangeInfo aCci) {  
   return aCci.mHrs;  
  }  
  public static ClockChangeInfo getDayType(DateMidnight dateToCheck) {  
   DateMidnight nextDay = dateToCheck.plusDays(1);  
   //this is a safe convert as it is only for day(n) - day(n-1)  
   Integer millis = (int)(nextDay.getMillis() - dateToCheck.getMillis());  
   ClockChangeInfo cci = MSEC.get(millis);  
   if (cci == null) {  
    return INDETERMINATE;  
   }  
   return cci;  
  }  
 }  

 public class ClockChangeUtil {  
  public static ClockChangeInfo getDayType(DateMidnight dateToCheck) {  
   return ClockChangeInfo.getDayType((dateToCheck));  
  }  
  public static int getNumHoursInDay(DateMidnight dateToCheck) {  
   ClockChangeInfo dayType = ClockChangeUtil.getDayType(dateToCheck);  
   return dayType.getHrs(dayType);  
  }  
  public static int getNumHalfHoursINMonthSoFar(DateMidnight dateToCheck) {  
   int numHours = 0;  
   int day = dateToCheck.getDayOfMonth();  
   if (day == 1) {  
    return 0;  
   }  
   DateMidnight dm = dateToCheck.minusDays(1);  
   do {  
    numHours += getNumHoursInDay(dm);  
    dm = dm.minusDays(1);  
    day--;  
   } while (day > 1);  
   return numHours * 2;  
  }  
 }  


and some test methods for it. NB these are UK based.


 public class ClockChangeUtilUnitTest  
 {  
  @Test  
  public void test_isLongDay() throws Exception  
  {  
   DateMidnight dm28 = new DateMidnight(2011, 10, 28);  
   DateMidnight dm29 = new DateMidnight(2011, 10, 29);  
   DateMidnight dm30 = new DateMidnight(2011, 10, 30);  
   DateMidnight dm31 = new DateMidnight(2011, 10, 31);   
   assertEquals(ClockChangeInfo.NORMAL_DAY, ClockChangeUtil.getDayType(dm28));  
   assertEquals(ClockChangeInfo.NORMAL_DAY, ClockChangeUtil.getDayType(dm29));  
   assertEquals(ClockChangeInfo.LONG_DAY, ClockChangeUtil.getDayType(dm30));  
   assertEquals(ClockChangeInfo.NORMAL_DAY, ClockChangeUtil.getDayType(dm31));  
  }  
  @Test  
  public void test_isShortDay() throws Exception  
  {  
   DateMidnight dm26 = new DateMidnight(2011, 3, 26);  
   DateMidnight dm27 = new DateMidnight(2011, 3, 27);  
   DateMidnight dm28 = new DateMidnight(2011, 3, 28);  
   DateMidnight dm29 = new DateMidnight(2011, 3, 29);  
   assertEquals(ClockChangeInfo.NORMAL_DAY, ClockChangeUtil.getDayType(dm26));  
   assertEquals(ClockChangeInfo.SHORT_DAY, ClockChangeUtil.getDayType(dm27));  
   assertEquals(ClockChangeInfo.NORMAL_DAY, ClockChangeUtil.getDayType(dm28));  
   assertEquals(ClockChangeInfo.NORMAL_DAY, ClockChangeUtil.getDayType(dm29));  
  }  
  @Test  
  public void testClockChange() throws Exception  
  {  
   long millisInANormalDay = 24 * 60 * 60 * 1000;  
   long millisInALongDay = 25 * 60 * 60 * 1000;  
   DateMidnight dm28 = new DateMidnight(2011, 10, 28);  
   DateMidnight dm29 = new DateMidnight(2011, 10, 29);  
   DateMidnight dm30 = new DateMidnight(2011, 10, 30);  
   DateMidnight dm31 = new DateMidnight(2011, 10, 31);  
   assertEquals(millisInANormalDay, dm29.getMillis() - dm28.getMillis());  
   assertEquals(millisInANormalDay, dm30.getMillis() - dm29.getMillis());  
   assertEquals(millisInALongDay, dm31.getMillis() - dm30.getMillis());  
   DateTime dt28 = new DateTime(dm28);  
   DateTime dt29 = new DateTime(dm29);  
   DateTime dt30 = new DateTime(dm30);  
   DateTime dt31 = new DateTime(dm31);  
   assertEquals(millisInANormalDay, dt29.getMillis() - dt28.getMillis());  
   assertEquals(millisInANormalDay, dt30.getMillis() - dt29.getMillis());  
   assertEquals(millisInALongDay, dt31.getMillis() - dt30.getMillis());  
   assertTrue(dt28.getZone().equals(dt29.getZone()));  
   assertTrue(dt28.getZone().equals(dt30.getZone()));  
   assertTrue(dt28.getZone().equals(dt31.getZone()));  
  }  
  @Test  
  public void test_getNumHoursInDay() throws Exception  
  {  
   DateMidnight dm26 = new DateMidnight(2011, 3, 26);  
   DateMidnight dm27 = new DateMidnight(2011, 3, 27);  
   DateMidnight dm28 = new DateMidnight(2011, 3, 28);  
   DateMidnight dm29 = new DateMidnight(2011, 3, 29);  
   assertEquals(24, ClockChangeUtil.getNumHoursInDay(dm26));  
   assertEquals(23, ClockChangeUtil.getNumHoursInDay(dm27));  
   assertEquals(24, ClockChangeUtil.getNumHoursInDay(dm28));  
   assertEquals(24, ClockChangeUtil.getNumHoursInDay(dm29));  
  }  
 }