gwtproject / gwt

GWT Open Source Project
http://www.gwtproject.org
1.53k stars 377 forks source link

Consider adding BaseProxy.clone() #5793

Open dankurka opened 9 years ago

dankurka commented 9 years ago

Originally reported on Google Code with ID 5794

A ValueProxy.clone() method should be pretty straightforward since it has no identity
concept.

EntityProxy.clone() can be accomplished with a call to RequestFactory.find(), but this
will necessitate a round-trip to the server (pending some kind of caching semantics).
 Cloning a mutable EntityProxy doesn't make sense, as the mutable state must be associated
with exactly one RequestContext.  

http://groups.google.com/group/google-web-toolkit-contributors/t/a211fa044625866b

Reported by bobv%google.com@gtempaccount.com on 2010-12-22 13:57:13

dankurka commented 9 years ago
Instead of a clone() method, maybe consider adding a RequestContext#create overload
(or a copy() method):

  public <T extends BaseProxy> T create(java.lang.Class<T> clazz, T toCopy);

or maybe without the Class<T> argument?

  public <T extends BaseProxy> T copy(T toCopy);

Or just call the method BaseProxy#copy() or similar.

Rationale: http://checkstyle.sourceforge.net/config_coding.html#NoClone

Reported by t.broyer on 2011-01-09 16:02:38

dankurka commented 9 years ago

Reported by bobv%google.com@gtempaccount.com on 2011-01-13 18:41:47

dankurka commented 9 years ago

Reported by bobv%google.com@gtempaccount.com on 2011-01-13 18:42:32

dankurka commented 9 years ago
There might be a need for being able to clone mutable entities between contexts: once
the context has been fired and it failed, it's not reusable, so your changes to the
entities are kind of "lost".
See https://groups.google.com/d/topic/google-web-toolkit/Qwnh5g8suNg/discussion and
issue 6007

Reported by t.broyer on 2011-02-19 00:03:20

dankurka commented 9 years ago

Reported by bobv%google.com@gtempaccount.com on 2011-06-13 13:56:37

dankurka commented 9 years ago
The scenario Thomas is describing in comment 4 is of great interest to us.

We don't want our users to lose all of their changes just because one field failed
server-side validation, especially on complex forms.  It would be very handy to be
able to clone the object client-side so we could just allow the user to make more edits
and send it again.

Reported by ericandresen on 2011-07-26 20:30:47

dankurka commented 9 years ago
Are there any plans this future to be added in GWT 2.4 or 2.5 ?

Reported by MGenov on 2011-08-23 07:11:37

