Emergency!! - Intermittent date / time corruption.

Hi all,

I have to post this; I just can't seem to find the cause of this intermittent bug, but it's happening - here's the scoop ...

2 environments - DEV & PROD (exact same specs, see below)

JDK 1.5.0_06

Tomcat 5.5.16

SQL Server 2000

Only difference between DEV & PROD is the OS...

DEV - windows XP

PROD - windows server 2003.

Now, with this in mind, my JSP is doing the following:

1. Querying the DB.

2. Getting back the results (1000s of rows, 50 a page)

3. Displaying the results in a HTML table.

For testing purposes, i have DEV & PROD pointing to the same SQL Server and the results I get when displaying results from the DB are like this:

0002828, NUW Picnic,25-Sep-2006 10:00- DEV (correct)

0002828, NUW Picnic,25-Sep-2006 18:27- PROD (wrong)

0002822, Alfa Romeo, 02-Jul-2006 08:30- DEV (correct)

0002822, Alfa Romeo, 02-Mar-2006 16:29- PROD (wrong)

These are just 2 rows from many and as you can see, the date/time presented in DEV is correct, but the date/time presented in PROD is wrong! What is worse is that this bug is intermittent - meaning that this does not happen to PROD all the time - if you were to refresh (F5) PROD a couple of times, the result page (date/time) would be correct).

I checked the timezones for both OS's ... they are both correct.

Furthermore, I've hardcoded mytimezone (Australia/Melbourne) in theSimpleDateFormat object, but these are my results.

NOTE: the code base is exactly the same for both DEV & PROD.

A snippet of the code where date formatting takes place is...

String eSD[] = DateUtil.formatDate(resultset.getTimestamp(5),DateUtil.dd_MMM_yyyy_HH_mm).split(" ");

eStartDate_v.addElement(eSD[0]);

eStartTime_v.addElement(eSD[1]);

String eED[] = DateUtil.formatDate(resultset.getTimestamp(6),DateUtil.dd_MMM_yyyy_HH_mm).split(" ");

eEndDate_v.addElement(eED[0]);

eEndTime_v.addElement(eED[1]);

TheDateUtil class is as follows...

publicstatic SimpleDateFormat sdf[];

publicstatic Vector<String> date_format_vect;

publicstaticint yyyy = 0;

publicstaticint dd_MMM_yyyy = 1;

publicstaticint dd_MMM_yyyy_HH_mm = 2;

publicstaticint dd_MMM_yyyy_hh_mm = 3;

publicstaticint yyyy_MM_dd = 4;

publicstaticint EEE_dd_MMM_yyyy_HH_mm_ss = 5;

publicstaticint dd_MMM_yyyy_HH_mm_ss = 6;

publicstaticint EEE_dd_MMM_yyyy_HH_mm = 7;

publicstaticint HH_mm = 8;

static

{

date_format_vect =new Vector<String>();

date_format_vect.addElement("yyyy");

date_format_vect.addElement("dd-MMM-yyyy");

date_format_vect.addElement("dd-MMM-yyyy HH:mm");

date_format_vect.addElement("dd-MMM-yyyy hh:mm");

date_format_vect.addElement("yyyy-MM-dd");

date_format_vect.addElement("EEE, dd-MMM-yyyy HH:mm:ss");

date_format_vect.addElement("dd-MMM-yyyy HH:mm:ss");

date_format_vect.addElement("EEE, dd-MMM-yyyy HH:mm");

date_format_vect.addElement("HH:mm");

sdf =new SimpleDateFormat[date_format_vect.size()];

for (int i = 0; i < date_format_vect.size(); i++)

{

sdf[i] =new SimpleDateFormat((String)date_format_vect.elementAt(i));

sdf[i].setLenient(false);

sdf[i].setTimeZone(TimeZone.getTimeZone("Australia/Melbourne"));

}

}

public DateUtil(){}

publicstatic String formatDate(Date date,int i)

{

String s =null;

s = sdf[i].format(date);

return s;

}

