-->
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.  [ 6 posts ] 
Author Message
 Post subject: Converting proxy object to the real thing
PostPosted: Wed Aug 31, 2005 12:09 pm 
Newbie

Joined: Fri Feb 25, 2005 3:40 pm
Posts: 8
Location: Victoria, BC Canada
I've been trying to figure out how to convert a proxy object (with a weaker interface than what is needed) into the actual object I need.

I tried using the visitor pattern described here:

http://www.hibernate.org/280.html

but it looked to me like this was just a way to force an unnecessary method call on the proxy object so that it could become instantiated.

So I tried this approach:

Code:
Hibernate.initialize(member);


That initialized the object, but I still had a reference to a proxy. Since the initialize call does not return the target object, I still couldn't cast to my more detailed interface.

After playing with the API a bit, I came up with this:

Code:
Hibernate.initialize(member);
HibernateProxy proxy = (HibernateProxy)member;                                                         
Person person = (Person)proxy.getHibernateLazyInitializer().getImplementation();


This works except that I occasionally get warnings about Narrowing the class breaking "=".

So is this the right way to go? Is there a better way to get the real object or to get a more detailed Proxy? At the time I know I need this, I am far past the DAO.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 01, 2005 10:22 pm 
Beginner
Beginner

Joined: Tue Sep 09, 2003 9:11 pm
Posts: 32
pedxing,

I use almost the same code you have listed here when I need the "real" object (also I'm using Hib2.1). It try to do this very infrequently as it can have side affects (but I write automated test cases to make sure things don't break).


I know the Hib2.1 documenation talks about inheritance and equals. That section probably speaks to the warning you are getting.

One side affect you might encounter is lazy loading. I'm pretty sure lazy loading will not work on the "implementation" class. The proxy class is what is actually doing the lazy loading.

My best suggestion is to test and then write a test case to make sure the behavour does not change with each new Hibernate version.

Good Luck!

_________________
___________
Chris....
Don't forget to rate


Top
 Profile  
 
 Post subject: Best practices for getting widened interface via Proxy
PostPosted: Fri Sep 02, 2005 1:25 pm 
Newbie

Joined: Fri Feb 25, 2005 3:40 pm
Posts: 8
Location: Victoria, BC Canada
chane wrote:
It try to do this very infrequently as it can have side affects (but I write automated test cases to make sure things don't break).

This is good to know. Can you categorize the problems that can occur? What types of unit tests should I make sure are present? Just verifying existence and general behaviour of fields in the object?

chane wrote:
I know the Hib2.1 documenation talks about inheritance and equals. That section probably speaks to the warning you are getting.

I don't think so. I make it a practice to override equals() and hashcode() wherever it is sensible to do so. I've followed Hibernate best practices for doing this. I guess I could have missed a spot, though. I'll doublecheck.

chane wrote:
One side affect you might encounter is lazy loading.

Really? I've instantiated the object itself. Any fields it holds should themselves be proxy objects if lazy loaded, no? I know I have gotten mixed up about whether the owning object or the owned object was responsible for initialization before, but I thought I had that part figured out now.

Thanks for your comments. I gave you a point for it, since I appreciate the time you put into it. I am still no closer to finding out the recommended best practices for getting my object instance via a Proxy, though. Although it is nice to know that I am not alone.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 06, 2005 2:30 pm 
Beginner
Beginner

Joined: Wed Dec 31, 2003 1:40 pm
Posts: 25
I avoid using any proxy objects. They are so misleading because they pretend to be omnipotent, all code that uses instanceof will be mislead. I hate proxy objects and avoid them like the pest. I'm curious where you actually need them?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 07, 2005 7:34 pm 
Regular
Regular

Joined: Tue Jun 22, 2004 8:01 pm
Posts: 106
Location: PowderTown, Utah, USA
Ok, there are some ways around this. Admittedly, they are BAD! (Shame on me for even inventing them!) They pretty much violate basic tenets of Object Oriented Programming. The Hibernate authors will probably yank my Swanky Programmers Club membership card for even disclosing these workarounds.

Oh well.

For starts, it's often valuable to iterate a collection of heterogenous objects and perform disparate operations on them that are not permitted by their common ancestor. In other words, you want to do crazy things that break encapsulation. A great way to do that is the Visitor pattern, as described in my writeup:

http://www.hibernate.org/280.html

The Visitor pattern also happens to punch past the proxy objects nicely. You can even use it to "visit" single objects. Combined with anonymous inner types, you can get into all kinds of trouble. The only down side is that it is much more verbose, although more object oriented than the stricnine/cyanide combo of typecast/instanceof. If that isn't enough for you and you still want to typecast your little heart out, you can use the following "hack."

All my Hibernate model objects descend from a base object. To this object I add three utility hack methods to punch past the proxy layer for type info purposes:

Code:
public class BaseModel {
  // all your id stuff goes here...
  . . .
  public boolean isInstance(Class clazz) {
    return this.getClass().isAssignableFrom(clazz);
  }

  public BaseModel unproxy() {
    return this;
  }

  public BaseModel unproxyIfInstance(Class clazz) {
    return isInstance(clazz) ? this : null;
  }
}


The first method can be used in place of instanceof. The second allows you to remove the proxy. The third method conveniently combines the first two, since in places like UI code you often use both of them together.

Because these methods are on the base class, the proxy mechanism will implement them. They will safely delegate the method calls back to the underlying object:

Code:
public Class A extends BaseModel {}
public Class B extends BaseModel {}

... // somewhere, later in your non-OO codebase...
BaseModel model = someService().getModel(id);
if (model.isInstance(A.class) {
  A a = (A)model.deproxy();
} else if (model.isInstance(B.class) {
  B b = (B)model.deproxy();
}

B b = (B)model.deproxyIfInstance(B.class);
if (b is null) // do something


Pretty frigtening, eh? What have I done...


Top
 Profile  
 
 Post subject: The need for Proxy Objects
PostPosted: Mon Dec 12, 2005 2:23 pm 
Newbie

Joined: Fri Feb 25, 2005 3:40 pm
Posts: 8
Location: Victoria, BC Canada
gschadow, why do I need Proxy objects? Because I use lazy initialization, and you get Proxy objects automatically then. If I didn't load lazily, the whole database would come back any time I tried to get a single object.

Cardsharp, I did indeed read your article about the Visitor pattern. I admire the ingenuity of the technique, but it breaks my heart to make these method calls for no good reason. Still, it worked and so I used it.

What really bothered me about this problem is that I have this mapped as <joined-subclass>'s but the parent table also has a discriminator column, so I have a type field on each object that tells me exactly what it is. But I can't tell hibernate about it because it doesn't allow discriminators on a joined subclass.

This was all in Hibernate 2, though. I think with Hibernate 3 we can use <subclass> with a join. That would allow me to work the discriminator in there. I haven't reworked the code to do that yet, but I will next time I'm looking to refactor that section. Still, I think it is too bad that I can't specify a discriminator on a joined-subclass, since that is an artificial limitation caused because the developers of hibernate don't particularly like joined subclasses.

Anyway, thanks to everyone for their help.


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