Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring 3.0, EclipseLink 2.0.0 (JPA 2.0), getCriteriaBuilder() NullPointerException [SPR-6826] #11492

Closed
spring-projects-issues opened this issue Feb 11, 2010 · 8 comments
Assignees
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) status: declined A suggestion or change that we don't feel we should currently apply

Comments

@spring-projects-issues
Copy link
Collaborator

Tomas Milo opened SPR-6826 and commented

With final version of Spring 3.0 after calling getCriteriaBuilder() I received following exception:

Exception in thread "main" java.lang.NullPointerException
at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.initialize(MetamodelImpl.java:370)
at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.<init>(MetamodelImpl.java:101)
at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.<init>(MetamodelImpl.java:120)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.getMetamodel(EntityManagerSetupImpl.java:1939)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getMetamodel(EntityManagerFactoryImpl.java:472)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getCriteriaBuilder(EntityManagerFactoryImpl.java:456)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:431)
at $Proxy6.getCriteriaBuilder(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:160)
at $Proxy10.getCriteriaBuilder(Unknown Source)
at dao.impl.TestDao.getCustomerBySurname(TestDao.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy12.getCustomerBySurname(Unknown Source)
at service.impl.TestService.getCustomerBySurname(TestService.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy13.getCustomerBySurname(Unknown Source)
at main.StartTest.main(StartTest.java:26)

In latest nightly snapshot (3.0.1.CI-577) it also doesn't work.
With Spring 3.0 RC3 it works.


Affects: 3.0 GA

Attachments:

@spring-projects-issues
Copy link
Collaborator Author

Tomas Milo commented

Example illustrating problem.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

This seems to be a bug in EclipseLink, where that javaClass property suddenly is null there, running into the NullPointerException.

What we changed in Spring 3.0 GA is simply to obtain the CriteriaBuilder directly from the EntityManagerFactory. So on a shared EntityManager proxy, em.getCriteriaBuilder() is basically equivalent to calling emf.getCriteriaBuilder() on the containing EntityManagerFactory.

However, if this doesn't work with EclipseLink 2.0.0, there must be a bug hiding somewhere - possibly with retrieving the CriteriaBuilder from the EntityManagerFactory in particular. Note that I cannot reproduce this within our test suite: emf.getCriteriaBuilder() works just fine there.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Michael O'Brien commented

Juergen, Tomas,
Thank you for raising this issue. The base change to handle the case where we have an unexpected invalid descriptor.javaClass uninitialized as null is being tracked by bug# 303063.
http://bugs.eclipse.org/303063

/michael
http://www.eclipselink.org

@spring-projects-issues
Copy link
Collaborator Author

Michael O'Brien commented

Bottom line is that this error is not occuring for standard Java SE deployments - only EE and Spring container apps
This very simple test case is very helpfull in getting this fixed asap.

The documentation needs to be updated - see...
http://jira.springframework.org/browse/SPR-6469?page=com.atlassian.jira.plugin.ext.bamboo%3Abamboo-build-results-tabpanel
-javaagent:spring-agent.jar
now
-javaagent:c:\opt\spring3\org.springframework.instrument-3.0.0.RELEASE.jar
org.springframework.instrument-3.0.0.jar

  1. I ran the example Customer entity in a pure EclipseLink SE application and did not receive any exceptions.
    value EntityTypeImpl<X> (id=191)
    descriptor RelationalDescriptor (id=195)
    alias "Customer" (id=201)
    javaClass Class<T> (Customer) (id=189)
    javaClassName "Customer" (id=250)
    idAttributes HashSet<E> (id=360)
    javaClass Class<T> (Customer) (id=189)
    members HashMap<K,V> (id=362)
    metamodel MetamodelImpl (id=62)
    superType null
    versionAttribute null
  1. I ran your example (modified to run on the Derby DB) - the configuration in persistence unit defined in persistence.xml is missing a reference to the entity (for non-EE containers)
    Add
    <class>model.Customer</class>
    And you will see
    [EL Finer]: 2010-02-18 17:00:29.848--ServerSession(15794899)--Thread(Thread[main,5,main])--Class [model.Customer] registered to be processed by weaver.
    And the reproduction
    18-Feb-2010 5:00:29 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
    INFO: Bean 'emf' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    18-Feb-2010 5:00:29 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
    INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1b8f864: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,testService,testDao,org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,transactionManager,emf,postgresqlDataSource]; root of factory hierarchy
    Exception in thread "main" java.lang.NullPointerException
    at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.initialize(MetamodelImpl.java:371)
    at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.<init>(MetamodelImpl.java:101)

Debugging before this (where the TypeImpl is constructed) I see that the descriptor only has it's class name set - we have seen this before - it is related to several delayed descriptor initialization issues.
this EntityTypeImpl<X> (id=93)
descriptor RelationalDescriptor (id=102)
additionalAggregateCollectionKeyFields null
additionalTablePrimaryKeyFields null
additionalWritableMapKeyFields ArrayList<E> (id=133)
alias "Customer" (id=137)
..
isNativeConnectionRequired false
javaClass null
javaClassName "model.Customer" (id=162)
lockableMappings null
idAttributes null
javaClass null
members null
metamodel MetamodelImpl (id=100)
superType null
versionAttribute null

Thread [main] (Suspended (breakpoint at line 126 in ManagedTypeImpl))
EntityTypeImpl<X>(ManagedTypeImpl<X>).<init>(MetamodelImpl, RelationalDescriptor) line: 126
EntityTypeImpl<X>(IdentifiableTypeImpl<X>).<init>(MetamodelImpl, RelationalDescriptor) line: 73
EntityTypeImpl<X>.<init>(MetamodelImpl, RelationalDescriptor) line: 51
ManagedTypeImpl<X>.create(MetamodelImpl, RelationalDescriptor) line: 442
MetamodelImpl.initialize() line: 321
MetamodelImpl.<init>(DatabaseSession) line: 101
MetamodelImpl.<init>(EntityManagerSetupImpl) line: 120
EntityManagerSetupImpl.getMetamodel() line: 1968
EntityManagerFactoryImpl.getMetamodel() line: 480
EntityManagerFactoryImpl.getCriteriaBuilder() line: 463
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(Object, Method, Object[]) line: 431
$Proxy6.getCriteriaBuilder() line: not available
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(Object, Method, Object[]) line: 160
$Proxy10.getCriteriaBuilder() line: not available
TestDao.getCustomerBySurname(String) line: 32
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 307
ReflectiveMethodInvocation.invokeJoinpoint() line: 183
ReflectiveMethodInvocation.proceed() line: 150
PersistenceExceptionTranslationInterceptor.invoke(MethodInvocation) line: 137
ReflectiveMethodInvocation.proceed() line: 172
JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 202
$Proxy12.getCustomerBySurname(String) line: not available
TestService.getCustomerBySurname(String) line: 30
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 307
ReflectiveMethodInvocation.invokeJoinpoint() line: 183
ReflectiveMethodInvocation.proceed() line: 150
TransactionInterceptor.invoke(MethodInvocation) line: 107
ReflectiveMethodInvocation.proceed() line: 172
JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 202
$Proxy13.getCustomerBySurname(String) line: not available
StartTest.main(String[]) line: 26

@spring-projects-issues
Copy link
Collaborator Author

Michael O'Brien commented

Even with NPE handlers we need to fix the root lazy-set-javaClass in descriptor problem because criteria/metamodel users will still fail
on an AbstractQueryImpl.from() for example - when standard JPA 2 type checking is applied

Caused by: java.lang.IllegalArgumentException: The type [null] is not the expected [EntityType] for the key class [class model.Customer].
at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.entity(MetamodelImpl.java:152)
at org.eclipse.persistence.internal.jpa.querydef.AbstractQueryImpl.from(AbstractQueryImpl.java:97)
at dao.impl.TestDao.getCustomerBySurname(TestDao.java:34)

@spring-projects-issues
Copy link
Collaborator Author

Michael O'Brien commented

For Spring containerMode=true at least...
It looks like we are not calling Project.convertClassNamesToClasses during the deploy call from LocalContainerEntityManagerFactoryBean when the injected EntityManager is deployed
Normally this happens after predeploy() during createEntityManager for an SE app - I am debugging an EE app on either WebLogic/JBoss/GlassFish to verify

On Spring in this case - the Metadata javaClass and descriptor.javaClassName are set (but not the javaClass yet)
Thread [main] (Suspended)
MetadataDescriptor.setJavaClass(MetadataClass) line: 1510
MetadataDescriptor.<init>(MetadataClass) line: 214
EntityAccessor(ClassAccessor).<init>(MetadataAnnotation, MetadataClass, MetadataProject) line: 171
EntityAccessor(MappedSuperclassAccessor).<init>(MetadataAnnotation, MetadataClass, MetadataProject) line: 180
EntityAccessor.<init>(MetadataAnnotation, MetadataClass, MetadataProject) line: 136
MetadataProcessor.initPersistenceUnitClasses() line: 268
MetadataProcessor.processEntityMappings() line: 446
PersistenceUnitProcessor.processORMetadata(MetadataProcessor, boolean) line: 386
EntityManagerSetupImpl.predeploy(PersistenceUnitInfo, Map) line: 947
PersistenceProvider.createContainerEntityManagerFactory(PersistenceUnitInfo, Map) line: 202
LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory() line: 225

normally this happens for an SE EM or an application managed EM on an EE server
Thread [main] (Suspended (breakpoint at line 4070 in ClassDescriptor))
RelationalDescriptor(ClassDescriptor).setJavaClass(Class) line: 4070
RelationalDescriptor(ClassDescriptor).convertClassNamesToClasses(ClassLoader) line: 1266
Project.convertClassNamesToClasses(ClassLoader) line: 362
EntityManagerSetupImpl.deploy(ClassLoader, Map) line: 322
EntityManagerFactoryImpl.getServerSession() line: 153
EntityManagerFactoryImpl.createEntityManagerImpl(Map) line: 210
EntityManagerFactoryImpl.createEntityManager() line: 198
PersistenceService.initialize() line: 32
PersistenceService.persistObjects(List) line: 136
PersistenceService.persistHyperCube() line: 96
Client.doTableGeneration() line: 14
Client.main(String[]) line: 25

On the GlassFish server
GlassFish v2.1.1 Java EE 5 at localhost [Application Server (GlassFish or Sun)]
BEA JRockit(R)[localhost:9009]
Thread [Thread-21] (Running)
Thread [SelectorThread-8080] (Running)
Daemon Thread [httpSSLWorkerThread-8080-0] (Suspended (breakpoint at line 4070 in ClassDescriptor))
RelationalDescriptor(ClassDescriptor).setJavaClass(Class) line: 4070
RelationalDescriptor(ClassDescriptor).convertClassNamesToClasses(ClassLoader) line: 1266
Project.convertClassNamesToClasses(ClassLoader) line: 362
EntityManagerSetupImpl.deploy(ClassLoader, Map) line: 324
EntityManagerFactoryImpl.getServerSession() line: 153
EntityManagerFactoryImpl.createEntityManagerImpl(Map) line: 210
EntityManagerFactoryImpl.createEntityManager() line: 198
ApplicationManagedService.initialize(String) line: 38

In Spring we go directly to weaving instead (where there is no Project.convertClassNamesToClasses() call in a deploy from Springs' LocalContainerEntityManagerFactoryBean
where className=model/Customer
[EL Finest]: 2010-02-18 22:29:32.367--ServerSession(4940455)--Thread(Thread[main,5,main])--Begin weaver class transformer processing class [model/Customer].
Note the difference from WebLogic weaving where the className uses "." package delimiters instead of "/" slashes
[EL Finest]: 2010-01-20 10:01:32.274--ServerSession(8493003)--Thread(Thread[[ACTIVE] ..])--Begin weaver class transformer processing class [org.eclipse.persistence.example.business.Cell].
should not be an issue as the byte code is loaded

Thread [main] (Suspended (breakpoint at line 91 in PersistenceWeaver))
PersistenceWeaver.transform(ClassLoader, String, Class, ProtectionDomain, byte[]) line: 91
ClassFileTransformerAdapter.transform(ClassLoader, String, Class, ProtectionDomain, byte[]) line: 56 InstrumentationLoadTimeWeaver$FilteringClassFileTransformer.transform(ClassLoader, String, Class, ProtectionDomain, byte[]) line: 181
TransformerManager.transform(ClassLoader, String, Class, ProtectionDomain, byte[]) line: 169
InstrumentationImpl.transform(ClassLoader, String, Class, ProtectionDomain, byte[], boolean) line: 365

The result of this is we later place the descriptor into a map using a null key
{null=RelationalDescriptor(model.Customer --> [DatabaseTable(CUSTOMER)])}
However the null key really has no effect since we are only iterating the values - it is the lookup of this null javaClass that is causing the issue.

Thread [main] (Suspended)
HashMap<K,V>.putForNullKey(V) line: 393
HashMap<K,V>.put(K, V) line: 371
Project.getDescriptors() line: 553
ServerSession(AbstractSession).getDescriptors() line: 1722
MetamodelImpl.initialize() line: 319
MetamodelImpl.<init>(DatabaseSession) line: 101
MetamodelImpl.<init>(EntityManagerSetupImpl) line: 120
EntityManagerSetupImpl.getMetamodel() line: 1968
EntityManagerFactoryImpl.getMetamodel() line: 480
EntityManagerFactoryImpl.getCriteriaBuilder() line: 463
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(Object, Method, Object[]) line: 431
$Proxy6.getCriteriaBuilder() line: not available

@spring-projects-issues
Copy link
Collaborator Author

Carlos Verdes commented

I think is something about Spring.

If I have:
CriteriaQuery<EntityType> criteriaQuery = getEntityManager().getCriteriaBuilder()
.createQuery(entityClass);

...where getEntityManager() is a method that returns:
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
protected EntityManager entityManager;

Then npe occurs.

However, if I create the EM manually it works:

EntityManager em = getEntityManagerFactory().*createEntityManager()*;
CriteriaQuery<EntityType> criteriaQuery = em.getCriteriaBuilder()
          .createQuery(entityClass);

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Does it work for you if you obtain the CriteriaBuilder through getEntityManagerFactory().getCriteriaBuilder() - i.e. through the EntityManagerFactory rather than through the EntityManager? That's basically what Spring does underneath, so I'd expect you to get an NPE from that native JPA call as well...

Juergen

@spring-projects-issues spring-projects-issues added type: bug A general bug status: declined A suggestion or change that we don't feel we should currently apply in: data Issues in data modules (jdbc, orm, oxm, tx) labels Jan 11, 2019
@spring-projects-issues spring-projects-issues removed the type: bug A general bug label Jan 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

2 participants