Hi,
In trying to implement support for HTTP conditional GET I ran across a bizarre
bug which seems to be somehow related to the implementation of ImmutableDate.
The scene:
lastModified is a java.util.Date (also works if it's a java.sql.Timestamp)
corresponding to the last modified date for this resource.
final Date clientCopy = request.getConditions().getModifiedSince();
// This represents the "If-Modified-Since" header from the client.
/*
If this condition is true, the server must send a new copy of the resource
(HTTP 200)
*/
// Both of these calls returns inaccurate results, tested in cases where
// lastModified is up to 24 minutes after clientCopy
if (clientCopy == null || lastModified.after(clientCopy)) {
if (clientCopy == null || !clientCopy.before(lastModified)) {
// Both of these calls behave as expected.
if (clientCopy == null || lastModified.after(new Date(clientCopy.getTime()))) {
if (clientCopy == null || lastModified.getTime() > clientCopy.getTime()) {
I'm not really sure what's going on, but manually extracting the epoch timestamp
using getTime() (and either comparing the dates as longs or constructing a
canonical java.util.Date) fixes the problem.
FWIW, java.util.Date.after() uses some sort of bizarre internal structures
(fastTime and cdate) to get an epoch time in millis, and doesn't call
subclassers' implementations of getTime().
My theory is that ImmutableDates, since they store their real date in a
delegate, keep the date of their creation in their internal fields (inherited
from java.util.Date). java.util.Date.after() probably reads from this data and
not the delegate.
A better strategy for ImmutableDate might be to keep the Date data inside the
object itself and override all the setXXX functions to throw Exceptions. This
maintains functional type inheritance.