Support generic domain models

Description

No reaction in forum to my bug so I create a JIRA issue for it:
https://forum.hibernate.org/viewtopic.php?f=1&t=1029259

I wondered why my Unit-Test-Case fails:
http://m-m-m.sourceforge.net/surefire-report.html#net.sf.mmm.persistence.impl.hibernateEnversTest

So I debugged what is going on. Actually hibernate is creating a JdbcPreparedStatement with 3 parameters but fills in 4 parameters.
This is happening because Hibernated created a ComponentType for my ID of the type Long and the ComponentType is composed out of two Long values.
This again happens because of a bug that exists since Java 1.5.
I reported this bug with ID "1059797" to the Java Bugtracker with Summary "Duplicate Method in Class.getDeclaredMethods() if return type overridden" but as Java is anything but Open-Source issues are hidden until Sun or now Oracle thinks that the public should be able to see them, what never happened for my bug, even though it has been confirmed by tons of other users.
I spend ~1 year to implement reflection on POJOs that actually works without bugs and is able to determine the proper type of a property, etc.
http://m-m-m.sourceforge.net/mmm-util/mmm-util-core/apidocs/net/sf/mmm/util/pojo/descriptor/api/package-summary.html#documentation

You should be aware that both hibernate and springframework as very prominent OSS projects so far fail to do this correctly. The only other implementation I was not yet able to find bugs is in guava.

So what is going wrong:
If you define a generic method like
public abstract class AbstractEntity<ID> {
...
@Id
public ID getId()
...
}

and then sub-class like

public class MyEntity extends AbstractEntity<Long> {
@Id
@GeneratedValue
public Long getId() {
return super.getId();
}
}

then Java will return two Method instances for getId on MyEntity from getDeclaredMethod() what IMHO violates the contract of getDeclaredMethod() and is an obvious bug in Java but the makes do not care.
Therefore Hibernate recognizes two id properties and therefore sets two Long values in the JdbcPreparedStatement with the ID value exceeding the parameter index.

So my suggestion to the world is: never ever try to create jet another (buggy) implementation of property introspection or resolving of type variables. Instead use an existing solution that is proved to work correctly.
However, if you want to keep your own implementation here is my workaround/hack that you may want to consider:
https://github.com/m-m-m/mmm/blob/master/mmm-util/mmm-util-core/src/main/java/net/sf/mmm/util/pojo/descriptor/impl/PojoDescriptorBuilderImpl.java#L198

With kind regards
Jörg

Environment

tested on windows with H2 but surely independent from this

Activity

Show:
Jörg Hohwiller
March 7, 2014, 10:34 PM

It is not as straight as I guessed initially. I tried to debug your code but actually had to give up.
Just to show you some impressions: I added a conditional breakpoint in Eclipse to TypeEnvironmentFactory.java:48 with the expression:
System.out.println("TypeEnvironmentFactory.createEnvironment(" + context + ")"); return false;

Then I get this:
[07 Mrz 2014 23:29:01] DEBUG [org.hibernate.validator.xml.ValidationXmlParser][getValidationConfig]: No META-INF/validation.xml found. Using annotation based configuration only
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.impl.hibernate.DummyRevisionedFooEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.impl.hibernate.DummyRevisionedFooEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.impl.hibernate.DummyRevisionedFooEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.impl.hibernate.DummyRevisionedFooEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.impl.hibernate.DummyRevisionedFooEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.impl.hibernate.DummyRevisionedFooEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.impl.hibernate.DummyRevisionedFooEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.impl.hibernate.DummyRevisionedFooEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.impl.hibernate.DummyRevisionedFooEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.JpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.persistence.base.jpa.AbstractJpaEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractRevisionedEntity)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)
TypeEnvironmentFactory.createEnvironment(class net.sf.mmm.util.entity.base.AbstractGenericEntity)
TypeEnvironmentFactory.createEnvironment(class java.lang.Object)

Your code might need some revisit. I wonder what will go on if I have more than just 4 JPA relevant classes.

Jörg Hohwiller
March 7, 2014, 11:30 PM

