EntityProxy, AutoBeanVisitor and Hibernate lazy properties.

492 views
Skip to first unread message

Tiago Rinck Caveden

unread,
Aug 16, 2011, 12:07:27 PM8/16/11
to google-we...@googlegroups.com
Hello all,

Sorry if this has been answered somewhere - it probably has, since I doubt I'm the fist one to have the issue - but I couldn't find it.

I have an EntityProxy for a Hibernate entity which contains a lazy collection. In a particular use case I need this collection, so I have the getter defined in the EntityProxy interface. In another use case, I have no use for it, so it should not be loaded. But the AutoBeanVisitor tries to visit every element of the said collection, what raises a runtime error since at this stage there's no Hibernate session open.

How can I prevent this visitor from accessing this unloaded hibernate proxy?

Thank you.

Tiago Rinck Caveden

unread,
Sep 2, 2011, 4:39:50 AM9/2/11
to google-we...@googlegroups.com
Hello again,

Sorry for annoying the group again, but really nobody else has ever encountered this issue? It seems I get it every time I use GWT editors with Hibernate lazy proxies... I can't just convert every lazy property to eager, so I wonder how you people are doing.

Thank you!
--
Tiago Rinck Caveden

Tiago Rinck Caveden

unread,
Sep 7, 2011, 5:12:47 AM9/7/11
to google-we...@googlegroups.com
It seems I might indeed be the first one to encounter this problem, so I've opened an issue for it: http://code.google.com/p/google-web-toolkit/issues/detail?id=6767

Thanks,
Tiago.

StefanR

unread,
Sep 7, 2011, 9:43:09 AM9/7/11
to google-we...@googlegroups.com
You can use the OpenEntityManagerInView pattern (servlet filter with Spring) to ensure a EntityManager session is open during the RF-request.

Regards,
Stefan.

Tiago

unread,
Sep 7, 2011, 10:08:24 AM9/7/11
to Google Web Toolkit
Hello Stefan,

Thank you for your answer. Yes, I could do that, but then I would be
loading unnecessary data from the DB. Depending on the entity graph,
that could go really far. In order words, that just switches one
problem for another.

The correct solution is not to have these unnecessary properties
accessed at all. That's why I think this is actually a bug. The
RequestFactory engine should not touch every property in an
EntityProxy since it's expected to find ORM proxies. I thought the
with() method existed precisely for that reason.

As a workaround, I'm creating multiple versions of the same entity
proxy, for example a "light" one, with only the eager properties
defined, and then other classes which define lazy properties to be
used when such properties need to be loaded. That's damn dirty as a
solution though.

StefanR

unread,
Sep 8, 2011, 4:22:47 AM9/8/11
to google-we...@googlegroups.com
Hi Tiago,

I just made a little test and it works as expected. Only those getters are called which are referenced in the with() statement.

Maybe there's an issue with your entityProxies? Can you provide some details about your setup?

Regards,
Stefan.

Tiago

unread,
Sep 8, 2011, 9:48:15 AM9/8/11
to Google Web Toolkit
Hello Stefan,

Here's a summary of a situation where I got the error:

I have a Child entity which has a link to its Parent. The parent
entity also has a collection of entities of the Child type.
I'm loading the child to display its values with the help of the GWT
Editor framework, in read-only mode. I need to display some data from
the parent entity as well, so when creating the request, I add
with("parentProperty") to it.

Doing that results in a LazyInitializationException. The exception
claims the proxy "parent.childs" has not been initialized, and indeed
it was not, since I'm displaying only one child. The AutoBeanVisitor
navigated child->parent->childs. The first step was ok, the second one
should not have happened.

Could it be related to the Editor framework, or with Collections, or
even a combination of both?

Thank you very much for you help.

Tiago

unread,
Sep 8, 2011, 10:00:39 AM9/8/11
to Google Web Toolkit
I'll post here a stack trace of the error I get, maybe it helps (I've
cut off everything before GWT classes, which were mostly
springframework and jetty stacks)

If I remove the List<Child> getter from ParentProxy, I don't have this
error anymore.

