Trying to understand how RF picks the domain objects to compose a request to a service

51 views
Skip to first unread message

Tiago Rinck Caveden

unread,
Jun 12, 2012, 9:54:32 AM6/12/12
to google-we...@googlegroups.com
Hello all,

I'm having a weird scenario in my application, and I guess that if I could understand better how RF picks the domain objects instances it will provide to a service, maybe I could understand what's going on.

Here's my scenario:

I have an Editor<AProxy>. The domain class A has a property B which is another domain entity.
In the editor there's a ValueListBox<BProxy>.

Use cases:
* If I just load the editor and hit submit without touching anything, everything works nicely.
* If I change the value of B by picking another entity in the ValueListBox, it also works nicely.
* If I change the value of B as above, but before submitting I change my mind and return the ValueListBox to its original value, RF will send to my service an object A whose property B is a non-initialized Hibernate proxy, linked to a closed session. That will result in a LazyInitializationException. In the other two cases, it was sending me an instance of B, not a hibernate proxy.

Can somebody kindly help me understand how RF composes my object A after receiving the request payload? Where is it getting this uninitialized proxy from?

Thank you,
--
Tiago Rinck Caveden

Thomas Broyer

unread,
Jun 12, 2012, 10:17:23 AM6/12/12
to google-we...@googlegroups.com
How are the acceptable values of the ValueListBox populated?
The difference between scenarios 1 and 3 is that in the former the value is not changed (stored in a field in setValue, returned as-is from getValue), while in the latter it is set to the equivalent value from the list of acceptable values.

It might be related to http://code.google.com/p/google-web-toolkit/issues/detail?id=7189 but it depends how you setup your Hibernate sessions.

With RF, you're supposed to use the OpenSessionInView paradigm, and then use one transaction per service method.

Tiago

unread,
Jun 12, 2012, 10:44:53 AM6/12/12
to google-we...@googlegroups.com
On Tuesday, June 12, 2012 4:17:23 PM UTC+2, Thomas Broyer wrote:
How are the acceptable values of the ValueListBox populated?

A request is done specifically for that. The list of acceptable values is properly initialized on the server side before returning it to the client side.
 
The difference between scenarios 1 and 3 is that in the former the value is not changed (stored in a field in setValue, returned as-is from getValue), while in the latter it is set to the equivalent value from the list of acceptable values.

I suspected this.
But the proxy that's being saved in B is not the same instance that was returned by the request I said above, which was used to populate the acceptable values. I verified that with the debugger. And it should be initialized if it was the same object of the list anyway.

 
It might be related to http://code.google.com/p/google-web-toolkit/issues/detail?id=7189 but it depends how you setup your Hibernate sessions.

I'm not touching any other field.. sure it's related?

Maybe another detail that might make some difference is that B is an abstract class. The subproxies to the concrete classes present in the ValueListBox are all properly defined in BProxy's @ExtraTypes annotation. Don't know if that might mess things up...

 
With RF, you're supposed to use the OpenSessionInView paradigm, and then use one transaction per service method.


Hum, I don't use OpenSessionInView, but regardless, the uninitialized proxy B must be set to A before my view method is called. Even if it was OpenSessionInView, the proxy comes from a previous session... right?
 

Thanks Thomas for your help!

Thomas Broyer

unread,
Jun 12, 2012, 11:31:01 AM6/12/12
to google-we...@googlegroups.com


On Tuesday, June 12, 2012 4:44:53 PM UTC+2, Tiago wrote:
On Tuesday, June 12, 2012 4:17:23 PM UTC+2, Thomas Broyer wrote:
How are the acceptable values of the ValueListBox populated?

A request is done specifically for that. The list of acceptable values is properly initialized on the server side before returning it to the client side.
 
The difference between scenarios 1 and 3 is that in the former the value is not changed (stored in a field in setValue, returned as-is from getValue), while in the latter it is set to the equivalent value from the list of acceptable values.

I suspected this.
But the proxy that's being saved in B is not the same instance that was returned by the request I said above, which was used to populate the acceptable values. I verified that with the debugger. And it should be initialized if it was the same object of the list anyway.

 
It might be related to http://code.google.com/p/google-web-toolkit/issues/detail?id=7189 but it depends how you setup your Hibernate sessions.

I'm not touching any other field.. sure it's related?

You're right; your issue is that you don't use OpenSessionInView.
 
Maybe another detail that might make some difference is that B is an abstract class. The subproxies to the concrete classes present in the ValueListBox are all properly defined in BProxy's @ExtraTypes annotation. Don't know if that might mess things up...

 
With RF, you're supposed to use the OpenSessionInView paradigm, and then use one transaction per service method.


Hum, I don't use OpenSessionInView, but regardless, the uninitialized proxy B must be set to A before my view method is called. Even if it was OpenSessionInView, the proxy comes from a previous session... right?

No.

HTTP is stateless, and so is RequestFactory.
See http://code.google.com/p/google-web-toolkit/wiki/RequestFactoryMovingParts#Flow for details on how a request is processed. The B domain object is created/loaded in the “All domain objects referred to by the payload will be loaded.” phase, that is, the very first thing that's being done on the server to process the request.
In the first scenario, the "b" property is seen as being untouched, so it's not sent to the server; but the third scenario, because of http://code.google.com/p/google-web-toolkit/issues/detail?id=5952, the GWT app thinks it's a different entity, so it tells the server to change the properties' value. If you used OpenSessionInView though, it would just work; it would do some unnecessary work, but it would work.

Tiago

unread,
Jun 14, 2012, 9:42:29 AM6/14/12
to google-we...@googlegroups.com
On Tuesday, June 12, 2012 5:31:01 PM UTC+2, Thomas Broyer wrote:
See http://code.google.com/p/google-web-toolkit/wiki/RequestFactoryMovingParts#Flow for details on how a request is processed. The B domain object is created/loaded in the “All domain objects referred to by the payload will be loaded.” phase, that is, the very first thing that's being done on the server to process the request.

I don't understand how is this property loaded. Why when I change it to something else (case 2), an actual instance of my entity is loaded, but when I change to the same thing, an uninitialized Hibernate proxy is loaded?
The locator linked to the proxy interface via the @ProxyFor annotation is set to always load initialized instances. (Session.get(Class, Serializable) method in Hibernate is used).

Do you know where is this Hibernate proxy coming from?

 
 If you used OpenSessionInView though, it would just work; it would do some unnecessary work, but it would work.

Why? My "UI Service" (the @Service behind the RequestContext) passes entity A as it receives it to the in-session service which actually have the exception. It is not touched by the UI service code, only in the business service layer the entity is touched.

Thank you a lot!
Reply all
Reply to author
Forward
0 new messages