Back to the actual problem: I also have this test case:
https://github.com/m-m-m/mmm/blob/master/mmm-persistence/mmm-persistence-impl-jpa/src/test/java/net/sf/mmm/persistence/impl/jpa/PersistenceTest.java

It is currently running. If I modify this entity used by the above test:
https://github.com/m-m-m/mmm/blob/master/mmm-persistence/mmm-persistence-impl-jpa/src/test/java/net/sf/mmm/persistence/impl/jpa/test/impl/DummyBarEntityImpl.java
from:
public class DummyBarEntityImpl extends AbstractJpaEntity<Long> implements DummyBarEntity {
to:
public class DummyBarEntityImpl extends JpaEntity implements DummyBarEntity {
the test fails with:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'EntityManagerFactory' defined in class path resource [net/sf/mmm/persistence/beans-persistence-jpa-hibernate.xml]: Invocation of init method failed; nested exception is
...
Caused by: org.hibernate.MappingException: property mapping has wrong number of columns: net.sf.mmm.persistence.impl.jpa.test.impl.DummyFooEntityImpl.bar type: net.sf.mmm.persistence.impl.jpa.test.impl.DummyBarEntityImpl
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:484)
at org.hibernate.mapping.RootClass.validate(RootClass.java:270)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1324)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1786)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:96)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:914)
... 42 more

However JpaEntity is nothing but this:
@MappedSuperclass
public abstract class JpaEntity extends AbstractJpaEntity<Long> {

/** UID for serialization. */
private static final long serialVersionUID = 4280571250879388596L;

/**

  • The constructor.
    */
    public JpaEntity() {

super();
}

/**

  • {@inheritDoc}
    */
    @Override
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    public Long getId() {

return super.getId();
}

/**

  • {@inheritDoc}
    */
    @Override
    public void setId(Long id) {

super.setId(id);
}

}

Steve Ebersole
May 21, 2015, 2:22 PM

So my suggestion to the world is: never ever try to create jet another (buggy) implementation of property introspection or resolving of type variables. Instead use an existing solution that is proved to work correctly.

Must be so nice to start developing a library sometime after 2000. Before you start being all condescending you really ought to consider that Hibernate and Spring and many others have been around since way before Java even started supporting generics.

Also, nowhere does Hibernate claim to support generic classes. Hard for something to be a bug when it is not claimed to be supported (by definition).

We eagerly await your pull request incorporating your far superior reflection insights!

Jörg Hohwiller
May 24, 2015, 8:22 PM

Sorry for being condescending. It is clear that generics came after hibernate was invented and now it is a tough job to make it work perfectly. I would have loved that sun or later oracle would support this better OOTB in the JDK. However, from that point we have pretty much low level APIs. I have seen so many bugs where programmers start to deal with getTypeParameters() or in general working with java.lang.reflect.Type without understanding the underlying generic type-system what is actually a complex animal.
Also I do not want to play the smart guy: I wanted to port my reflection and bean introspection code in my open-source project to Java5 and generics those days in one weekend and actually it took me almost a year to get it done covering all scenarios I am aware of.
You pretty much have to reimplement what javac has already done based on the reflection API.
I am already active in various OSS projects and will get totally lost if I also start hacking in hibernate. So sorry to say so but I will not find the time in the next future to provide PRs for you.
You can copy my source-code if you like it without restrictions and my full permission from here or get inspirations from it if you like it:
https://github.com/m-m-m/util/blob/master/mmm-util-core/src/main/java/net/sf/mmm/util/reflect/impl/GenericTypeImpl.java
Also you can dig in guava source code that also does a good job on this task.
Simply accept that resolving a type in a generic way to an actual class in java is nothing you should implement here and there. However, this is what IMHO is currently done in hibernate code base.
I do not want to argue if something is a bug or not. But users of the JPA will use the potential of the Java language and expect the JPA vendor to deal with that. Sorry for being harsh in my comments - please ignore my ignorance and just think about all the hibernate users that do not want to see such stacktraces.

Assignee

Unassigned

Reporter

Jörg Hohwiller

Fix versions

None

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

Priority

Major
Configure