SEVERE: Unexpected error
org.hibernate.LazyInitializationException: failed to lazily initialize
a collection of role: [Parent.childs], no session or session was
closed
at
org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:
383)
at
org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:
375)
at
org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:
368)
at
org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:
111)
at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:
272)
at
com.google.web.bindery.requestfactory.server.Resolver.resolveClientValue(Resolver.java:
441)
at com.google.web.bindery.requestfactory.server.Resolver.access
$200(Resolver.java:49)
at com.google.web.bindery.requestfactory.server.Resolver
$1.visitReferenceProperty(Resolver.java:359)
at
com.google.web.bindery.autobean.shared.AutoBeanVisitor.visitCollectionProperty(AutoBeanVisitor.java:
229)
at
com.google.web.bindery.autobean.vm.impl.ProxyAutoBean.traverseProperties(ProxyAutoBean.java:
271)
at
com.google.web.bindery.autobean.shared.impl.AbstractAutoBean.traverse(AbstractAutoBean.java:
166)
at
com.google.web.bindery.autobean.shared.impl.AbstractAutoBean.accept(AbstractAutoBean.java:
101)
at
com.google.web.bindery.requestfactory.server.Resolver.resolveClientProxy(Resolver.java:
323)
at
com.google.web.bindery.requestfactory.server.Resolver.resolveClientValue(Resolver.java:
418)
at com.google.web.bindery.requestfactory.server.Resolver.access
$200(Resolver.java:49)
at com.google.web.bindery.requestfactory.server.Resolver
$1.visitReferenceProperty(Resolver.java:359)
at
com.google.web.bindery.autobean.vm.impl.ProxyAutoBean.traverseProperties(ProxyAutoBean.java:
295)
at
com.google.web.bindery.autobean.shared.impl.AbstractAutoBean.traverse(AbstractAutoBean.java:
166)
at
com.google.web.bindery.autobean.shared.impl.AbstractAutoBean.accept(AbstractAutoBean.java:
101)
at
com.google.web.bindery.requestfactory.server.Resolver.resolveClientProxy(Resolver.java:
323)
at
com.google.web.bindery.requestfactory.server.Resolver.resolveClientValue(Resolver.java:
418)
at com.google.web.bindery.requestfactory.server.Resolver.access
$200(Resolver.java:49)
at com.google.web.bindery.requestfactory.server.Resolver
$1.visitReferenceProperty(Resolver.java:359)
at
com.google.web.bindery.autobean.vm.impl.ProxyAutoBean.traverseProperties(ProxyAutoBean.java:
295)
at
com.google.web.bindery.autobean.shared.impl.AbstractAutoBean.traverse(AbstractAutoBean.java:
166)
at
com.google.web.bindery.autobean.shared.impl.AbstractAutoBean.accept(AbstractAutoBean.java:
101)
at
com.google.web.bindery.requestfactory.server.Resolver.resolveClientProxy(Resolver.java:
323)
at
com.google.web.bindery.requestfactory.server.Resolver.resolveClientValue(Resolver.java:
418)
at
com.google.web.bindery.requestfactory.server.Resolver.resolveClientValue(Resolver.java:
196)
at
com.google.web.bindery.requestfactory.server.SimpleRequestProcessor.processInvocationMessages(SimpleRequestProcessor.java:
451)
at
com.google.web.bindery.requestfactory.server.SimpleRequestProcessor.process(SimpleRequestProcessor.java:
217)
at
com.google.web.bindery.requestfactory.server.SimpleRequestProcessor.process(SimpleRequestProcessor.java:
125)
at
com.google.web.bindery.requestfactory.server.RequestFactoryServlet.doPost(RequestFactoryServlet.java:
118)

On Sep 8, 10:22 am, StefanR <stefan.ro...@googlemail.com> wrote:

Thomas Broyer

unread,
Sep 8, 2011, 11:38:20 AM9/8/11
to google-we...@googlegroups.com
I believe RF is not meant to be used with lazy-loading if you don't also use (and accept the consequences) "OpenSessionInView".

