I tried migrating my project from hibernate 3.4 to hibernate 3.5, and it seems there are problems with generics.
I post my example entities... similar to the one I have it (that are to complicated).
I get an error in the mapping of the OneToMany associationg.
First entity
Code:
@Entity
public class AlarmManager {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
protected long id;
public long getId() {
return id;
}
protected void setId(long id) {
this.id = id;
}
protected String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany( cascade=CascadeType.ALL,
mappedBy= "alarmManager",
fetch=FetchType.LAZY
)
private List<AbstractAlarm<? extends AbstractCause>> activeAlarmList = new ArrayList<AbstractAlarm<? extends AbstractCause>>();
public List<AbstractAlarm<? extends AbstractCause>> getActiveAlarmList() {
return activeAlarmList;
}
public void setActiveAlarmList(List<AbstractAlarm<? extends AbstractCause>> activeAlarmList) {
this.activeAlarmList = activeAlarmList;
}
}
Second entity
Code:
@Entity
public abstract class AbstractAlarm<E extends AbstractCause> {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
protected long id;
public long getId() {
return id;
}
@ManyToOne
protected AlarmManager alarmManager;
public AlarmManager getAlarmManager() {
return alarmManager;
}
public void setAlarmManager(AlarmManager alarmManager) {
this.alarmManager = alarmManager;
}
protected void setId(long id) {
this.id = id;
}
protected String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
an then something like
Code:
public abstract class AbstractCause {
// . . .
}
if you run a test with these classes in hibernate 3.4 it works.
With hibernate 3.5 no:
this is the stack trace:
Code:
org.hibernate.annotations.common.AssertionFailure: Fail to process type argument in a generic declaration. Type: class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
at org.hibernate.ejb.metamodel.AttributeFactory$PluralAttributeMetadataImpl.getClassFromGenericArgument(AttributeFactory.java:836)
at org.hibernate.ejb.metamodel.AttributeFactory$PluralAttributeMetadataImpl.<init>(AttributeFactory.java:748)
at org.hibernate.ejb.metamodel.AttributeFactory$PluralAttributeMetadataImpl.<init>(AttributeFactory.java:723)
at org.hibernate.ejb.metamodel.AttributeFactory.determineAttributeMetadata(AttributeFactory.java:518)
at org.hibernate.ejb.metamodel.AttributeFactory.buildAttribute(AttributeFactory.java:93)
at org.hibernate.ejb.metamodel.MetadataContext.wrapUp(MetadataContext.java:183)
at org.hibernate.ejb.metamodel.MetamodelImpl.buildMetamodel(MetamodelImpl.java:66)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:83)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:883)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:56)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)
at it.ge.burland.JPABasicTest.init(JPABasicTest.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
java.lang.NullPointerException
at it.ge.burland.JPABasicTest.sweep(JPABasicTest.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:37)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
and this is the code where the Assertion is thrown:
the class is org.hibernate.ejb.metamodel.AttributeFactory:
the type passed is:
it.ge.burland.AbstractAlarm<? extends it.ge.burland.AbstractCause>and the code inters the
else statement
Code:
private Class<?> getClassFromGenericArgument(java.lang.reflect.Type type) {
Class<?> javaType;
Object unsafeElementType = type;
if ( unsafeElementType instanceof Class ) {
javaType = (Class) unsafeElementType;
}
else if ( unsafeElementType instanceof TypeVariable ) {
final java.lang.reflect.Type upperBound = ( ( TypeVariable ) unsafeElementType ).getBounds()[0];
javaType = getClassFromGenericArgument( upperBound );
}
/*********************************
* IT ENTERS HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!
**********************************/
else {
throw new AssertionFailure("Fail to process type argument in a generic declaration. Type: "
+ type.getClass() );
}
return javaType;
}
public ValueContext getElementValueContext() {
return elementValueContext;
}
public PluralAttribute.CollectionType getAttributeCollectionType() {
return attributeCollectionType;
}
public ValueContext getMapKeyValueContext() {
return keyValueContext;
}
}
Even changing the attribute list from:
private List<AbstractAlarm<? extends AbstractCause>> activeAlarmList
to
private List<AbstractAlarm<?>> activeAlarmList
produces the same error.
Is it an error or an expected behaviour?
If it is a bug should I post it on the JIRA?
thanks Davide