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.  [ 12 posts ] 
Author Message
 Post subject: NHibernateUtil.IsInitialized bug?
PostPosted: Mon Nov 12, 2007 9:23 am 
Beginner
Beginner

Joined: Tue Mar 27, 2007 4:54 am
Posts: 47
NHibernate version:
1.2

Has the NHibernateUtil.IsInitialized impl changed since prior versions? I might be wrong here, but as far as I remember the following worked ok in previous versions....

I have an User class with a simple collection, ApplicationRoleCollection, which is lazy loaded. Lazy loading works but NHibernateUtil.IsInitialized seems to always return true no matter if the proxy has been initialized or not.

The following little test will fail because IsInitialized returns true.
[pseudo]
User user = [sess].Load<User>(someId);
Assert.IsFalse(NHibernateUtil.IsInitialized(user.ApplicationRuleCollection));
[/pseudo]

I'm pretty sure lazy loading works because if the following snippet runs...
User user = Session.Load<User>(someId);
[sess].Close();
user.ApplicationRuleCollection[0].Something();
...NHibernate complains, "Could not initialize proxy - the owning Session was closed.", just as expected.

Has something changed regarding NHibernateUtil.IsInitialized() in nhib v 1.2?

Regards
Roger


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 12, 2007 11:29 am 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
This could very well be a bug. Please report it to JIRA. If you could also create a test case, that would be most helpful. Please see the following article for some information on how to do so. Thanks.
http://hibernate.org/428.html

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 12, 2007 1:23 pm 
Beginner
Beginner

Joined: Tue Mar 27, 2007 4:54 am
Posts: 47
I've reported it to JIRA with test included.

http://jira.nhibernate.org/browse/NH-1198

/R


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 13, 2007 7:21 pm 
Beginner
Beginner

Joined: Tue Mar 27, 2007 4:54 am
Posts: 47
I feel a bit ashamed of myself, turned out there was an obvious reason for this too happend. I exposed my collection in a wrapper (ReadonlyCollection<T>) which of course doesn't derive from IPersistentCollection which is looked for in nhib's IsInitialized method. In that case - IsInitialized always returns true.

However - I must say that to encapsulate collections is something "everybody" do? And when you have a complex graph and reading it all in the query would be a bad option - at least I heavily rely on IsInitalize and Initialize.

I cannot be the only one that run into this problem? Is the only option to implement something own that reads the "mapped collection field" through reflection directly and use this object to IsInitialize/Initialize?

For me it would be more obvious if Initialize and IsInitialzed would throw an exception if the object sent to them were unknown types instead of doing nothing/return true.

Regards
Roger


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 14, 2007 1:18 am 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
Can I close the JIRA issue then?

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 14, 2007 6:00 am 
Beginner
Beginner

Joined: Tue Mar 27, 2007 4:54 am
Posts: 47
I really don't know if this is considered a bug or not. I totally understand why nhibernate behaves the way it does, and I find it hard to see any general solution to this problem myself. But - I cannot be the only one encapsulting my collections. At least I think the IsInitialize/Initialize would throw if the collection is of unknown type.

Do you yourself have any recommendations about this? I guess the only solution is to somehow get the "real" mapped data and pass this to the IsInitialize/Initialize.

Regards
Roger


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 14, 2007 11:04 am 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
You can either expose the real collection so you can call IsInitialized() on it, or you can add an IsApplicationRolesInitialized() method on your domain class. The first solution obviously breaks encapsulation, the second adds dependency of NHibernate to your domain class. A third option that prevents both is to use a delegate; but the syntax is kind of ugly:
Code:
public delegate bool IsInitializedDelegate(object enitityOrCollection);

public bool IsApplicationRolesInitialized(IsInitializedDelegate isInitialized)
{
    return isInitialized(this.realApplicationRolesCollection)
}

and call it like this
Code:
User user = session.Load<User>(someId);
Assert.IsFalse(user.IsApplicationRulesInitialized(NHibernateUtil.IsInitialized));

There are many ways to skin a cat.

Ultimately, NHibernate only care that the collection is an IList or its generic variant. To throw an exception on an "unknown collection", it means going through the meta data and basically do a validation on every IsInitialized() call. Someone else is going to complain about performance problem then. Like everything, there is always a trade off. In this case, it has been chosen to leave that responsibility with the user/programmer. Hope this make sense.

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 14, 2007 11:17 am 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
Actually, NHibenrate can't even check the metadata as NHibernateUtil.IsInitialized() is only given a reference to an object. Without the class and property path, it wouldn't even know where to look.

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 14, 2007 11:23 am 
Beginner
Beginner

Joined: Tue Mar 27, 2007 4:54 am
Posts: 47
Thanks.

FYI - I did my own way of skinning the cat, I wrapped the IsInitialized/Initialize in my own method where I first check if the "proxy" is of type ReadonlyCollection<T> (99% of my props are) and in that case get the real proxy using reflection before hitting nhib's methods.
Just another way of skinning the cat ;). Feels a bit awkard, but it doesn't feel good letting my entities knowing whether its collections has been initialized or not.

I do get your point about exceptions. However - It doesn't feel good that IsInitialized returns true when a proxy isn't used. Maybe an enum saying Yes, No or LazyLoadingIsNotUsed? Would at least have had helped me a lot.

Thanks again for your help and keep up the good work! I'll be glad to contribute if I run into suitable JIRA issue.
/Roger


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 14, 2007 11:46 am 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
Thanks for choosing NHibernate and thanks for your feedback. We would love to get more people involved. I will keep my eyes peeled on JIRA and post some entry-level issues on the forum here.

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 19, 2007 6:15 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Roger, we have the same issue and implemented essentially the same kind of solution as you did. We created a helper class with an IsInitialized() method that detects if the property value is our wrapper collection class. When that is the case, instead of just calling NHibernateUtil.IsInitialized on the passed value, extract the otherwise-inaccesible NHibernate collection from the wrapper collection via reflection and call IsInitialized on that.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 19, 2007 6:43 pm 
Beginner
Beginner

Joined: Tue Mar 27, 2007 4:54 am
Posts: 47
Nels_P_Olsen,

Thanks for your reply. Yes - it sounds like the way I solved it. Glad to hear that more people than me use the same work around :)


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