Strange Days Indeed
We ran into a strange problem that had crept by us undetected due to the overlapping effects of two only partially-connected issues.
The requirements were fairly basic – display a list of items, along with a starting date and a processed date for each of them. Easy enough, really. Or so you would think.
Both dates for each item displayed correctly locally, but as soon as it made it onto the test servers the starting date was rendered showing a date one day previously. The database confirmed what the correct date should have been but it wasn’t being displayed. The processed date displayed correctly in all cases.
Another developer mentioned that they’d had a similar issue that had been due to the date conversion performed by JSP’S <h:outputText/> – they’d never found out exactly what was going on, but they’d gotten around it by performing the date to string conversion themselves. An interesting theory, but it didn’t explain why the second date was being rendered correctly for each line.
Armed with this snippet of knowledge I went exploring and found that, by default, the date conversion performed by JSP assumes that the timezone is UTC regardless of system settings.
Given that our starting dates were initialized with a time of 00:00, a conversion to UTC with the associated loss of a few hours perfectly explained why we were getting a date one day prior to the expected one.
Obviously, if we’d been showing a time as well we would have picked this up sooner but it wasn’t a requirement in this case. The processed date was of course while people were at work, so those dates were showing correctly even with a couple of hours subtracted. We might have run into a similar issue had someone been working overtime, closer to that midnight hour.
One mystery remained – why did the error not occur locally?
A Good Foundation
It seemed likely that the issue also had to result from time zones. It turned out that, to our embarrassment, none of us had ever set our application servers to the correct time zone. We were in the GMT+2 timezone, but our local servers were still on their default GMT zone.
Because of this, the date converter issue was masked. The dates that our local servers had were loaded in the GMT timezone meaning that there was no conversion done when they were formatted as strings. This in turn meant that the issue only appeared on the test servers which were being administered correctly. Oops.
Making Things Better
So, how do we fix all of these? The date converter issue can be fixed in one of three ways. First, you could format the date manually, which would use the system timezone. This is annoying though, as we can no longer treat dates as dates but must do backwards and forwards conversions.
Second, you can set a timezone on the JSP tag. This is more correct and allows you to treat dates as dates. It’s somewhat cumbersome as you have to do it for each tag, but if you’re using versions of JSF less than version 2.0 as we are then it’s your only other reasonable option.
It’s fairly easy to add the timezone – simply set it as a property on the <f:convertDateTime /> tag, obviously adding one if one did not exist. In our case, we needed something like
<f:convertDateTime pattern="dd-MMM-yyyy" timeZone="GMT+2" />
Finally (of the quick solutions), you can set a property in your web XML that tells JSF 2.0 to use the system timezone, although you’ll obviously need to be using it to do this. The way in which this is done is summarized nicely in BalusC’s answer.
The app server time zone issue is easier to fix – you’ll need to add a command line parameter when you boot your server. In our case, for GMT+2, we needed to add the following to our app server’s start batch file.
This also corrected the issue we’d had of our local logs timestamps being two hours out – you’d think that would have raised flags previously, but it hadn’t caused enough grief until now to warrant following up on. That’ll be the last time we don’t follow up on weird behaviour in our systems.