RequestFactory - persist method that returns the saved Entity.

248 views
Skip to first unread message

Aidan O'Kelly

unread,
Jun 29, 2011, 1:55:47 PM6/29/11
to google-we...@googlegroups.com
So, still trying to fully understand the RequestFactory, I made myself
a small app to test having my persistence code in the entity itself.
(I have been previously working off the TurboManage
objectify+requestfactory sample, thanks David, its been very useful!)

I have an Entity called Parent, which has this method:

public Parent persistAndReturn() {
ObjectifyDao dao = new ObjectifyDao();
this.aBool = true;
Key<Parent> key = dao.ofy().put(this);
return dao.ofy().get(key);
}

In my App's RequestFactory interface, I have this:

@Service(Parent.class)
interface ParentRequestContext extends RequestContext {
InstanceRequest<ParentProxy, Void> persist();
InstanceRequest<ParentProxy, ParentProxy> persistAndReturn();
}
ParentRequestContext getParentRC();


Then when I want to create and persist a new Parent object, I do this...

ParentRequestContext rc = rf.getParentRC();
ParentProxy proxyObj = rc.create(ParentProxy.class);
(.. set some properties.. )

Request<ParentProxy> fetchRequest = rc.persistAndReturn().using(proxyObj);
fetchRequest.to(new Receiver<ParentProxy>(){
(... onSuccess Handler.. )
});

fetchRequest.fire();

