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.  [ 11 posts ] 
Author Message
 Post subject: ClassCastException when using Java5 Generics
PostPosted: Wed Jan 03, 2007 10:59 am 
Beginner
Beginner

Joined: Fri Nov 28, 2003 6:57 am
Posts: 20
I'm using Hibernate 3.2.1 with Java5 Generics.

My business model looks like this:
Code:
public class Contract<InvoiceType extends Invoice> {
   // ...
   private InvoiceType invoice;
   public InvoiceType getInvoice() {
      return invoice;
   }
   public void setInvoice(InvoiceType invoice) {
      this.invoice = invoice;
   }
}


Code:
public class SpecialContract extends Contract<SpecialInvoice> {
   // ...
}


Code:
public class SpecialInvoice extends Invoice {
   // ...
}



Persisting all this stuff works well, but when I have a persistant instance of SpecialContract, call getInvoide() and assign the result to a SpecialInvoice variable, I get a ClassCastException. The following code snippet illustrates it:
Code:
public class Test {
   public static void main(String[] args) throws Exception {
      Session session = HibernateUtil.getSession();
      SpecialContract contract = (SpecialContract) session.load(SpecialContract.class, new Long(1)); // retrives the special contract - this works
      SpecialInvoice invoice = contract.getInvoice(); // this works well in case of non-persistent code, but throws a ClassCastException when using Hibernate
      HibernateUtil.closeSession();
   }
}


That's the exception:

Code:
Exception in thread "main" java.lang.ClassCastException: packagename.Invoice$$EnhancerByCGLIB$$5b598911
   at packagename.Test.main


For completeness, here's the corresponding mapping:
Code:
<hibernate-mapping package="packagename">
   <class name="Contract" discriminator-value="C">
   ...
   <many-to-one name="invoice" cascade="all" />
</hibernate-mapping>


Isn't it possible to persist such generic fields using Hibernate or did I miss something in the configuration?

Thanks,

Thorsten[/code]


Last edited by thorstenschaefer on Wed Jan 03, 2007 12:41 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: CGLIB
PostPosted: Wed Jan 03, 2007 12:01 pm 
Beginner
Beginner

Joined: Wed Aug 31, 2005 3:54 am
Posts: 45
The ClassCast should be throwing when the cglib instantiate a lazy one to one relationship.

If you could debug this, what is the real type of object that create the call :
contract.getInvoice();

thanks


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 03, 2007 12:14 pm 
Beginner
Beginner

Joined: Thu Aug 31, 2006 2:31 pm
Posts: 25
Location: USA
HI ,
It shows all the depend objects are not loaded.Either you set lazy= false or load all the dependent object before closing the session.
Or you can get a session stored to threadLocal and close the session at the end.
So that you will get the right object instead of the Proxy Object.
Your error shows you are having Proxy Object .
Thanks,
Vinodh

_________________
I am using a shitty e-mail filtering system that caused a lot of bounces for the admin of this forum. I need to turn on my brain next time and update my e-mail address.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 03, 2007 12:17 pm 
Beginner
Beginner

Joined: Fri Nov 28, 2003 6:57 am
Posts: 20
If I call contract.getInvoice().getClass() I also get a ClassCastException. The debuger shows the following value for contract.getInvoice(): Invoice$$EnhancerByCGLIB$$75f1074d

I assume that the invoice is actually a Hibernate-generated proxy, but this proxy only extends form Invoice, not from SpecialInvoice (if I make a cast to Invoice, it works). However, I don't know how to solve this issue...

Any suggestions?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 03, 2007 12:20 pm 
Beginner
Beginner

Joined: Fri Nov 28, 2003 6:57 am
Posts: 20
vinodhts wrote:
It shows all the depend objects are not loaded.Either you set lazy= false or load all the dependent object before closing the session.
[...]
Your error shows you are having Proxy Object .


