h3. Summary When defining Hibernate one-to-many and many-to-many (bag/etc.) mappings using {{access="noop"}}, session factory initialization fails. More specifically, JPA metamodel generation fails with {{NullPointerException}} s while trying to process metadata related to {{access="noop"}} mappings.
When processing JPA entity metamodels for any-to-many associations, Hibernate expects mapping metadata to point to a non-null {{Member}} s . However, the {{access="noop"}} handler ({{PropertyAccessStrategyNoopImpl.GetterImpl}}) always returns a null {{Member}}. Null {{Member}}s are not handled, leading to NPEs.
This is specifically an issue with entity metamodel generation and is not seen when disabling {{hibernate.ejb.metamodel.population}}.
h3. Background
I know that {{access="noop"}} is a "secret" undocumented feature, but this feature has been very useful for our team. We are a small team maintaining a large application and have built a fair amount of dynamic query features around Hibernate. These queries depend on several relationships that are managed by the application but which don't exist as DTO fields. We are able to take advantage of these relationships by combining the {{lazy="true"}} and {{access="noop"}} attributes.
While this still technically works when using Hibernate criteria, it breaks when using the JPA metamodel. We recently upgraded from Hibernate 5.1.14 to Hibernate 5.4.2 and would like to begin our transition from Hibernate criteria to JPA.
h3. Reproduction
Test case attached (to be added to {{hibernate-core/src/test/java/org/hibernate/test/propertyref}}).
Stack trace: {code} Error performing callback invocation : org.hibernate.testing.junit4.BaseCoreFunctionalTestCase#buildSessionFactory org.hibernate.testing.junit4.CallbackException: org.hibernate.testing.junit4.BaseCoreFunctionalTestCase#buildSessionFactory at org.hibernate.testing.junit4.TestClassMetadata.performCallbackInvocation(TestClassMetadata.java:208) at org.hibernate.testing.junit4.TestClassMetadata.invokeCallback(TestClassMetadata.java:192) at org.hibernate.testing.junit4.TestClassMetadata.performCallbacks(TestClassMetadata.java:184) at org.hibernate.testing.junit4.TestClassMetadata.performBeforeClassCallbacks(TestClassMetadata.java:175) at org.hibernate.testing.junit4.BeforeClassCallbackHandler.evaluate(BeforeClassCallbackHandler.java:25) at org.hibernate.testing.junit4.AfterClassCallbackHandler.evaluate(AfterClassCallbackHandler.java:25) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:106) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38) at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:66) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:117) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137) at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.NullPointerException at org.hibernate.metamodel.internal.AttributeFactory.getSignatureType(AttributeFactory.java:910) at org.hibernate.metamodel.internal.AttributeFactory$PluralAttributeMetadataImpl.<init>(AttributeFactory.java:785) at org.hibernate.metamodel.internal.AttributeFactory$PluralAttributeMetadataImpl.<init>(AttributeFactory.java:762) at org.hibernate.metamodel.internal.AttributeFactory.determineAttributeMetadata(AttributeFactory.java:541) at org.hibernate.metamodel.internal.AttributeFactory.buildAttribute(AttributeFactory.java:90) at org.hibernate.metamodel.internal.MetadataContext.wrapUp(MetadataContext.java:238) at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.java:274) at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:294) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:462) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:708) at org.hibernate.testing.junit4.BaseCoreFunctionalTestCase.buildSessionFactory(BaseCoreFunctionalTestCase.java:118) at org.hibernate.testing.junit4.BaseCoreFunctionalTestCase.buildSessionFactory(BaseCoreFunctionalTestCase.java:105) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.hibernate.testing.junit4.TestClassMetadata.performCallbackInvocation(TestClassMetadata.java:205) ... 36 more {code} |
|