If you detach your objects "early", then you have to either remove the lazy-loading (best IMO, lazy-loading is appealing but the risks of loading much more than needed, generally in hard-to-debug places, and the hard-to-optimize –when possible, 'cause you'll generally design your services in such a way that lazy-loading is implied, with no hook to eager-load the things you need– requests are not worth it; I'd even go as far as saying that the benefits of JPQL are a lie, but that's another story) or "unproxy" your objects rather than simply detaching them.

Tiago

unread,
Sep 9, 2011, 3:23:51 AM9/9/11
to Google Web Toolkit
Hello Thomas,

On Sep 8, 11:38 am, Thomas Broyer <t.bro...@gmail.com> wrote:
> I believe RF is not meant to be used with lazy-loading if you don't also use
> (and accept the consequences) "OpenSessionInView".

That would be a pity. I thought the point of RF was dealing with ORM
entities without having to mind with stuff described here:
https://code.google.com/webtoolkit/articles/using_gwt_with_hibernate.html
Actually, I thought that preventing lazy initialization exceptions was
the point of the with() method... I wonder why it exists if not for
that...

> or "unproxy" your objects rather than simply detaching them.

Would you advice the use of Gilead with RF for this?

Thank you.

Thomas Broyer

unread,
Sep 9, 2011, 4:31:17 AM9/9/11
to google-we...@googlegroups.com


On Friday, September 9, 2011 9:23:51 AM UTC+2, Tiago wrote:
Hello Thomas,

On Sep 8, 11:38 am, Thomas Broyer <t.br...@gmail.com> wrote:
> I believe RF is not meant to be used with lazy-loading if you don't also use
> (and accept the consequences) "OpenSessionInView".

That would be a pity. I thought the point of RF was dealing with ORM
entities without having to mind with stuff described here:
https://code.google.com/webtoolkit/articles/using_gwt_with_hibernate.html
Actually, I thought that preventing lazy initialization exceptions was
the point of the with() method... I wonder why it exists if not for
that...

There are basically two choices when modelling synchronous APIs on top of inherently asynchronous communications: get everything eagerly (with the risk of retrieve the database as a whole) so that a getContactDetails() always returns something, or get only what's requested (so that getContactDetails() either returns data if it was requested, or returns 'null' otherwise).
RF falls in the second category (except that it doesn't apply it to properties with "simple values"), and .with() is the way to request data that wouldn't be loaded by default. By "loaded" here, we meant "serialized in the HTTP response", which is a different deal as to what can happen on the server.

.with() has nothing to do with lazy-loading or "lazy initialization exceptions"; it's only about what goes over the wire, and what's available on the client-side.

> or "unproxy" your objects rather than simply detaching them.

Would you advice the use of Gilead with RF for this?

I don't know Gilead (and I actually don't use JPA or JDO, but if I had to, I wouldn't use lazy-loading, it causes much more burden than what it's supposed to "solve", it's not worth it, it's a lie, it's counterproductive in the long run; JPA/JDO, like much "enterprisey" things, are over-engineered and much too complicated to get them to work unless you're an expert in the field).

Tiago

unread,
Sep 9, 2011, 5:52:33 AM9/9/11
to Google Web Toolkit
On Sep 9, 10:31 am, Thomas Broyer <t.bro...@gmail.com> wrote:
> .with() has nothing to do with lazy-loading or "lazy initialization
> exceptions"; it's only about what goes over the wire, and what's available
> on the client-side.

Right, but if I haven't explicitly said that a certain property is
going over the wire, then why is GWT accessing it with this
AutoBeanVisitor?

> I don't know Gilead (and I actually don't use JPA or JDO, but if I had to, I
> wouldn't use lazy-loading, it causes much more burden than what it's
> supposed to "solve", it's not worth it, it's a lie, it's counterproductive
> in the long run; JPA/JDO, like much "enterprisey" things, are
> over-engineered and much too complicated to get them to work unless you're
> an expert in the field).

You might have a good point there, but I'm not likely to remove
Hibernate from this app.
Many problems would be solved if Hibernate just automatically removed
every instrumentation it does on entities after they're detached. I
asked about Gilead because apparently that's what it does, but I
haven't found any examples of somebody mixing Gilead and RF.

Thank you,
Tiago.

Juan Pablo Gardella

unread,
Sep 9, 2011, 7:50:38 AM9/9/11
to google-we...@googlegroups.com
Hi Tiago,

