Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 5103041
Votes 101
Synopsis Regression: binary compatibility problem with java.sql.Timestamp.compareTo
Category jdbc:implementation
Reported Against tiger-rc
Release Fixed mustang(b59), 5.0u7(b01) (Bug ID:2132241)
State 11-Closed, Verified, bug
Priority: 2-High
Related Bugs 6304469 , 6207898
Submit Date 16-SEP-2004
Description
Just to make this concrete, here's a small program demonstrating the
problem.  Compile and run it, first against 1.4.2, then against
1.5/5.0:

import java.sql.Timestamp;
import java.util.Date;

public class Foo {
  public static void main(String[] args) {
    Date d = new Date();
    Timestamp ts = new Timestamp(d.getTime());
    System.out.println(ts.compareTo(d));
  }
}

Note that this a *binary compatibility problem*!!  The overload
resolution is the same in 1.4.2 and 1.5.0;  in either case, it's
compareTo(Date).  With a 1.4.2 runtime, it dispatches to the version
defined in java.util.Date, with a 1.5.0 runtime it dispatches to the
version defined in java.sql.Timestamp, which promptly casts its
argument to Timestamp (and blows up).  This really feels like a P2 bug
to me.
Work Around
N/A
Evaluation
A very interesting bug...  here's what I think happened.

In the fix for 4227983 (java.sql.Timestamp didn't overload compareTo, setTime
and getTime, delta 1.35, 2000/02/02, integrated into 1.4.0), two compareTo
methods were added to the Timestamp class, one taking a Timestamp and the other
taking an Object.  The compareTo(Object) method was specified as follows:

     * Compares this Timestamp to another Object. If the Object is 
     * a Date, this function behaves like compareTo(Timestamp). 
     * Otherwise, it throws aClassCastException (as Timestamps are 
     * comparable only to other Timestamps)
     * ...

The intent of this change was to allow Timestamps to be compared to Dates.

A later fix, for 4631234 (java.sql.Timestamp.compareTo no longer accepts
java.util.Dates in 1.4, delta 1.46 2002/04/01, integrated into 1.4.1), revised
the specification of the compareTo(Object) method instead to say:

     * Compares this <code>Timestamp</code> object to the given 
     * <code>Object</code>, which must be a <code>Timestamp</code>
     * object. If the argument is not a <code>Timestamp</code> object,
     * this method throws a <code>ClassCastException</code> object.
     * (<code>Timestamp</code> objects are 
     * comparable only to other <code>Timestamp</code> objects.)

In other words, the intent of this change was to require a ClassCastException
to be thrown when comparing a Timestamp to a Date.  Such behavior would cause
the submitter's code to fail.

The change for 4631234 did not modify any code.  It appears to have been made
under the assumption that the existing code already behaved according to the
new specification.  Due to the presence of a compareTo(Date) method in the Date
superclass, however, such comparisons were actually allowed, and so the
submitter's code actually worked... until recently.

The generification changes for Tiger (4964490) added the compareTo(Date) method
to Timestamp in order to preserve what was assumed (from the specification) to
be the current behavior; unfortunately the fact that the current behavior was
different from the specified behavior was not noticed at that time.  That new
method is what is now causing the submitter's code to receive the (specified)
ClassCastException.

A reasonable fix for this bug would be to revise the specification of the
Timestamp.compareTo(Date) method to allow Timestamp to be comparable to Dates
once again, and to redefine that method as

    public int compareTo(java.util.Date d) {
        return d.compareTo(this);
    }

(Of course the real problem here is that java.sql.Timestamp should not have
been made a subclass of java.util.Date in the first place, as explained in item
7 of Bloch's "Effective Java", but that's water under the bridge.)

--   xxxxx@xxxxx   2004/9/16

I agree with the above comprehensive assesment, and I'll work with the JCK team
and 1.5.x team to get fix for this. A specific determination as to the most
ideal delivery vehicle still has to be determined, but likely Mustang at this
point.

  xxxxx@xxxxx   2004-09-16

I am looking into fixing this bug.