However I get the 'autobean has been frozen' error (stack trace:
http://pastebin.com/NZ7280B9 )
Its clear from the stacktrace and other debug messages that the object
is persisted, but returning it fails.

So...

Is this possible? Is it desirable?

Also, if we look at the last line, fetchRequest.fire(), we could also
do rc.fire() instead of it, and get the same result.. Are we doing
the exact same operation when we call either 'fire' method?

Thanks,
Aidan.

David Chandler

unread,
Jun 29, 2011, 2:18:25 PM6/29/11
to google-we...@googlegroups.com
Hi Aidan,

I also see the AutoBeanFrozen error with persistAndReturn in GWT 2.3.0 and am looking into it. GWT 2.2.0 did not exhibit this behavior.

And yes, Request.fire() just calls RequestContext.fire(), so the effect is identical.

/dmc


--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.




--
David Chandler
Developer Programs Engineer, GWT+GAE
w: http://code.google.com/
b: http://googlewebtoolkit.blogspot.com/
t: @googledevtools

Aidan O'Kelly

unread,
Jun 29, 2011, 5:44:57 PM6/29/11
to google-we...@googlegroups.com
Ok thanks for the clarification. A bit more messing around (probably
should've tried this first) and changing the persistAndReturn method
to simply 'return this' actually works, with the returned proxy having
the newly generated ID and any server side changes that were made.

public Parent persistAndReturn() {
ObjectifyDao dao = new ObjectifyDao();
this.aBool = true;

dao.ofy().put(this);
return this;

David Chandler

unread,
Jun 29, 2011, 10:07:23 PM6/29/11
to google-we...@googlegroups.com
Aidan, thanks so much for sharing your success!

This was failing:


Key<NamedList> key = this.put(list);

return this.get(key);


but this works:

Key<NamedList> key = this.put(list);
return list;

I'll have to look closer at what changed between 2.2 and 2.3 that might be causing this.


/dmc

bloo

unread,
Oct 17, 2012, 1:57:33 PM10/17/12
to google-we...@googlegroups.com
Hi David,

I hate to bring up an old thread, but I noticed this happening with my switch from 2.4.0 to 2.5.0.  I am using JPA/Hibernate on the backend, and my entity instance's persist() method returns "this" on the server.  It stopped working with 2.5.0 with the Unfrozen bean error - BUT, it only happens when you persist an entity for the first time (not subsequent perists for update).

Just wondering if you have any insight into what would cause this.  I'm working around this by calling Request.find(EntityStableId) after the successful persist() call ONLY IF it was a new object being persisted (it is not necessary to do that for subsequent updates to the object).

Thanks!

>> For more options, visit this group at
>> http://groups.google.com/group/google-web-toolkit?hl=en.
>>
>
>
>
> --
> David Chandler
> Developer Programs Engineer, GWT+GAE
> w: http://code.google.com/
> b: http://googlewebtoolkit.blogspot.com/
> t: @googledevtools
>
> --
> You received this message because you are subscribed to the Google Groups
> "Google Web Toolkit" group.
> To post to this group, send email to google-we...@googlegroups.com.
> To unsubscribe from this group, send email to

> For more options, visit this group at
> http://groups.google.com/group/google-web-toolkit?hl=en.
>

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-toolkit+unsub...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.

Thomas Broyer

unread,
Oct 17, 2012, 2:22:21 PM10/17/12
to google-we...@googlegroups.com


On Wednesday, October 17, 2012 7:57:33 PM UTC+2, bloo wrote:
Hi David,

I hate to bring up an old thread, but I noticed this happening with my switch from 2.4.0 to 2.5.0.  I am using JPA/Hibernate on the backend, and my entity instance's persist() method returns "this" on the server.  It stopped working with 2.5.0 with the Unfrozen bean error - BUT, it only happens when you persist an entity for the first time (not subsequent perists for update).

Just wondering if you have any insight into what would cause this.  I'm working around this by calling Request.find(EntityStableId) after the successful persist() call ONLY IF it was a new object being persisted (it is not necessary to do that for subsequent updates to the object).

Could you post the payloads exchanged? (capture them with your browser, Wireshark, or set the gwt.rpc.dumpPayload system property to true on your server and it'll print them to System.out)
Preferably the smallest request that fails so it's easier to read ;-)

bloo

unread,
Jan 16, 2013, 10:21:48 PM1/16/13
to google-we...@googlegroups.com
Hi Thomas - I was not tracking my own question here! I apologize. I'm still hacking around this - that is, returning my new instance from my InstanceRequest "persist()", then turning around and doing a find(response.stableId()) on it to get a usable EntityProxy. I'll paste the wire data below - it was the smallest back-and-forth in my app I could find. Let me know if you need me to dig something else up for this or help decipher anything.

>>> {"F":"com.app.web.shared.bindery.AppServiceRequestFactory","I":[{"O":"gYfjUQeKypl3aT70L$lmyH$je_Q=","P":[[]]}]}
>>> {"F":"com.app.web.shared.bindery.AppInstanceRequestFactory","I":[{"O":"mZy6R_9WbCm4npb8ui4de53bLjM=","P":[{"R":"1","C":1,"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ="}],"R":["product.type","images"]}],"O":[{"O":"PERSIST","R":"1","C":1,"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","P":{"product":{"R":"1","C":2,"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow="},"vendor":{"S":"IjQi","T":"NMnlePAPPa8$chg1XXK6I_qmRTc="},"defaultQuantity":100,"defaultUnit":"lb.","name":"foo","defaultPrice":"10","images":[]}},{"O":"PERSIST","R":"1","C":2,"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","P":{"type":{"S":"IjEi","T":"vCoN_GmihaJOTBwUCW2N_JPjlaY="},"name":"foo"}},{"O":"UPDATE","S":"IjEi","T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","V":"MC4w"}]}
<<< {"S":[true],"I":[null]}
<<< {"S":[true],"O":[{"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","V":"MC4w","P":{"product":{"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","S":"IjkwIg=="},"id":"90","defaultQuantity":100,"name":"foo","images":[],"defaultUnit":"lb.","active":true,"defaultPrice":"10"},"S":"IjkwIg==","C":1,"O":"PERSIST"},{"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","V":"MC4w","P":{"name":"foo","type":{"T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","S":"IjEi"}},"S":"IjkwIg==","C":2,"O":"PERSIST"},{"T":"NMnlePAPPa8$chg1XXK6I_qmRTc=","V":"Ni4w","S":"IjQi","O":"UPDATE"},{"T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","V":"MC4w","P":{"name":"Other"},"S":"IjEi","O":"UPDATE"}],"I":[{"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","S":"IjkwIg=="}]}
>>> {"F":"com.app.web.shared.bindery.AppInstanceRequestFactory","I":[{"O":"?","P":[{"S":"IjkwIg==","T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ="}],"R":["product.type","images"]}]}
<<< {"S":[true],"O":[{"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","V":"MC4w","P":{"product":{"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","S":"IjkwIg=="},"id":"90","defaultQuantity":100,"name":"foo","images":[],"defaultUnit":"lb.","active":true,"defaultPrice":"10.00"},"S":"IjkwIg==","O":"UPDATE"},{"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","V":"MC4w","P":{"name":"foo","type":{"T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","S":"IjEi"}},"S":"IjkwIg==","O":"UPDATE"},{"T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","V":"MC4w","P":{"name":"Other"},"S":"IjEi","O":"UPDATE"}],"I":[{"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","S":"IjkwIg=="}]}


(I have a hunch that on the server side, an incomplete @Entity is being passed to the GWT serializing code before the @Transaction demarcation completes and the entity in memory is totally updated. Hunch.. I am not certain.)

Thomas Broyer

unread,
Jan 17, 2013, 4:24:26 AM1/17/13
to google-we...@googlegroups.com
Just noticed: you're saying you have an "Unfrozen bean with null RequestContext" assertion error?
If that's the case (wrt "AutoBean has been frozen" error as originally reported in this thread), can you put a breakpoint in AbstractRequestContext's checkStreamsNotCrossed and try to understand which proxy is causing the issue? (that's only a start, but could help build a testcase)

bloo

unread,
Jan 17, 2013, 4:54:17 PM1/17/13
to google-we...@googlegroups.com
So when I comment out the "refresh via find(stableId()) after receiving persist()'s response EntityProxy" and simply use the response EntityProxy as-is, the error gets thrown when I attempt to re-edit it.

It's not thrown when checkStreamsNotCrossed processes the parent EntityProxy (called CatalogItemProxy), but one of it's children (which is created at the same time, they have a 1-to-1 relationship with each other) called ProductProxy (path="product"). This was unexpected to me.

Here's the wire data without the refresh via find(stableId())

>>> {"F":"com.plovgh.web.shared.bindery.PlovghServiceRequestFactory","I":[{"O":"gYfjUQeKypl3aT70L$lmyH$je_Q=","P":[[]]}]}

<<< {"S":[true],"I":[null]}

>>> {"F":"com.plovgh.web.shared.bindery.PlovghInstanceRequestFactory","I":[{"O":"mZy6R_9WbCm4npb8ui4de53bLjM=","P":[{"R":"1","C":5,"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ="}],"R":["product.type","images"]}],"O":[{"O":"PERSIST","R":"1","C":5,"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","P":{"product":{"R":"1","C":6,"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow="},"vendor":{"S":"IjQi","T":"NMnlePAPPa8$chg1XXK6I_qmRTc="},"defaultQuantity":100,"defaultUnit":"lb.","name":"foo","defaultPrice":"10","images":[]}},{"O":"PERSIST","R":"1","C":6,"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","P":{"type":{"S":"IjEi","T":"vCoN_GmihaJOTBwUCW2N_JPjlaY="},"name":"foo"}},{"O":"UPDATE","S":"IjEi","T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","V":"MC4w"}]}

<<< {"S":[true],"O":[{"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","V":"MC4w","P":{"product":{"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","S":"Ijk0Ig=="},"id":"94","defaultQuantity":100,"name":"foo","images":[],"defaultUnit":"lb.","active":true,"defaultPrice":"10"},"S":"Ijk0Ig==","C":5,"O":"PERSIST"},{"T":"NMnlePAPPa8$chg1XXK6I_qmRTc=","V":"Ni4w","S":"IjQi","O":"UPDATE"},{"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","V":"MC4w","P":{"name":"foo","type":{"T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","S":"IjEi"}},"S":"Ijk0Ig==","C":6,"O":"PERSIST"},{"T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","V":"MC4w","P":{"name":"Other"},"S":"IjEi","O":"UPDATE"}],"I":[{"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","S":"Ijk0Ig=="}]}


Here's another persist request with a subsequent refresh:


>>> {"F":"com.plovgh.web.shared.bindery.PlovghServiceRequestFactory","I":[{"O":"gYfjUQeKypl3aT70L$lmyH$je_Q=","P":[[]]}]}

<<< {"S":[true],"I":[null]}

>>> {"F":"com.plovgh.web.shared.bindery.PlovghInstanceRequestFactory","I":[{"O":"mZy6R_9WbCm4npb8ui4de53bLjM=","P":[{"R":"1","C":1,"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ="}],"R":["product.type","images"]}],"O":[{"O":"PERSIST","R":"1","C":1,"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","P":{"product":{"R":"1","C":2,"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow="},"vendor":{"S":"IjQi","T":"NMnlePAPPa8$chg1XXK6I_qmRTc="},"defaultQuantity":100,"defaultUnit":"lbs.","name":"foo","defaultPrice":"10","images":[]}},{"O":"PERSIST","R":"1","C":2,"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","P":{"type":{"S":"IjEi","T":"vCoN_GmihaJOTBwUCW2N_JPjlaY="},"name":"foo"}},{"O":"UPDATE","S":"IjEi","T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","V":"MC4w"}]}

<<< {"S":[true],"O":[{"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","V":"MC4w","P":{"product":{"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","S":"Ijk3Ig=="},"id":"97","defaultQuantity":100,"name":"foo","images":[],"defaultUnit":"lbs.","active":true,"defaultPrice":"10"},"S":"Ijk3Ig==","C":1,"O":"PERSIST"},{"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","V":"MC4w","P":{"name":"foo","type":{"T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","S":"IjEi"}},"S":"Ijk3Ig==","C":2,"O":"PERSIST"},{"T":"NMnlePAPPa8$chg1XXK6I_qmRTc=","V":"Ni4w","S":"IjQi","O":"UPDATE"},{"T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","V":"MC4w","P":{"name":"Other"},"S":"IjEi","O":"UPDATE"}],"I":[{"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","S":"Ijk3Ig=="}]}

>>> {"F":"com.plovgh.web.shared.bindery.PlovghInstanceRequestFactory","I":[{"O":"?","P":[{"S":"Ijk3Ig==","T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ="}],"R":["product.type","images"]}]}

<<< {"S":[true],"O":[{"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","V":"MC4w","P":{"product":{"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","S":"Ijk3Ig=="},"id":"97","defaultQuantity":100,"name":"foo","images":[],"defaultUnit":"lbs.","active":true,"defaultPrice":"10.00"},"S":"Ijk3Ig==","O":"UPDATE"},{"T":"UCoe6wjm6hP1YdFtuSowpMxJ0ow=","V":"MC4w","P":{"name":"foo","type":{"T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","S":"IjEi"}},"S":"Ijk3Ig==","O":"UPDATE"},{"T":"vCoN_GmihaJOTBwUCW2N_JPjlaY=","V":"MC4w","P":{"name":"Other"},"S":"IjEi","O":"UPDATE"}],"I":[{"T":"lUUyvXo8bCZWuM6Ew6LR72oN2nQ=","S":"Ijk3Ig=="}]}

Thomas Broyer

unread,
Jan 17, 2013, 6:48:13 PM1/17/13
to google-we...@googlegroups.com
OK, it indeed looks like a bug.

This code fails with the "Unfrozen proxy" assertion error:

    delayTestFinish(DELAY_TEST_FINISH);

    SimpleFooRequest context = simpleFooRequest();
    final SimpleFooProxy foo = context.create(SimpleFooProxy.class);
    final SimpleBarProxy bar = context.create(SimpleBarProxy.class);
    foo.setBarField(bar);
    Request<SimpleFooProxy> fooReq = context.persistAndReturnSelf().using(foo).with("barField");
    fooReq.fire(new Receiver<SimpleFooProxy>() {

      @Override
      public void onSuccess(SimpleFooProxy returned) {
        simpleFooRequest().edit(returned);

        finishTestAndReset();
      }
    });

The same code without the SimpleBarProxy works.

I'm currently debugging it. Will file an issue too.

Thomas Broyer

unread,
Jan 17, 2013, 6:54:33 PM1/17/13
to google-we...@googlegroups.com

bloo

unread,
Jan 18, 2013, 12:30:09 PM1/18/13
to google-we...@googlegroups.com
Thanks!
Reply all
Reply to author
Forward
0 new messages