I use JPA2 (with Hibernate as a provider) in a GWT application. I use a Filter that put to null uninitialized properties in a transparent manner. So if you in service layer don't initialize the properties, this filter solve the problem of serialization. Check this thread.

Juan

2011/9/9 Tiago <cav...@gmail.com>

--
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.


Tiago

unread,
Sep 9, 2011, 10:58:48 AM9/9/11
to Google Web Toolkit
Thank you very much Juan, you helped me finding an easier workaround.
After seeing your use of filters to the RPC calls, I imagined there
should be a way to filter the creation of properties in
RequestFactory, and after searching a little I found that the
ServiceLayerDecorator could help me if I just override the getProperty
method. Much better now!

But I still think RF shouldn't visit all properties of an entity.
Imagine how many people are using OpenSessionInView and are having
unnecessary overheads in their applications without knowing.
This could be done by just treating any Collection as a potential
relation, and not even resolving the type of its members if this
collection was not requested through with().

On Sep 9, 1:50 pm, Juan Pablo Gardella <gardellajuanpa...@gmail.com>
wrote:
> Hi Tiago,
>
> I use JPA2 (with Hibernate as a provider) in a GWT application. I use a *Filter
> *that put to null uninitialized properties in a transparent manner. So if
> you in service layer don't initialize the properties, this filter solve the
> problem of serialization. Check this
> thread<http://groups.google.com/group/google-web-toolkit/browse_thread/threa...>
> .
>
> Juan
>
> 2011/9/9 Tiago <cave...@gmail.com>

Sanjiv Jivan

unread,
Sep 9, 2011, 1:29:54 PM9/9/11
to google-we...@googlegroups.com
Just curious to know what you're using for your persistence layer?  

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.

Thomas Broyer

unread,
Sep 9, 2011, 6:44:46 PM9/9/11
to google-we...@googlegroups.com
In my current project, MongoDB through Morphia (without lazy-loading). But it would be the same with, say, AppEngine Objectify. The persistence API doesn't change much things; what matters is that if you think of things without lazy-loading, it changes the way you design your data-access APIs. You're free to use lazy-loading then if you want, but at least you designed your APIs with performance-tuning in mind (i.e. if you want a user entity and all its contact details, you can do 2 requests, or a single one using a join; if you design your API with lazy-loading in mind, you won't tell the lower-layer that you might sometime want the contact details and sometimes won't, which makes it impossible to later optimize requests).
RF's .with() is about what goes over the wire, not what goes out of your database (even though it'd be *really* useful to have that same info to fine-tune what you get out of the DB, particularly with relational persistence that stores @Embedded objects in separate tables)

Tiago

unread,
Sep 19, 2011, 12:15:10 PM9/19/11
to Google Web Toolkit
Hello again Juan (and all :)),

In an attempt to solve this problem:
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/96c0c1ce2af9d96d/16b856e4e130a711
I decided to implement one of my services as RPC instead of RF. Then,
I started having this Hibernate issue again. I remembered you had done
your filtering in RPC so I decided I was going to check your code
again to see what I could cop...I mean, inspire myself with. :D

Looking to your code I realized you had redefined a big chunk of GWT
code. One has to redefine all that classes if the only thing one wants
is to add filtering to each object being serialized? There's no other
easier way, like there's for RequestFactory with its
ServiceLayerDecorator? I don't feel comfortable with the idea of
redoing what's already done (and maintained!) by the GWT team.

Thank you all

On Sep 9, 1:50 pm, Juan Pablo Gardella <gardellajuanpa...@gmail.com>
wrote:
> Hi Tiago,
>
> I use JPA2 (with Hibernate as a provider) in a GWT application. I use a *Filter
> *that put to null uninitialized properties in a transparent manner. So if
> you in service layer don't initialize the properties, this filter solve the
> problem of serialization. Check this
> thread<http://groups.google.com/group/google-web-toolkit/browse_thread/threa...>
> .
>
> Juan
>
> 2011/9/9 Tiago <cave...@gmail.com>
>
>
>
>
>
>
>

Juan Pablo Gardella

