hibernate 5.0 + equinox 4.5.0 and custom UserType

408 Views Asked by At

I was able to get Hibernate 5.0 Osgi Bundles work with Equinox 4.5.0 in Unmanaged JPA mode. There is one problem though, when I use a custom UserType (for example TestTypeMapType which implements EnhancedUserType) in one of my entities I get the following exception:

org.hibernate.MappingException: Could not determine type for: com.xxx.yyy.TestTypeMapType, at table: TestTable, for columns: [org.hibernate.mapping.Column(testType)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:390)

When I check SimpleValue.java from Hibernate sources I see that it is using org.hibernate.internal.util.Reflecthelper to create the type info with the below line of code

ReflectHelper.classForName(typeName);

and ReflectHelper is using the below lines to create the type info

try {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    if (classLoader != null) {
        return classLoader.loadClass(typeName);
    }
}
catch(Throwable ignore){}

return Class.forName(typeName);

Both classLoader.loadClass and Class.forName throws the below exception

java.lang.ClassNotFoundException: com.xxx.yyy.TestTypeMapType cannot be found by org.hibernate.core_5.0.2.Final

But if I execute ReflectHelper.classForName contents directly from the bundle which creates the EntityManagerFactory, I can successfully create the type info of custom UserType. Specifically for the below example line-A and line-B works but line-C throws exception.

try {
    Class<?> typeClass = null;

    // A
    typeClass = Thread.currentThread().getContextClassLoader().loadClass("com.xxx.yyy.TestTypeMapType");

    // B
    typeClass = Class.forName("com.xxx.yyy.TestTypeMapType");

    // C
    typeClass = ReflectHelper.classForName("com.xxx.yyy.TestTypeMapType");
}
catch(Exception e){}

What can I do, so that my custom UserType can be discovered by hibernate in the osgi environment?

PS: I have no problems with other Entity classes, dialect, jdbc driver etc. and also ReflectHelper.classForName is deprecated and it is advised to use either ClassLoaderService or ClassLoaderAccess. Can it be a hibernate bug?

Thank you...

1

There are 1 best solutions below

0
user1936595 On

You need to use TypeContributor extension point as described here.

https://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/Hibernate_User_Guide.html#_extension_points

Example how it is done is at hibernate envers:

https://github.com/hibernate/hibernate-orm/blob/master/hibernate-envers/src/main/resources/OSGI-INF/blueprint/blueprint.xml

NOTE: You should register type contributor in the bundle that does not use entity manager instance directly or indirectly. Otherwise your type contributor will not be used for entity manager creation. I spent a lot of time debugging this. It is better to have a separate bundle just for user types.