-->
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.  [ 13 posts ] 
Author Message
 Post subject: Reflection on CGLIB proxies
PostPosted: Fri Oct 29, 2004 12:59 pm 
Beginner
Beginner

Joined: Tue Aug 17, 2004 5:06 am
Posts: 46
Once again these CGLIB proxies make me go crazy.

I have a one-to-one association to a polymorph object. The proxy is derived from the top level object, i.e.

Person
Worker extends Person
Student extends Person

The proxy is derived from the top level object, so it's a Person.

If the one-to-one accessor returns a proxy (a Person) that proxies a Worker then I can't access the Worker's getter and setter methods using reflection. They are just not found.

Any hints ?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 29, 2004 1:06 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Why did you not fill out the form in the text field? We don't know what you are talking about.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 29, 2004 1:51 pm 
Beginner
Beginner

Joined: Tue Aug 17, 2004 5:06 am
Posts: 46
Sorry, but I can't fill out the form due to 'security constraints'. Abstracting the mapping files would be too difficult...

I really like Hibernate, but my experience is that the CGLIB proxies break polymorphism in case of associations. Once I disable them everything works fine.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 29, 2004 2:10 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Sure, a proxy is a subclass generated at runtime. Use a tool that uses buildtime bytecode enhancement if you can't work with this.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 29, 2004 2:11 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
P.S. And they don't break polymorphism as long as you are not using "instanceof" all over the place.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 30, 2004 7:24 am 
Beginner
Beginner

Joined: Tue Aug 17, 2004 5:06 am
Posts: 46
christian wrote:
P.S. And they don't break polymorphism as long as you are not using "instanceof" all over the place.


I think that breaking the "instanceof" functionality does indeed mean that they break polymorphism. It's getting even worse if you use business interfaces.

I understand the problem. There's no way that a proxy can know it's correct subclass in advance to being initialized. However frameworks that depend on reflection will get into deep trouble here. In my case I can't call getters and setters using reflection *before* the object is initialized and the object isn't initialized when accessing it using reflection.

I see two approaches for solving my problem:
* initialize the proxy before it's being touched (better solution)
* disable proxies for polymorph objects at all (worse solution)

I'll try this today.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 30, 2004 8:17 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Code:
      Item aProxy = new ItemDAO().getItemById(auctionOne.getId(), false); // session.load()

      System.out.println("### PROXY IS INITIALIZED: " + Hibernate.isInitialized(aProxy)); // false
      System.out.println("### PROXY INSTANCE OF IS: " + (aProxy instanceof Item) ); // true
      System.out.println("### PROXY CLASS IS: " + aProxy.getClass().getName() ); // CGLIB class

      // Initializes the proxy and prints out the name of the Item
      System.out.println("### INVOKING METHOD ON PROXY: " +
              aProxy.getClass().getDeclaredMethod("getName", null).invoke(aProxy, null));

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 30, 2004 8:19 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Oh, you use inheritance, so this code doesn't apply to you. You only have the two solutions you already mentioned.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject: Re: Reflection on CGLIB proxies
PostPosted: Sat Oct 30, 2004 12:42 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
Woyzeck wrote:
Person
Worker extends Person
Student extends Person

The proxy is derived from the top level object, so it's a Person.

If the one-to-one accessor returns a proxy (a Person) that proxies a Worker then I can't access the Worker's getter and setter methods using reflection. They are just not found.
Any hints ?


If you need proxy for "Worker", then can tell it in mapping, but this mapping is static and you will get class cast exception if it will be a "Student" at runtime.
You can unwrapp proxied instance to get the real type too.

BTW Hibernate assigns proxy itself and it knows runtime type ( if poster is right then proxied instance type is "Worker" ), is it some problem to generate proxy using runtime type ? It looks like a bug, doe's not it ?


Top
 Profile  
 
 Post subject: Re: Reflection on CGLIB proxies
PostPosted: Sat Oct 30, 2004 5:01 pm 
Beginner
Beginner

Joined: Tue Aug 17, 2004 5:06 am
Posts: 46
baliukas wrote:
Woyzeck wrote:
You can unwrapp proxied instance to get the real type too.

BTW Hibernate assigns proxy itself and it knows runtime type ( if poster is right then proxied instance type is "Worker" ), is it some problem to generate proxy using runtime type ? It looks like a bug, doe's not it ?


How can I unwrap a proxy ?


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 30, 2004 5:08 pm 
Beginner
Beginner

Joined: Tue Aug 17, 2004 5:06 am
Posts: 46
Those CGLIB proxies are driving me crazy...

We have associations that return proxies. These proxies do not implement anything but the base class. No business interface, no concrete type. We can't cast them to anything useful.

I tried to call Hibernate.initialize(myProxy), but it did not change a thing.

Is there any way how I can force a proxy object to expose the correct (polymorph) getters and setters in case of an association ?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 31, 2004 2:22 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
Proxy is generated by mapping information, if you will use "Worker" in one-to-one association then proxy will extend it too, but it can not be generated by runtime type, probably it because framework needs to hit database to know "discriminator" and lazy proxy is meaningless for this use case (probably all persistence frameworks have this problem).
There is "ProxyHelper" API or something like that to unwrapp proxy, find it in javadoc, I do not remember it, there are a few discussions about it in this forum too.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 31, 2004 4:52 am 
Beginner
Beginner

Joined: Tue Aug 17, 2004 5:06 am
Posts: 46
Ok, I've read the chapter 6.4 "Mapping polymorphic associations" and it clearly warns of my problems. I should have done this earlier...

The proposed solution (using session.load()) to get a typesafe instance is unusable for all but the most trivial data structures, so I'll drop proxies for my polymorphic objects at all.

I understand all the problems and why polymorphic proxies have to be implemented that way, but my personal opinion is that proxies that don't hide themselves from the application code are bad design.

Breaking language fundamentals like instanceof and typecasts is very intrusive and leads to problems that can be very difficult to find during testing. In my opinion it would be better to disable proxying for polymorphic associations by default and warn the user of the problems that he can expect when enabling it.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 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.