Using the beanlib to duplication a hibernate persistant class which has sorted collections causes class cast exceotions:
java.lang.ClassCastException: com.saqib.MyClass
at java.util.TreeMap.compare(TreeMap.java:1085)
at java.util.TreeMap.put(TreeMap.java:463)
at java.util.TreeSet.add(TreeSet.java:209)
at net.sf.beanlib.hibernate.HibernateBeanTransformer.replicateCollection(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanTransformer.replicate(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanTransformer.transform(Unknown Source)
at net.sf.beanlib.BeanPopulator.doit(Unknown Source)
at net.sf.beanlib.BeanPopulator.processSetterMethod(Unknown Source)
at net.sf.beanlib.BeanPopulator.populate(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanTransformer.populate(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanTransformer.replicate(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanTransformer.transform(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanReplicator.copy(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanReplicator.copy(Unknown Source)
The class has a collection hibernate mapping that looks like this:
...
<set name="..." table="..." cascade="all-delete-orphan" lazy="true" sort="com.saqib.MySorter">
...
[I am Using Hibernate 2.x]
Anyways, digging into your code, in the
net.sf.beanlib.hibernate.HibernateBeanTransformer
class, it seems that when you create a Collection for a SortedSet, you dont specify a Comparator, which will then lead to a ClassCastExceptions when adding something to this Collection. This happens in the following method:
if (isJavaPackage(fromClass))
return createToInstanceAsCollection(from);
if (from instanceof SortedSet) {
SortedSet asSortedSet = (SortedSet)from;
// add the comparator to the sorted set
return new TreeSet<Object>(asSortedSet.comparator());
}
if (from instanceof Set)
return new HashSet<Object>();
if (from instanceof List)
return new ArrayList<Object>(from.size());
// don't know what collection, so use list
log.warn("Don't know what collection object:" + fromClass + ", so assume List.");
return new ArrayList<Object>(from.size());
}
And it worked!
I would say this is only a hack, since i am not an expert :)
I would like to get your opinion of this.
Also many thanks for this library! It saved me doing heaps of work to replicate Hibernate Persistent objects. Great Work!
Regards,
Saqib
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
if (isJavaPackage(fromClass))
return createToInstanceAsCollection(from);
if (from instanceof SortedSet) {
SortedSet asSortedSet = (SortedSet)from;
// add SortedSet's Comparator to the new TreeSet
return new TreeSet<Object>(asSortedSet.comparator());
}
if (from instanceof Set)
return new HashSet<Object>();
if (from instanceof List)
return new ArrayList<Object>(from.size());
// don't know what collection, so use list
log.warn("Don't know what collection object:" + fromClass + ", so assume List.");
return new ArrayList<Object>(from.size());
}
Sorry for the confustion...
Regards,
Saqib
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for reporting this bug. I think your proposed hack is a great hack :) I wonder if we should also clone the comparator object across instead of just copying the reference...
Would you be interested in writing a Junit Test case for this particular bug ?
Hanson
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
hmm... cloning the Comparator... good question... cloning would make sence if the Comparator had properties that needed to be copied... but simply using the reference makes sence if the Comparator has no properties. Perhaps we could use the Hibernate Replicators to create a copy of it... or could there be another class that does this 'cloning' for you? I guess to cover all the bases, cloning would be the only option.
I will write a JUnit Test case for this bug. I should have it tomorrow.
Regards,
Saqib
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
My apologies for not getting back to you with that unit test... i started writing it... but then something came up at work. If you are still interested, i will finish it off.
I will do a fresh checkout and try it out tomorrow.
In the maintime, i found another "bug". I will post it in a new thread...
Thanks for implementing the fix.
Regards,
Saqib
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi,
Using the beanlib to duplication a hibernate persistant class which has sorted collections causes class cast exceotions:
java.lang.ClassCastException: com.saqib.MyClass
at java.util.TreeMap.compare(TreeMap.java:1085)
at java.util.TreeMap.put(TreeMap.java:463)
at java.util.TreeSet.add(TreeSet.java:209)
at net.sf.beanlib.hibernate.HibernateBeanTransformer.replicateCollection(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanTransformer.replicate(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanTransformer.transform(Unknown Source)
at net.sf.beanlib.BeanPopulator.doit(Unknown Source)
at net.sf.beanlib.BeanPopulator.processSetterMethod(Unknown Source)
at net.sf.beanlib.BeanPopulator.populate(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanTransformer.populate(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanTransformer.replicate(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanTransformer.transform(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanReplicator.copy(Unknown Source)
at net.sf.beanlib.hibernate.HibernateBeanReplicator.copy(Unknown Source)
The class has a collection hibernate mapping that looks like this:
...
<set name="..." table="..." cascade="all-delete-orphan" lazy="true" sort="com.saqib.MySorter">
...
[I am Using Hibernate 2.x]
Anyways, digging into your code, in the
net.sf.beanlib.hibernate.HibernateBeanTransformer
class, it seems that when you create a Collection for a SortedSet, you dont specify a Comparator, which will then lead to a ClassCastExceptions when adding something to this Collection. This happens in the following method:
net.sf.beanlib.hibernate.HibernateBeanTransformer.createToCollection()
So i modified this class to look like this:
private Collection<Object> createToCollection(Collection<?> from)
throws InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException
{
Class fromClass = from.getClass();
if (isJavaPackage(fromClass))
return createToInstanceAsCollection(from);
if (from instanceof SortedSet) {
SortedSet asSortedSet = (SortedSet)from;
// add the comparator to the sorted set
return new TreeSet<Object>(asSortedSet.comparator());
}
if (from instanceof Set)
return new HashSet<Object>();
if (from instanceof List)
return new ArrayList<Object>(from.size());
// don't know what collection, so use list
log.warn("Don't know what collection object:" + fromClass + ", so assume List.");
return new ArrayList<Object>(from.size());
}
And it worked!
I would say this is only a hack, since i am not an expert :)
I would like to get your opinion of this.
Also many thanks for this library! It saved me doing heaps of work to replicate Hibernate Persistent objects. Great Work!
Regards,
Saqib
Whoops... sorry, the code should be:
private Collection<Object> createToCollection(Collection<?> from)
throws InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException
{
Class fromClass = from.getClass();
if (isJavaPackage(fromClass))
return createToInstanceAsCollection(from);
if (from instanceof SortedSet) {
SortedSet asSortedSet = (SortedSet)from;
// add SortedSet's Comparator to the new TreeSet
return new TreeSet<Object>(asSortedSet.comparator());
}
if (from instanceof Set)
return new HashSet<Object>();
if (from instanceof List)
return new ArrayList<Object>(from.size());
// don't know what collection, so use list
log.warn("Don't know what collection object:" + fromClass + ", so assume List.");
return new ArrayList<Object>(from.size());
}
Sorry for the confustion...
Regards,
Saqib
Hi Jam,
Thanks for reporting this bug. I think your proposed hack is a great hack :) I wonder if we should also clone the comparator object across instead of just copying the reference...
Would you be interested in writing a Junit Test case for this particular bug ?
Hanson
Hi Hanson,
hmm... cloning the Comparator... good question... cloning would make sence if the Comparator had properties that needed to be copied... but simply using the reference makes sence if the Comparator has no properties. Perhaps we could use the Hibernate Replicators to create a copy of it... or could there be another class that does this 'cloning' for you? I guess to cover all the bases, cloning would be the only option.
I will write a JUnit Test case for this bug. I should have it tomorrow.
Regards,
Saqib
Hi Saqib,
It turns out the fix is a little bit more complicated in the general case, and needs to be made both for SortedSet and SortedMap .
Anyhow, it is now available for download in the beanlib-3.0.6 release. Please let me know if any problem.
Cheers,
Hanson
Hi Hanson,
My apologies for not getting back to you with that unit test... i started writing it... but then something came up at work. If you are still interested, i will finish it off.
I will do a fresh checkout and try it out tomorrow.
In the maintime, i found another "bug". I will post it in a new thread...
Thanks for implementing the fix.
Regards,
Saqib
You may have a look at HibernateBeanReplicatorTestComparator.java which is a junit test for the comparator related changes.
I am definitely interested if your tests cover more cases.