Hi!

  I see the point of your solution (doing whatever has to be done as soon as 
possible), but like Mike, I believe it has many problems:

  1) Your delegate works for situations where different attributes of the same 
object are modified by different threads. You merge the changes made by the 
first thread into the second thread EC, and when you finally save, you have the 
object with all the changes applied. But what about the situation where both 
threads changed the same attribute? On the example I sent you some days ago, 
the attribute is a sort-of counter, so the final value depends on the initial 
one. If you ignore the changes made by other threads, you will be corrupting 
your logic. You need to be notified in the most catastrophic way possible that 
you WILL corrupt data if you save. Of course, you could write a specific 
delegate for that, but...

  2) ... as said, your delegate can not throw an exception in the correct 
thread, which would be the best way to tell you to stop whatever you are doing 
and start all over again. So I add my voice to Mike's and I ask again, how can 
you make the second thread be notified of the problem? :)

  3) You *still* have to deal with inter-instances OL exceptions, and write 
code for that. Why write two pieces of code in different places to do the same 
thing? :)

  4) All this depends a lot on what you are trying to do. In Survs, for 
instance, there are some situations where we read a lot of objects, process 
them, and save them. This has to be done with all the possible guarantees that 
no other thread or instance is modifying the same values. The logic is so 
complex that I simply don't care about dealing "gracefully" with this. If it 
fails, I throw it all away and try to do everything again. So, I still would 
need that exception, or any other mechanism that prevented me from saving (and, 
by consequence, corrupting) my data.

  5) Even if the delegate has some way of throwing the exception in the correct 
thread, you would have to be ready to catch that exception during the whole 
EC's existence and not only during the saving. That would lead to more complex 
code and error handling.

  And, BTW, another detail for the most curious readers...

>> Application.Application: C1 1274149686265
>> Application.Application: C2 1274149686265

  If this attribute was an integer or long (with the timestamp, for instance) 
and not a string, in this specific situation, the second commit would not 
produce any SQL statement. Why? :)

  Yours

Miguel Arroz

On 2010/05/18, at 03:33, Mark Ritchie wrote:

> Hey Mike!
> 
> On 17/May/2010, at 4:24 PM, Mike Schrag wrote:
>> so here's your challenge ... make this fail with an optimistic lock 
>> exception when EC2 saves (which is what would happen if EC1 was in another 
>> instance):
> 
> But that's the point...  When an EO in your application changes, you are 
> notified via the delegate!  You don't have to wait until you try to 
> saveChanges and get the exception.  I agree with what others have posted 
> recently on this topic, getting notified of a collision at the earliest point 
> is much preferred!
> 
> As to the rest of it, I think that you're making it way too complicated...
> My delegate works just fine at caching the changes and applying them later:
> <MarksDelegate.java>
> 
> This is what I've used in the past (since ObjC days) and I don't know of a 
> case where it fails.
> M.
> 
> P.S.  My run log looks like this (after the 100 objects are created):
> 
> 
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  -  evaluateExpression: 
> <com.webobjects.jdbcadaptor.MySQLPlugIn$MySQLExpression: "SELECT t0.id, 
> RTRIM(t0.name) FROM Company t0" withBindings: >
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  - 100 row(s) processed
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  -  === Commit Internal 
> Transaction
> Application.Application: ec0 = er.extensions.eof.er...@7fd88db7
> Application.Application: ec1 = er.extensions.eof.er...@524c71d2
> Application.Application: ec2 = er.extensions.eof.er...@49198ff2
> Application.Application: Company 98
> Application.Application: Company 98
> Application.Application: Company 98
> 
> C1 updated, not saved.
> Application.Application: Company 98
> Application.Application: C1 1274149686265
> Application.Application: Company 98
> 
> C2 updated, not saved.
> Application.Application: Company 98
> Application.Application: C1 1274149686265
> Application.Application: C2 1274149686265
> 
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  -  === Begin Internal 
> Transaction
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  -  evaluateExpression: 
> <com.webobjects.jdbcadaptor.MySQLPlugIn$MySQLExpression: "UPDATE Company SET 
> name = ? WHERE (id = ? AND name = ?)" withBindings: 1:"C1 
> 1274149686265"(name), 2:89(id), 3:"Company 98"(name)>
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  -  === Commit Internal 
> Transaction
> MarksDelegate.editingContext: er.extensions.eof.er...@49198ff2 
> shouldMergeChangesForObject: eo = <your.app.eo.Company 2d397e5c 
> _EOIntegralKeyGlobalID[Company (java.lang.Integer)89]>
> MarksDelegate.editingContext: er.extensions.eof.er...@49198ff2 
> didMergeChanges:
> MarksDelegate.editingContext: er.extensions.eof.er...@7fd88db7 
> shouldInvalidateObject: eo = <your.app.eo.Company 51701bdc 
> _EOIntegralKeyGlobalID[Company (java.lang.Integer)89]>
> MarksDelegate.editingContext: er.extensions.eof.er...@7fd88db7 
> didMergeChanges:
> MarksDelegate.editingContext: er.extensions.eof.er...@524c71d2 
> shouldInvalidateObject: eo = <your.app.eo.Company 1c2006a0 
> _EOIntegralKeyGlobalID[Company (java.lang.Integer)89]>
> MarksDelegate.editingContext: er.extensions.eof.er...@524c71d2 
> didMergeChanges:
> C1 saved.
> Application.Application: C1 1274149686265
> Application.Application: C1 1274149686265
> Application.Application: C2 1274149686265
> 
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  -  === Begin Internal 
> Transaction
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  -  evaluateExpression: 
> <com.webobjects.jdbcadaptor.MySQLPlugIn$MySQLExpression: "UPDATE Company SET 
> name = ? WHERE (id = ? AND name = ?)" withBindings: 1:"C2 
> 1274149686265"(name), 2:89(id), 3:"C1 1274149686265"(name)>
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  -  === Commit Internal 
> Transaction
> MarksDelegate.editingContext: er.extensions.eof.er...@524c71d2 
> shouldInvalidateObject: eo = <your.app.eo.Company 1c2006a0 
> _EOIntegralKeyGlobalID[Company (java.lang.Integer)89]>
> MarksDelegate.editingContext: er.extensions.eof.er...@524c71d2 
> didMergeChanges:
> MarksDelegate.editingContext: er.extensions.eof.er...@7fd88db7 
> shouldInvalidateObject: eo = <your.app.eo.Company 51701bdc 
> _EOIntegralKeyGlobalID[Company (java.lang.Integer)89]>
> MarksDelegate.editingContext: er.extensions.eof.er...@7fd88db7 
> didMergeChanges:
> MarksDelegate.editingContext: er.extensions.eof.er...@49198ff2 
> shouldInvalidateObject: eo = <your.app.eo.Company 2d397e5c 
> _EOIntegralKeyGlobalID[Company (java.lang.Integer)89]>
> MarksDelegate.editingContext: er.extensions.eof.er...@49198ff2 
> didMergeChanges:
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  -  === Begin Internal 
> Transaction
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  -  evaluateExpression: 
> <com.webobjects.jdbcadaptor.MySQLPlugIn$MySQLExpression: "SELECT t0.id, 
> RTRIM(t0.name) FROM Company t0 WHERE t0.id = ?" withBindings: 1:89(id)>
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  - 1 row(s) processed
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  -  === Commit Internal 
> Transaction
> C2 saved.
> Application.Application: C2 1274149686265
> Application.Application: C2 1274149686265
> Application.Application: C2 1274149686265
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  - The URL for webserver 
> connect is:
> http://17.246.48.60/cgi-bin/WebObjects/UseTheDelegate.woa/-49584
> The URL for direct connect is:
> http://17.246.48.60:49584/cgi-bin/WebObjects/UseTheDelegate.woa
> May 17 19:28:06 UseTheDelegate[49584] WARN  NSLog  - 
> May 17 19:28:06 UseTheDelegate[49584] WARN  
> er.extensions.appserver.ERXApplication  - You are running in development mode 
> with WOAutoOpenInBrowser = false.  No browser will open and it will look like 
> the application is hung, but it's not.  There's just not a browser opening 
> automatically.
> May 17 19:28:06 UseTheDelegate[49584] DEBUG NSLog  - Waiting for requests...
> 
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/webobjects-dev/arroz%40guiamac.com
> 
> This email sent to ar...@guiamac.com


Attachment: smime.p7s
Description: S/MIME cryptographic signature

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to