Can someone help, this is an emergency because this web application is a mission critical application for a state wide government agency and time is critical.

Thanks.

[5817 byte] By [stevekatsarasa] at [2007-10-2 16:55:25]
# 1

The code looks good enough. Can you check the value of resultset.getTimestamp() in both dev and prod?

If it returns the same in both cases, then the problem is in your formatDate() method.

Can you try with resultset.getDate() method. You really dont require the getTimestamp() unless you are interested in nano second values.

ram.

Madathil_Prasada at 2007-7-13 18:07:52 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 2

It could be a multi-threading issue. The [url http://java.sun.com/j2se/1.5.0/docs/api/java/text/SimpleDateFormat.html]API[/url] has this to say:

Synchronization

Date formats are not synchronized. It is recommended to create

separate format instances for each thread. If multiple threads access a

format concurrently, it must be synchronized externally.

Try modifying your code to NOT cache the SimpleDateFormats, and instead instantiate them each time.

See if that fixes the problem. It is more important to be correct than fast in this case.

Also just as a matter of style, I would call your constants by a logical name rather than what you have.

eg

public static int yearOnly = 0;

public static int shortFormat = 1;

If one of those formats changes your constant would be misnamed.

ie public static int dd_MMM_yyyy might change requirements to print as dd/MM/yyyy and then where would you be?

evnafetsa at 2007-7-13 18:07:52 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 3

> It could be a multi-threading issue. The [url

> http://java.sun.com/j2se/1.5.0/docs/api/java/text/Simp

> leDateFormat.html]API[/url] has this to say:

>

> Synchronization

> Date formats are not synchronized. It is recommended

> to create

> separate format instances for each thread. If

> multiple threads access a

> format concurrently, it must be synchronized

> externally.

>

> Try modifying your code to NOT cache the

> SimpleDateFormats, and instead instantiate them each

> time.

> See if that fixes the problem. It is more important

> to be correct than fast in this case.

evnafets, i've taken your suggestion and i've modified the DateUtil class (see 1st post) to as follows...

public class DateUtil

{

public DateUtil() {}

public static SimpleDateFormat getDateFormat(String pattern)

{

SimpleDateFormat sdf = new SimpleDateFormat(pattern);

sdf.setLenient(false);

sdf.setTimeZone(TimeZone.getDefault());

return sdf;

}

public static Date getCurrentTime()

{

Calendar calendar = Calendar.getInstance();

calendar.setTime(new Date());

return calendar.getTime();

}

public static Calendar getCurrentCalendarTime()

{

return Calendar.getInstance();

}

}

So now, in my java beans, instead of doing the following...

while(res.next())

{

...

String eSD[] = DateUtil.formatDate(resultset.getTimestamp(5),DateUtil.dd_MMM_yyyy_HH_mm).split(" ");

eStartDate_v.addElement(eSD[0]);

eStartTime_v.addElement(eSD[1]);

String eED[] = DateUtil.formatDate(resultset.getTimestamp(6),DateUtil.dd_MMM_yyyy_HH_mm).split(" ");

eEndDate_v.addElement(eED[0]);

eEndTime_v.addElement(eED[1]);

...

}

I do...

SimpleDateFormat sdf = DateUtil.getDateFormat("dd-MMM-yyyy HH:mm");

while(res.next())

{

...

String eSD[] = sdf.format(res.getTimestamp(5)).split(" ");

eStartDate_v.addElement(eSD[0]);

eStartTime_v.addElement(eSD[1]);

String eED[] = sdf.format(res.getTimestamp(6)).split(" ");

eEndDate_v.addElement(eED[0]);

eEndTime_v.addElement(eED[1]);

...

}

Do you think this implementation will work in a multithreaded environment? (many operators will be hitting this concurrently).

I have just implemented this and we are now performing tests.

Thanks.

PS: I shall get back to you with my results.

stevekatsarasa at 2007-7-13 18:07:52 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 4
So far so good, my results are coming out correct.Thanks guys.
stevekatsarasa at 2007-7-13 18:07:52 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...