unread,
Sep 19, 2011, 8:43:56 PM9/19/11
to google-we...@googlegroups.com
No because some classe that must extend is final. So you must hack in this way. But with you put this classes then you forgot problems. It works.

2011/9/19 Tiago <cav...@gmail.com>

-sowdri-

unread,
Sep 20, 2011, 1:11:11 AM9/20/11
to google-we...@googlegroups.com
Hi Tiago,

I faced similar issues with hibernate, RF and lazy initialization. 

Finally I found that it was because of proxying that is done by hibernate. I finally solved it by using the @Proxy(lazy=false) annotation. 


@Entity
@Table(name = "CALL_TABLE")
@Proxy(lazy=false)
public class Call extends Base {

private static final long serialVersionUID = 3748496188367374385L;

@Temporal(TemporalType.TIMESTAMP)
Date startTime;
...
}

Hope this helps!

Tiago

unread,
Sep 20, 2011, 4:04:41 AM9/20/11
to Google Web Toolkit
On Sep 20, 2:43 am, Juan Pablo Gardella <gardellajuanpa...@gmail.com>
wrote:
> No because some classe that must extend is final. So you must hack in this
> way. But with you put this classes then you forgot problems. It works.

I'm not very comfortable with it. It means I would have to follow GWT
code updates, manage incompatibilities etc.
If that's the only way, then I think I will implement it on my DAO
layer. I know, I know, the DAO shouldn't care about the problems of
UI, but at least there I can use Hibernate metadata to navigate
through each entity and filter Hibernate proxies recursively.

Thanks!

Tiago

unread,
Sep 20, 2011, 4:10:45 AM9/20/11
to Google Web Toolkit
Sowdri,

On Sep 20, 7:11 am, -sowdri- <sow...@gmail.com> wrote:
> Finally I found that it was because of proxying that is done by hibernate. I
> finally solved it by using the @Proxy(lazy=false) annotation.

That will make hibernate load every relation annotated as such, what
may make your application load much more data than what it actually
needs.
Actually, I think everybody that's currently using OpenSessionInView
is already having such overhead issues. They are either not bothering
with it, or, most probably, not aware of it.
That's why I've opened an issue to GWT. The RequestFactory framework
should not navigate through entities which are not meant to be
transferred to the client (those that are not indicated by the with()
method).

Thomas Broyer

unread,
Sep 20, 2011, 5:03:15 AM9/20/11
to google-we...@googlegroups.com


On Tuesday, September 20, 2011 10:04:41 AM UTC+2, Tiago wrote:
If that's the only way, then I think I will implement it on my DAO
layer. I know, I know, the DAO shouldn't care about the problems of
UI, but at least there I can use Hibernate metadata to navigate
through each entity and filter Hibernate proxies recursively.

It's not a "the DAO then cares about problems of UI", it's just a shift in contract from "getX(i) returns a 'pointer' to X(i) but potentially gives you access to the whole database by following relationships" to "getX(i) gives you a snapshot of X(i), and only X(i)" (or "getX(i,props) gives you a snapshot of X(i) with its 'props' relationships being populated by snapshots of their values")

-sowdri-

unread,
Sep 20, 2011, 5:54:29 AM9/20/11
to google-we...@googlegroups.com
If you would like to have a non-invasive workaround (where-in the size of the child entities you are loading is not so heavy), you can go for this!

And I do agree with your view!

Thanks, 

Tiago

unread,
Sep 20, 2011, 9:19:55 AM9/20/11
to Google Web Toolkit
On Sep 20, 11:03 am, Thomas Broyer <t.bro...@gmail.com> wrote:
> It's not a "the DAO then cares about problems of UI", it's just a shift in
> contract from "getX(i) returns a 'pointer' to X(i) but potentially gives you
> access to the whole database by following relationships" to "getX(i) gives
> you a snapshot of X(i), and only X(i)" (or "getX(i,props) gives you a
> snapshot of X(i) with its 'props' relationships being populated by snapshots
> of their values")

You're right. Hibernate should do this cleanup itself (you make the
mess, you clean it up), or at least provide an easy config option as
opt-in. I don't know what's the reason not to do it.
Reply all
Reply to author
Forward
0 new messages