The following lines will be getting removed from javadocs for the method
  public int compareTo(java.util.Date o) 

      * @exception ClassCastException if the argument is not a
      *        <code>Timestamp</code> object
      * @since    1.5
      */
     // This forwarding method ensures that the compareTo(Date) method defined
     // in java.util.Date is not invoked on a Timestamp

  xxxxx@xxxxx   2005-05-02 05:25:12 GMT

1. I will be removing the above lines from mustang i.e. jdk 6.0 and will not be doing the changes in jdk5.0uX versions.
I hope that is fine.

  xxxxx@xxxxx   2005-06-07 13:58:51 GMT

2. Also will change the method code to, in addition to above :-
public int compareTo(java.util.Date d) {
       return  - (d.compareTo(this));
   }

  xxxxx@xxxxx   2005-06-07 14:39:59 GMT

Since this is a regression and a binary incompatibility,
it is not unlikely that we will get requests for backports.
So I think a backport to a Tiger update must be considered.

The proposed solution is problematic:

java.util.Date d1 = new java.sql.Timestamp(...);
java.util.Date d2 = new java.sql.Timestamp(...);
d1.compareTo(d2); // stack overflow

See "Suggested Fix" section for an alternative solution.

  xxxxx@xxxxx   2005-06-07 19:02:25 GMT

I propose the following fix, other fixes propose either don't work with 1.4.x and 1.5.x or if they work don't produce the same results.

Index: src/java/sql/Timestamp.java

(cvs diff -wu Timestamp.java)
===================================================================
RCS file: /m/jws/jdbc4.0/src/java/sql/Timestamp.java,v
retrieving revision 1.5
diff -w -u -r1.5 Timestamp.java
--- src/java/sql/Timestamp.java    18 Jul 2005 19:33:37 -0000    1.5
+++ src/java/sql/Timestamp.java    21 Jul 2005 11:13:21 -0000
@@ -462,14 +462,22 @@
     *        <code>Timestamp</code> object
     * @since    1.5
     */
-    // This forwarding method ensures that the compareTo(Date) method defined
-    // in java.util.Date is not invoked on a Timestamp
    public int compareTo(java.util.Date o) {
-        return compareTo((Timestamp)o);
-    }
+        if(o instanceof Timestamp) {
+            // When Timestamp instance compare it with a Timestamp
+            // Hence it is basically calling this.compareTo((Timestamp))o);
+            // Note typecasting is safe because o is instance of Timestamp
+            return compareTo((Timestamp)o);
+        } else {
+            // When Date doing a o.compareTo(this)
+            // will give wrong results.
+            Timestamp ts = new Timestamp(o.getTime());
+            return this.compareTo(ts);
+        }
+    }

    static final long serialVersionUID = 2745179027874758501L; 

The test cases against which I verified the fix are already as given here and as below.

/////////////// Test Case 1 ///////////////////////
import java.sql.Timestamp;
import java.util.Date;

public class Foo {
 public static void main(String[] args) {
   Date d = new Date();
     Timestamp ts = new Timestamp(d.getTime());
   System.out.println(ts.compareTo(d));
   }
}

/////////////// Test Case 2 ///////////////////////
import java.sql.Timestamp;
import java.util.Date;

public class Foo1 {
 public static void main(String[] args) {

   Date d1 = new Date();
     java.util.Date d1 = new java.sql.Timestamp(d.getTime());
     java.util.Date d2 = new java.sql.Timestamp(d.getTime());
     System.out.println("Value is : "+d1.compareTo(d2));
 }
} 