The session is opened at the time the exception occurs (actually, I'm using a threadlocal to store the session). I'm also aware that I'm using a proxy and, as stated before, I can cast it to Invoice. The real problem is that I cannot cast it to SpecialInvoice, although the proxied object is an instance of this class.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 03, 2007 12:24 pm 
Senior
Senior

Joined: Sun Jun 04, 2006 1:58 am
Posts: 136
thorstenschaefer wrote:
vinodhts wrote:
It shows all the depend objects are not loaded.Either you set lazy= false or load all the dependent object before closing the session.
[...]
Your error shows you are having Proxy Object .


The session is opened at the time the exception occurs (actually, I'm using a threadlocal to store the session). I'm also aware that I'm using a proxy and, as stated before, I can cast it to Invoice. The real problem is that I cannot cast it to SpecialInvoice, although the proxied object is an instance of this class.


use get instead of load !!

_________________
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 03, 2007 12:33 pm 
Beginner
Beginner

Joined: Fri Nov 28, 2003 6:57 am
Posts: 20
scarface wrote:
use get instead of load !!


This doesn't change anything. The problem is not getting a reference to the contract (proxy), but casting the invoice (proxy) to the special type. I think I need to tell Hibernate/CGLIB somehow that it should use the SpecialInvoice as the invoice proxy's supertype instead of only Invoice. But how?!?


Top
 Profile  
 
 Post subject: Well well well
PostPosted: Wed Jan 03, 2007 12:33 pm 
Beginner
Beginner

Joined: Wed Aug 31, 2005 3:54 am
Posts: 45
The class name designed in your mapping is Contract.
So it is for Contract that Hibernate dynamicaly generate a proxy.

So the getInvoice method return an Invoice object, not a SpecialInvoice object so that you cannot cast it into SpecialInvoice.


Top
 Profile  
 
 Post subject: Re: Well well well
PostPosted: Wed Jan 03, 2007 12:40 pm 
Beginner
Beginner

Joined: Fri Nov 28, 2003 6:57 am
Posts: 20
asic wrote:
The class name designed in your mapping is Contract.
So it is for Contract that Hibernate dynamicaly generate a proxy.

So the getInvoice method return an Invoice object, not a SpecialInvoice object so that you cannot cast it into SpecialInvoice.


Ahhh, ok. Unfortunately, I removed an important part from the mapping file in my initial post. Acutally, it looks like this:

Code:
<hibernate-mapping package="packagename">
   <class name="Contract" discriminator-value="C">
   ...
   <many-to-one name="invoice" cascade="all" />
   
   <subclass name="SpecialContract" discriminator-value="S">
   </subclass>

</hibernate-mapping>


In the subclass element, however, I do not "override" the invoice field. But in the Contract mapping, I just specified that theres an association for the field invoice - I didn't say something about the type. And the compile time type of field invoice in class SpecialContract is SpecialInvoice, so I would assume that it should work. Do I have to add something to my mapping?[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 04, 2007 4:55 am 
Beginner
Beginner

Joined: Fri Nov 28, 2003 6:57 am
Posts: 20
I've found a workaround for this issue: one has to override the invoice mapping in each subclass and specify the concrete class:

<hibernate-mapping package="packagename">
<class name="Contract" discriminator-value="C">
...
<many-to-one name="invoice" cascade="all" />

<subclass name="SpecialContract" discriminator-value="S">
<many-to-one name="invoice" class="SpecialInvoice" cascade="all" />
</subclass>

</hibernate-mapping>

However, I'm not sure if this is intended or if it's a bug. Hibernate knows that I'm requesting a SpecialContract and thus could infer that invoice has to be a SpecialInvoice, right? Can anyone tell if this behavior is intended? Otherwise, I'd file a bug.


Top
 Profile  
 
 Post subject: Hibernate and Generic
PostPosted: Thu Jan 04, 2007 9:44 am 
Beginner
Beginner

Joined: Wed Aug 31, 2005 3:54 am
Posts: 45
I 'm not sur that Hibernate and CGLib are compliant with the java 5 Generics. That's prehaps the reason why ....


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