Found in GWT Release (e.g. 1.5.3, 1.6 RC):
GWT 2.1.1
Encountered on OS / Browser (e.g. WinXP, IE6-7, FF3):
All
Detailed description (please be as specific as possible):
RequestContext.isChanged implementation done in the AbstractRequestContext relies on AutobeanUtils.diff(x,y) to detect if the edited proxies were modified or not.
But this is incorrect in the following example :
1/ Entity A has a collection of entities B (many-to-many relationship). 2/ A view/editor focuses on editing an entity A with a custom widget (derived from ValueListBox) to handle the collection of entities B 2/ An entitiy A is edited with the collection of entities B in the requestContext 3/ If no modifications are done, requestContext.isChanged returns TRUE
=> This is due to AutobeanUtils.diff(x,y) that performs the equality of the 2 collections of entities B on the 'equals' method of the Collection objects.
Proposal : Why dont use something like AutobeanUtils.deepEquals that performs equality of collections based on equality of the elements of the collection ?
Shortest code snippet which demonstrates issue (please indicate where actual result differs from expected result):
Workaround if you have one: I'm looking for it
Links to relevant GWT Developer Forum posts:
Comment #1
Posted on Jan 31, 2011 by Swift RhinoIm not sure if exactly the same problem.
final DICT_TERMRequest rc = requestFactory.dICT_TERMRequest(); rc.findDICT_TERM("1234")/.with("lAST_MODIFIED_BY_OID")/.to(new Receiver() {
@Override
public void onSuccess(DICT_TERMProxy response) {
rftest.proxy = response;
System.out.println(rftest.proxy);
}
}).fire();
final DICT_TERMRequest rc2 = requestFactory.dICT_TERMRequest(); System.out.println("changed before edit start: " + rc2.isChanged()); DICT_TERMProxy edited = rc2.edit(rftest.proxy); System.out.println("changed after edit start: " + rc2.isChanged());
results in:
{CREATED_AT=Mon Sep 20 17:15:19 CEST 2010, TERM_KEY=key1, LAST_MODIFIED_AT=Tue Oct 19 10:26:12 CEST 2010, DICT_DESCRIPTION=v1, Id=1234, Version=11} changed before edit start: false changed after edit start: false
when '.with("lAST_MODIFIED_BY_OID")' uncomented:
{LAST_MODIFIED_BY_OID={USER_ID=root, Id=0, Version=1}, CREATED_AT=Mon Sep 20 17:15:19 CEST 2010, TERM_KEY=key1, LAST_MODIFIED_AT=Tue Oct 19 10:26:12 CEST 2010, DICT_DESCRIPTION=v1, Id=1234, Version=11} changed before edit start: false changed after edit start: true
Comment #2
Posted on Feb 13, 2011 by Swift RhinoComment #3
Posted on Aug 28, 2011 by Helpful WombatThis issue (i.e. not deep checking) causes a performance problem ...
Consider the case when the client obtains a bunch of data and caches it somewhere. For example, at the start of the application, we obtain an object graph for the currently logged in user. Note that the objects we receive have their request context tag in their bean set to null by request factory.
After some time, in response to user actions, the cached data has to be modified, so we'd call request.edit(cachedData). Now, when we actually fire the request, it will think the entire object graph has changed, and ends up sending everything that we cached.
So, when does request factory actually send diff'd data?
The only workaround we have right now is to fetch a single object using find(..) without its object graph, edit the single object, and send back. However, this means two round trips. If we have multiple requests, we can queue multiple find's in the first request and do a bulk update in the second request, which is still two round trips.
Any suggestions?
Comment #4
Posted on Aug 29, 2011 by Helpful WombatLooking for workarounds...
My first workaround was to write a customized RequestContext impl class. This was a little unsuccessful, given I couldn't delegate addInvocation(..) method to a dynamically generated RequestContext class from RF.
Second workaround was to do a little hack before I edit the object: AutoBean bean = AutoBeanUtils.getAutoBean(parentObject); bean.setTag(Constants.REQUEST_CONTEXT, request); request.edit(bean.as());
That tries to take advantage of the weak mapping cache but that doesn't work too, because the parent object's request context is somehow set back to null just before the equals is called on the bean.
Are there any workarounds?
For reference:
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/e752268c76c300fc
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/d34d48adbfbeb21d
Comment #5
Posted on Sep 16, 2011 by Grumpy RhinoComment deleted
Comment #6
Posted on Sep 16, 2011 by Grumpy Rhino*Found in GWT Release (e.g. 1.5.3, 1.6 RC): GWT 2.4
*Encountered on OS / Browser (e.g. WinXP, IE6-7, FF3): All
*Detailed description (please be as specific as possible):
Im facing the same issue :( https://groups.google.com/forum/#!topic/google-web-toolkit/zyJ4EVxEwfM
It is one of the key feature of RequestFactory
"keeps track of objects that have been modified and sends only changes to the server, which results in very lightweight network payloads"
Comment #7
Posted on Sep 28, 2011 by Quick RabbitThe problem with isChanged is that it uses AutoBeanUtils.diff which ends up using EntityProxyCategory.equals which returns its value using: return stableId(bean).equals(stableId(other)) && requestContext(bean) == requestContext(other);
The original object, which is stored under the PARENT_OBJECT tag in the AutoBean does not have a requestContext, so it will fail on the last part.
Comment #8
Posted on Dec 2, 2011 by Swift Rhino+1 to Kevin's analysis. I don't know what I was thinking about in my proposed patch back in February.
Anyway, I'm working on a real fix for this issue: making equals() evaluate to 'true' when diff'ing a mutable AutoBean and its immutable "parent" (but keep the old behavior otherwise, for backwards compatibility: there must have been a reason for it)
Comment #9
Posted on Dec 4, 2011 by Swift RhinoNew patch sent for review: http://gwt-code-reviews.appspot.com/1601806/
Comment #10
Posted on Dec 22, 2011 by Happy Wombat+++ Vote +++ Sending only changes to server is a very important feature. Especially it allows a very simple for of optimistic concurrency. Currently we are loosing collection members when adding from two browser sites at the same time. I'll try the patches next year ;-)
Comment #11
Posted on May 31, 2012 by Swift RhinoCommitted at r11004
Comment #12
Posted on May 31, 2012 by Swift Rhino(No comment was entered for this change.)
Comment #13
Posted on Jun 1, 2012 by Quick GiraffeWoo! I have clients waiting for this to be fixed :D
Comment #14
Posted on Jun 27, 2012 by Happy ElephantBulk edit: should be fixed in the GWT 2.5 release candidate.
Status: Fixed
Labels:
Category-RPC
Milestone-2_5