dankurka commented 9 years ago
For cloning proxies I've been using this with success. I haven't completely tested it
with nested objects or against entity proxies (we're not using them yet). 

 public static <T extends BaseProxy> T cloneProxyToNewContext(Class<T> clazz, T proxy,
            RequestContext context) {
        T newProxy = context.create(clazz);
        AutoBean<T> oldBean = AutoBeanUtils.getAutoBean(proxy);
        AutoBean<T> newBean = AutoBeanUtils.getAutoBean(newProxy);
        AutoBeanCodex.decodeInto(AutoBeanCodex.encode(oldBean), newBean);
        newBean.setFrozen(true);
        newProxy = newBean.as();
        context.edit(newProxy);
        return newProxy;

    }

Reported by larsenje on 2011-09-21 14:29:15

dankurka commented 9 years ago
I tested the method above with an EntityProxy and I get a "
java.lang.UnsupportedOperationException: Cycles not supported" exception. The fact
that my proxies form a cycle had never been a problem so far...

Reported by caveden on 2011-12-20 13:53:28

dankurka commented 9 years ago
RF supports arbitrary graphs, but not AutoBeans. While RF proxies are AutoBeans, RF
does not use AutoBeans serialization for them. You can however use AutoBeanUtils.

Have a look at how AbstractRequestContext clones proxies when you edit them: it uses
an AutoBeanVisitor to collect property values and then push them (recursively cloning
them if they're collections or other proxies) into the clone.
It should be possible to reuse that code in a create() overload or copy() method added
to RequestContext, as I proposed earlier.

Reported by t.broyer on 2011-12-20 14:36:58

dankurka commented 9 years ago
Just made a patch about this one at: http://gwt-code-reviews.appspot.com/1620804/

Reported by MGenov on 2011-12-26 13:08:36

dankurka commented 9 years ago
This would also be useful for cloning the original proxy fetched before being edit()'d
by the request in case of any server errors so that the updates can be reapplied.

Reported by shang.xiao.sanders on 2012-05-15 07:24:09

dankurka commented 9 years ago
Hi all,

I am not sure if any update on GWT 2.4 or 2.5 changed this behaviour, so i do not really
know where to post this, but this seemed like the best place to me anyway.

Well, my issue is i am trying to apply the cloneProxyToNewContext workaround, but the
moment i invoke context.edit (newProxy) i get an "Unfrozen bean with null RequestContext"
exception. I am using the exact code as in the workaround. In other posts i saw that
setFrozen (true) should be called before the edit, but that is already there. Is anybody
using this workaround (or any other) in GWT 2.5, or am i missing something?

Btw, the cloning seems to work perfect with my cycle-less entityProxies.

Thx!

Reported by grodriguez2006 on 2013-03-11 15:56:49

dankurka commented 9 years ago
What about this issue? The patch is ready since 2011. It would be great to see it integrated
on 2.6.

Reported by lunarjchav on 2013-06-18 20:06:20

dankurka commented 9 years ago
The patch is far from being "ready". With the current RF design, cloning would be almost
useless. I think we should rather relax the constraint that a proxy can only be edit()ed
in one RequestContext at a time; AFAICT there's no real reason for that constraint
(there was one in earlier versions of RF where it tried to keep the proxies synchronized
with the server-side domain objects, but that no longer holds I believe).

Reported by t.broyer on 2013-06-19 14:46:12

dankurka commented 9 years ago
I think you are right. Removing the constraint which requires to edit a proxy in only
one RequestContext could solve several real daily problems and to avoid the necessity
of implementing this clone() method. 

Im not sure about which is the roadmap of RF on the further versions (or if it exists)
but I hope it relaxes some constraint which sometimes make the daily work with RF a
little bit though.

Reported by lunarjchav on 2013-06-19 15:00:43

dankurka commented 9 years ago
I see the same "Unfrozen bean with null RequestContext" exception as in post #13. By
stepping through the request context code I found that this message came from a referenced
bean. The primary bean has already been set to be frozen, which avoids this message
for this one bean, but all other beans are non-frozen with no request context assigned.
It would be nice to see some sort of solution to this problem.

Reported by stigrv on 2014-04-30 13:05:06

dankurka commented 9 years ago
It seams this bug is not moving, it is good to make it difficult to do a thing differently
than the "standard", but when it becomes too diffcult, the solutions might cheat to
get the wanted result. For example use the validation process instead of the regular
RF method to avoid having to duplicate the proxies...

So +1 for this feature request

Reported by zhamdi.into on 2014-08-19 14:44:45

dankurka commented 9 years ago
I also need this to avoid lost changes. Using find is not an answer as you may have
been in the middle of editing the object and find just gives you what you had before
you started editing.
As Thomas said in comment 4, after such a server failure your changes are lost at present.
Not sure how to deal with this in the UI in a user acceptable way. Does anyone have
any other solid workarounds regarding this problem (nothing yet posted seems entirely
satisfactory :( )?
Again, +1 for the feature request regarding cloning.

Reported by darren.hurt on 2014-09-19 16:30:05

dankurka commented 9 years ago
I just use this code snippet and works for my needs, maybe it can help you.

http://stackoverflow.com/a/20180605/1815133

Reported by nicolasps on 2014-09-20 10:15:14