Good points. So what kind of solution do you propose. Eliminating synchronization would lead to __equalsCalc being corrupted in a multi-threaded situation. Keeping synchronization could lead to deadlock. But if the __equalsCalc state information is eliminated completely, there will be an infinite loop problem and incorrect behavior.
I also want to point out the eliminating the equals() method and reverting to Object.equals will break the tests. The only solution is to make __equalsCalc a singleton static item in the system and synchronize on it. This would cause all generated equals logic to wait.... Comments. Rich Scheuerle IBM WebSphere & Axis Web Services Development 512-838-5115 (IBM TL 678-5115) Eric.D.Friedman@Wel lsFargo.COM To: [EMAIL PROTECTED] cc: 12/19/2002 04:14 PM Subject: RE: Q. about equals() in WSDL generated datatypes Please respond to axis-dev I'm not Stephen, but I'd like to join this thread, as I think there's a more subtle problem here: // Stephen pointed out that we can never recurse back // because the method is syncronized... // or does syncronization know that I am recursing back // in the same thread. The lock on the object with the synchronized method belongs to your thread, so yes, it's possible to call a synchronized method recursively from within a single thread, just as it's possible to invoke other synchronized methods on that same object. There's a bigger problem here, however: synchronizing equals() methods in this manner could result in thread deadlock if the objects in question are deeply self referential. Look at the calls to exchange.equals() and number.equals() in the code below. Now imagine that number has a backreference to Phone and so its equals() method needs to invoke Phone.equals() for the same reason that Phone's equals() method needs to invoke number.equals(). Further suppose that two threads are active: one invokes Phone.equals() while the other one calls number.equals() for some other purpose. Both threads will be deadlocked, since neither equals() method can terminate until the other relinquishes the lock. This is a danger inherent in code generation of this kind, and I suggest that the right thing to do is to leave synchronization to the user of the object -- it's just not possible (read: too expensive) to adequately handle all of the cases that a tool like wsdl2java would have to deal with. My unsolicited 2 cents, Eric -----Original Message----- From: R J Scheuerle Jr [mailto:[EMAIL PROTECTED]] Sent: Thursday, December 19, 2002 1:46 PM To: [EMAIL PROTECTED] Subject: RE: Q. about equals() in WSDL generated datatypes Here's the full annotated code (for Phone). I think the bug is that __equalsCalc must be be reset before returning. So I marked this as red. Please evaluate and send me your comments. Also think of the equals evaluating to different linked lists that contain the same data. Lets assume A1->A2->A3 equals B1->B2->B3 Now change the above slightly so the linked lists are circular. A1->A2->A3 equals B1->B2->B3 ^-------+ ^--------+ They are still the same, and the equals method should return true. This is the case handled by __equalsCalc == obj Now change the linked lists in a more devious way. A1->A2->A3 equals B1->B2->B3->A1->A2->A3 ^-------+ ^-------------------+ In this situation, the equals method should return false since the looping is different. In the first case, the third object points back to the initial object. In the second case, the third element points to an object other than the initial object. This is the case handled by __equalsCalc != obj. private java.lang.Object __equalsCalc = null; public synchronized boolean equals(java.lang.Object obj) { // Return false immediately if wrong types if (!(obj instanceof Phone)) { __equalsCalc = null; return false;} // Return false if other object is null Phone other = (Phone) obj; if (obj == null) { __equalsCalc = null; return false; } // Return true if == if (this == obj) { __equalsCalc = null; return true; } // if equalsCalc is set, then we have looped // back to the "this" object. Since the last time through // we set _equalsCal to the other object, return // true if the equalsCalc == the other object (the // the other object loops the same way) or return // false if the equalsCalc != the other object (the other // object does not loop the same way.) // Stephen pointed out that we can never recurse back // because the method is syncronized... // or does syncronization know that I am recursing back // in the same thread. if (__equalsCalc != null) { boolean rc = (_equalsCalc == obj); __equalsCalc = null; return rc; } // Flow to here indicates no recursion, so set _equalsCalc // to the other object in-case recursion occurs in the following code. __equalsCalc = obj; boolean _equals; _equals = true && areaCode == other.getAreaCode() && ((exchange==null && other.getExchange()==null) || (exchange!=null && exchange.equals(other.getExchange()))) && ((number==null && other.getNumber()==null) || (number!=null && number.equals(other.getNumber()))); // Always reset __equalsCalc before returning. __equalsCalc = null; return _equals; } Rich Scheuerle IBM WebSphere & Axis Web Services Development 512-838-5115 (IBM TL 678-5115) Glen Daniels <gdaniels@macrome To: "'[EMAIL PROTECTED]'" <[EMAIL PROTECTED]> dia.com> cc: Subject: RE: Q. about equals() in WSDL generated datatypes 12/19/2002 07:59 AM Please respond to axis-dev Hi Rich! Hm - I'm trying to imagine an example for when this would actually get used, and having trouble coming up with one. Could you elucidate? I guess what I'm really asking is why doesn't "if (this == obj) return true" catch this? --G P.S. Nice to see you back! > -----Original Message----- > From: R J Scheuerle Jr [mailto:[EMAIL PROTECTED]] > Sent: Wednesday, December 18, 2002 8:27 PM > To: [EMAIL PROTECTED] > Subject: Re: Q. about equals() in WSDL generated datatypes > > > > Yes __equalsCal was meant to support equals for objects that > had direct or > indirectly references back to the object. > > Rich Scheuerle > IBM WebSphere & Axis Web Services Development > 512-838-5115 (IBM TL 678-5115) > > > > > "Steve Loughran" > > <[EMAIL PROTECTED] To: > "axis-dev" <[EMAIL PROTECTED]> > om> cc: > > Subject: Q. > about equals() in WSDL generated datatypes > 12/18/2002 02:38 > > PM > > Please respond to > > axis-dev > > > > > > > > > > So I'm staring at the equals() method that's been generated > for me from a > datatype > > private java.lang.Object __equalsCalc = null; > > public synchronized boolean equals(java.lang.Object obj) { > if (!(obj instanceof JobInfo)) return false; > JobInfo other = (JobInfo) obj; > if (obj == null) return false; > if (this == obj) return true; > if (__equalsCalc != null) { > return (__equalsCalc == obj); > } > __equalsCalc = obj; > ...tests > __equalsCalc = null; > return _equals; > > > My q. is: what is all this __equalsCalc stuff? It implies > that if there is > a > reentrant equality test then the test would return true while > the test is > ongoing, but since the method is synchronized, you'd be hard > pressed to > call > equals() twice. > > Is that what the __equalsCalc is there for? To catch recursion? > > -steve > > > > >