-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Lazy field returns proxy instead of real object ??
PostPosted: Sat Dec 01, 2012 11:55 am 
Regular
Regular

Joined: Thu Aug 28, 2003 2:42 pm
Posts: 77
Location: The Netherlands
Hibernate version: 4.1.8
I call a method on a persist object that is proxied by Javassist, that simple returns "this" (to get the proxied object)

The class JavassistLazyInitializer noticed this and will return the proxy again :(... that results in a ClassCastException.
I don't think this is correct, JavassistLazyInitializer should not return the proxy, but the real return value as it results in unexpected behavior... And it's hard to find and results in nasty bugs!

Let me explain:
I have a subclass Member that extends from Person:
Code:
class  Person {
  Member asMember() {
    throw RuntimeException("WrongType");
  }
}

class Member extends Person {
  Member asMember() {
    return this;
  }
}


I use this as an alternative to the visitor pattern, as it's usage is friendlier, easier, and performs better.
So when I am sure that the Person is a member (by a isMember() method), I call the asMember() method.

This works fine till the Member instance is proxied by Hibernate. Example: member is a field of a Company class:
Code:
class Company {
Person person;
}


When Company.member is lazy loaded and I call company.person.asMember() I get a ClassCastException. I think this is a bug, as what I do is fine and legal.

What Hibernate however does: it will proxy the field person of type Person.
When I call the method company.person.asMember(), it will call method JavassistLazyInitializer.invoke() which will return the proxy as soon as it sees that method asMember() returns the same object as wrapped by the proxy (line 200):
Code:
   return returnValue == target ? proxy : returnValue;

However the proxy is a generated subclass of Person and the return type of the asMember() method is of type Member, such that ClassCastException occurs.
Conclusion: I don't think this optimization (returning the proxy) is a "good one".
I think the above line in JavassistLazyInitializer, should simple be:
Code:
   return returnValue;

But I am not sure what kind of optimizations you will miss in this case.
So you could fine tune this to:
Code:
   return returnValue == target && returnValue.getClass().isInstance(proxy) ? proxy : returnValue;

I tested this, and it seem to work fine...


Please some feedback on this?

BTW, Workarounds:
a) remove the method, and use a "real" visitor object...
b) Return the object in a Wrapper object such that JavassistLazyInitializer won't see it as the same object as the target, such that it will return the "real" return value...


Top
 Profile  
 
 Post subject: Re: Lazy field returns proxy instead of real object ??
PostPosted: Wed Dec 05, 2012 3:28 am 
Regular
Regular

Joined: Thu Aug 28, 2003 2:42 pm
Posts: 77
Location: The Netherlands
I opened a bug concerning this issue:
https://hibernate.onjira.com/browse/HHH-7845
If you want it solved, please vote it.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.