Except the comments(//This forwarding) which I am not sure can be backported, I think this fix of the code can be backported without problems, if required.
Please comment for the fix.
Posted Date : 2005-08-03 11:17:46.0

This is getting fixed in Mustang and jdk5 update release as well. 
I have got the approval and this fix should be in soon.
All those requesting for this fix watch out for this fix and comeback with your comments.
Posted Date : 2005-10-13 09:12:21.0

Fix integrated in jdk 5.0u7 as of Jan 3. This should be available in the builds of jdk5.0u7 after Jan 3.
Posted Date : 2006-01-17 06:51:47.0
Comments
  
  Include a link with my name & email   

Submitted On 21-FEB-2005
cowwoc
Please note that Atlassian JIRA 3.1 depends upon this bugfix. See http://jira.atlassian.com/browse/JRA-5354 for more information.


Submitted On 24-FEB-2005
swamp_ig
This has affected the ability to run some third party libraries. Would it be so onerous to fix it in the next patch release? It's only a one line change to the source at most.


Submitted On 23-MAR-2005
janhoeve1
Yeah, please fix this one


Submitted On 01-APR-2005
craigwblake
You might want to negate the value in your fix, there. ;-)


Submitted On 29-APR-2005
Apoptosis66
This bug effects the Apache Torque framework, and the Quartz Scheduler.


Submitted On 01-MAY-2005
amit_h
Guys this is getting fixed in the current development release of Java which is code named Project Mustang.

But we will need your active support to verify the fix.


Submitted On 02-MAY-2005
Apoptosis66
Correct me if I am wrong but Mustang is java 6.0 (1.6)?  I  personally think this is not soon enough.  I have a team of developers who are fiending to move to Java 1.5 but can't because of third party libraries we rely on.  All of which are waiting for this bug to fix.  I think it would be a shame to make everyone wait a whole release, for what appears to be a one or two line fix.  What is the issue with getting this into 1.5 update 4?


Submitted On 06-JUL-2005
vor23
To avoid the stack overflow in the proposed solution, use this instead:

public int compareTo(java.util.Date d) {
    return (d instanceof Timestamp) ? compareTo((Timestamp) d) : d.compareTo(this);
}


Submitted On 13-JUL-2005
Apoptosis66
So maybe 1.5 Update 5 :)


Submitted On 08-SEP-2005
This needs to get fixed in 1.5. This does introduce backwards incompatibility that is only detectable in run-time, not in compile time.


Submitted On 19-SEP-2005
Apoptosis66
So maybe 1.5 Update 6?  This is getting nuts.  How are major features like changes to LDAP Api going into updates, where as this regression bug, that is a simple fix does not?


Submitted On 06-OCT-2005
obsidian
What's the point of making everyone wait years for this fix? There is clearly no problem doing bugfix releases. This absolutely should be fixed in the next one. 

Moving to 1.5 is a big problem for most people today  (if not altogether impossible) - __because of bugs like this__. 

If you won't fix this in 1.5, you may as well not fix it at all. 1.6 will introduce 100 new showstoppers that you won't fix until 1.7... and the cycle will continue...  


Submitted On 11-OCT-2005
smithk10
why is sun holding java developers hostage?   going to have to stay on 1.4 and then move to a non-java solution.    13 months since being reported!  insane.


Submitted On 26-OCT-2005
matt@slc
How about:

public int compareTo(Date d) {
  return (d instanceof Timestamp) ?
    compareTo((Timestamp)d) :
    -d.compareTo(this);
}


Submitted On 02-MAR-2006
asioanid
please, can you guys at sun give us a statement about the scheduling of jdk5.0u7? we have lots of banking software which cannot be run under 5.0 cuz of this bug :-((


Submitted On 15-MAR-2006
rmcgeary
18 months and this backwards compatibility issue still isn't resolved?  Truthfully, this should have been fixed before 1.5 came out of beta.  How long until 1.5u7?  How sad.


Submitted On 23-APR-2006
wbolivar
What is going on with this bug? We have been waiting for the resolution of this stuff but is still there, you said this bug was included on the jdk5.0u7 on January the 2th but that version dose not exist yet.


Submitted On 14-JUN-2006
nrkonjeti
I think there is a fix in 5.0 release.


Submitted On 14-JUN-2006
nrkonjeti
check 5.0 , it is solved no need to use third party solutions


Submitted On 14-JUN-2006
nrkonjeti
I think there is a fix in 5.0 release.


Submitted On 06-OCT-2006
down
down



PLEASE NOTE: JDK6 is formerly known as Project Mustang