This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
Bug 315041 - JPA2: javaClass attribute is not set on RelationalDescriptor during of the call of EntityManagerFactoryImpl.getMetamodel method.
Summary: JPA2: javaClass attribute is not set on RelationalDescriptor during of the ca...
Status: CLOSED DUPLICATE of bug 303063
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P2 major (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL: http://wiki.eclipse.org/EclipseLink/D...
Whiteboard:
Keywords:
Depends on: 266912 297748 303063 322585
Blocks:
  Show dependency tree
 
Reported: 2010-05-31 05:29 EDT by Andrey Lomakin CLA
Modified: 2022-06-09 10:30 EDT (History)
3 users (show)

See Also:


Attachments
JPA Entity with problem (3.06 KB, text/x-java)
2010-05-31 05:29 EDT, Andrey Lomakin CLA
no flags Details
Entity MappedSuperClass (3.66 KB, text/x-java)
2010-05-31 05:30 EDT, Andrey Lomakin CLA
no flags Details
Do a getServerSession that will do a login/deploy as part of an entityManagerFactory.predeploy() so all metadata processing, ddlgeneration and metamodel initialization is complete before a create em (5.51 KB, patch)
2010-08-17 22:29 EDT, Michael OBrien CLA
no flags Details | Diff
Option 7 (in use): Do a getServerSession that does a deploy/login that calls initializeDescriptors only for early emf.getMetamodel() users - em.getMetamodel() users do not login (3.28 KB, patch)
2010-09-03 10:48 EDT, Michael OBrien CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Andrey Lomakin CLA 2010-05-31 05:29:41 EDT
Created attachment 170500 [details]
JPA Entity with problem

After the call of org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getCriteriaBuilder method we get following stack trace:

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:1956)
                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(NativeMethodAccessorImpl.java:39)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:423)
                at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:485)
                at $Proxy11.getCriteriaBuilder(Unknown Source)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:176)
                at $Proxy20.getCriteriaBuilder(Unknown Source)
Comment 1 Andrey Lomakin CLA 2010-05-31 05:30:53 EDT
Created attachment 170501 [details]
Entity MappedSuperClass
Comment 2 Andrey Lomakin CLA 2010-05-31 14:45:43 EDT
This issue is reproduced only in non-transactional context.
Comment 3 Tom Ware CLA 2010-06-14 14:30:11 EDT
Setting target and priority.  See the following page for details of what these fields mean:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines
Comment 4 Michael OBrien CLA 2010-08-05 16:51:46 EDT
>Reverify for 2.2 - I was not aware of this issue in 2.1
>in queue but not assigned yet
Comment 5 Michael OBrien CLA 2010-08-06 09:54:06 EDT
>The original fix for bug # 297748 is insufficient - the updated fix will affect or preclude the fix here
Comment 6 Michael OBrien CLA 2010-08-06 13:11:11 EDT
>voted on bugs get raised in the priority queue

>Some development history: It is assumed by the Metamodel API that metadata processing of RelationalDescriptors have their javaClass set (non-NULL)
There has been several scenarios where the javaClass is null - usually on @MappedSuperclass objects documented below.
bug # 303063
http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_101:_20100218:_Descriptor.javaClass_is_null_on_a_container_EM_for_a_specific_case

>This issue is one of them.
I think we cannot in the future "assume" that all metadata processing is complete (aka convertClassNamesToClasses()

>Hi, I inserted your part-model to quickly narrow down the problem
I need the entire hierarchy of this branch of your model to the root

>I am missing
  +-- ? (possibly none)
      +-- AbstractAggregateRoot (likely an abstract @MappedSuperclass)

>As withouth the E --> MS --> MS tree I am unable to reproduce this
I thought at first it may be the UUID Basic type - but this is coming in fine
It may be the UUIDConverter - but most likely what is above the ESAbstractAggregateRoot @MappedSuperclass
As you can see the following trace and variable post will show that the problem would be in the section that computes the [IdentifiableType] tree.

>Breakpoint during initialization
org.eclipse.persistence.example.jpa.server.common.DDLGenerationClient at localhost:49849	
	Thread [main] (Suspended)	
		MetamodelImpl.initialize() line: 373	
		MetamodelImpl.<init>(DatabaseSession) line: 101	
		MetamodelImpl.<init>(EntityManagerSetupImpl) line: 120	
		EntityManagerSetupImpl.getMetamodel() line: 2003	
		EntityManagerSetupImpl.deploy(ClassLoader, Map) line: 399	
		EntityManagerFactoryImpl.getServerSession() line: 157	
		EntityManagerFactoryImpl.createEntityManagerImpl(Map) line: 214	
		EntityManagerFactoryImpl.createEntityManager() line: 202	
		DDLGenerationClient.initialize(String) line: 130	
		DDLGenerationClient.doQuery() line: 425	
		DDLGenerationClient.main(String[]) line: 416	

>shows us a valid processed @MappedSuperclass (that temporarily inherits from Object
potentialIdentifiableType	MappedSuperclassTypeImpl<X>  (id=98)	
	descriptor	RelationalDescriptor  (id=96)	
	idAttributes	null	
	inheritingIdentifiableTypes	HashMap<K,V>  (id=145)	
	javaClass	Class<T> (org.eclipse.persistence.example.jpa.server.business.ESAbstractAggregateRoot) (id=113)	
	members	null	
	metamodel	MetamodelImpl  (id=21)	
	superType	null	
	versionAttribute	null	
aClass	Class<T> (org.eclipse.persistence.example.jpa.server.business.ESAbstractAggregateRoot) (id=113)	
>superclass	Class<T> (java.lang.Object) (id=9)	

>We end up with a valid Metamodel containing your two classes User --> ESAbstractAggregateRoot
tempMetaModel	MetamodelImpl  (id=21)	
	entities	LinkedHashMap<K,V>  (id=1806)	
		size	5	
		table	HashMap$Entry<K,V>[16]  (id=1821)	
			[10]	LinkedHashMap$Entry<K,V>  (id=1826)	
				after	LinkedHashMap$Entry<K,V>  (id=1827)	
					after	LinkedHashMap$Entry<K,V>  (id=1820)	
					before	LinkedHashMap$Entry<K,V>  (id=1826)	
					hash	33513469	
>					key	Class<T> (org.eclipse.persistence.example.jpa.server.business.User) (id=807)	
					next	null	
					value	EntityTypeImpl<X>  (id=1799)	
	managedTypes	LinkedHashMap<K,V>  (id=1807)	
	mappedSuperclasses	LinkedHashSet<E>  (id=1808)	
		map	LinkedHashMap<K,V>  (id=1810)	
			size	1	
			table	HashMap$Entry<K,V>[16]  (id=1812)	
				[12]	LinkedHashMap$Entry<K,V>  (id=1813)	
					after	LinkedHashMap$Entry<K,V>  (id=1811)	
					before	LinkedHashMap$Entry<K,V>  (id=1811)	
					hash	14885724	
					key	MappedSuperclassTypeImpl<X>  (id=1800)	
						descriptor	RelationalDescriptor  (id=1815)	
						idAttributes	HashSet<E>  (id=1816)	
						inheritingIdentifiableTypes	HashMap<K,V>  (id=1817)	
>						javaClass	Class<T> (org.eclipse.persistence.example.jpa.server.business.ESAbstractAggregateRoot) (id=967)	
						members	HashMap<K,V>  (id=1818)	
						metamodel	MetamodelImpl  (id=21)	
						superType	null	
						versionAttribute	null	
					value	Object  (id=1814)	
	types	LinkedHashMap<K,V>  (id=1809)	
		size	11	
		table	HashMap$Entry<K,V>[16]  (id=1867)	
			[1]	LinkedHashMap$Entry<K,V>  (id=1869)	
				key	Class<T> (java.util.UUID) (id=1877)	
				value	BasicTypeImpl<X>  (id=1878)	
>					javaClass	Class<T> (java.util.UUID) (id=1877)	

From your @Overrides in the middle class ESAbstractAggregateRoot - it looks like you have an @Id on both levels
      +-- AbstractAggregateRoot (likely an abstract @MappedSuperclass)
          +--ESAbstractAggregateRoot (abstract @MappedSuperclass)

It looks like you may have the following hierarchy
Object
  +-- ? (possibly none)
      +-- AbstractAggregateRoot (likely an abstract @MappedSuperclass)
          +--ESAbstractAggregateRoot (abstract @MappedSuperclass)
             +--User (concrete @Entity)

>After adding a fake AbstractAggregateRoot @MappedSuperclass above ESAbstractAggregateRoot I still process the Metamodel fine

tempMetaModel	MetamodelImpl  (id=21)	
  mappedSuperclasses	LinkedHashSet<E>  (id=62)	
    map	LinkedHashMap<K,V>  (id=134)	
      modCount	2	
  	size	2	
	table	HashMap$Entry<K,V>[16]  (id=137)	
  	  [2]	LinkedHashMap$Entry<K,V>  (id=139)	
  	    key	MappedSuperclassTypeImpl<X>  (id=48)	
  	      	descriptor	RelationalDescriptor  (id=146)	
  	      	idAttributes	HashSet<E>  (id=149)	
  	      	map	HashMap<K,V>  (id=194)	
  	      		table	HashMap$Entry<K,V>[16]  (id=196)	
  	      		[4]	HashMap$Entry<K,V>  (id=198)	
  	      				key	SingularAttributeImpl<X,T>  (id=200)	
  	      					elementType	BasicTypeImpl<X>  (id=182)	
  	      						javaClass	Class<T> (java.util.UUID) (id=205)	
  	      					managedType	MappedSuperclassTypeImpl<X>  (id=48)	
  	      					mapping	DirectToFieldMapping  (id=203)	
  	      			values	null	
  	      	inheritingIdentifiableTypes	HashMap<K,V>  (id=150)	
  	      	javaClass	Class<T> (org.eclipse.persistence.example.jpa.server.business.ESAbstractAggregateRoot) (id=151)	
  	      	members	HashMap<K,V>  (id=152)	
  	      	metamodel	MetamodelImpl  (id=21)	
  	      	superType	MappedSuperclassTypeImpl<X>  (id=45)	
  	  [12]	LinkedHashMap$Entry<K,V>  (id=141)	
  	    	key	MappedSuperclassTypeImpl<X>  (id=45)	
  	    	descriptor	RelationalDescriptor  (id=159)	
  	    	idAttributes	HashSet<E>  (id=160)	
  	    		map	HashMap<K,V>  (id=209)	
  	    			size	1	
  	    			table	HashMap$Entry<K,V>[16]  (id=211)	
  	    				[14]	HashMap$Entry<K,V>  (id=216)	
  	    					hash	22509022	
  	    					key	SingularAttributeImpl<X,T>  (id=177)	
  	    						elementType	BasicTypeImpl<X>  (id=182)	
  	    								javaClass	Class<T> (java.util.UUID) (id=205)	
  	    						managedType	MappedSuperclassTypeImpl<X>  (id=45)	
  	    						mapping	DirectToFieldMapping  (id=185)	
  	    					next	null	
  	    					value	Object  (id=144)	
  	    				[15]	null	
  	    			threshold	12	
  	    			values	null	
  	    	inheritingIdentifiableTypes	HashMap<K,V>  (id=161)	
  	    	javaClass	Class<T> (org.eclipse.persistence.example.jpa.server.business.AbstractAggregateRoot) (id=162)	
  	    	members	HashMap<K,V>  (id=163)	
  	    	metamodel	MetamodelImpl  (id=21)	
  	    	superType	null	

>So multiple UUID @Id attributes are not an issue
it is likely the actual hierarchy above ESAbstractAggregateRoot or in compination with the @Converter.
I will not put the bug to cannot-reproduce temporarily as a NPE is serious - I will until we get more reproduction info 
- add exception handling and more finest logging for this case which may be part of 
Could you also post the rest of this subtree hiearchy to get this reproduced.
This issue is a duplicate of DI 101 in bug# 303063
http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_101:_20100218:_Descriptor.javaClass_is_null_on_a_container_EM_for_a_specific_case

*** This bug has been marked as a duplicate of bug 303063 ***
Comment 7 Michael OBrien CLA 2010-08-17 22:29:47 EDT
Created attachment 176857 [details]
Do a getServerSession that will do a login/deploy as part of an entityManagerFactory.predeploy() so all metadata processing, ddlgeneration and metamodel initialization is complete before a create em

>Currently metamodel initialization is a 2-part process during emf.predeploy and em.deploy
>See design issue 106 option 3 for bug # 322585 that moves everything to emf.predeploy
http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_106:_20100810:_322585:Metamodel_initialization_via_EMF.getMetamodel.28.29_before_EM_deploy_results_in_an_invalid_Metamodel_because_of_UNINITIALIZED_descriptor.initializationStage

After trying 2 locations of a getServerSession() call in order to do a login before an official deploy() on createEntityManager - I came across code that already exists for JPA validation that will do a login for us and effect a deploy just after the predeploy finishes on the EMF. 

>shouldGetSessionOnCreateFactory()

>Performance Results 106-3
The following show that that the time taken to update the session, do DDL generation and intialize the metamodel and canonical metamodel has shifted to the EMF creation from the EM creation. In essence an emf.createEntityManager() now takes just a couple microseconds instead of seconds. 
Doing all the following in the predeploy 
  updateServerSession 
  session.login 
  generateDDL 
  metamodel initalization 
  canonical metamodel initialization 
takes in SE 
> with change 
  predeploy() = 2.6 sec 
   [EL Finest]: 2010-08-17 18:01:12.002--ServerSession(27196165)--Thread(Thread[main,5,main])--Begin predeploying Persistence Unit dao.create.tables.derby; session default-session; state Initial; factoryCount 0 
   [EL Finest]: 2010-08-17 18:01:14.67--ServerSession(27196165)--Thread(Thread[main,5,main])--End deploying Persistence Unit dao.create.tables.derby; session default-session; state Deployed; factoryCount 1 
  deploy() = 0.09 sec 
   [EL Finest]: 2010-08-17 18:01:14.67--ServerSession(27196165)--Thread(Thread[main,5,main])--End deploying Persistence Unit dao.create.tables.derby; session default-session; state Deployed; factoryCount 1 
   [EL Finer]: 2010-08-17 18:01:14.763--ServerSession(27196165)--Thread(Thread[main,5,main])--client acquired 
 
> without change 
  predeploy() = 0.75 sec 
   [EL Finest]: 2010-08-17 17:58:29.169--ServerSession(2279771)--Thread(Thread[main,5,main])--Begin predeploying Persistence Unit dao.create.tables.derby; session default-session; state Initial; factoryCount 0 
   [EL Finest]: 2010-08-17 17:58:29.934--ServerSession(2279771)--Thread(Thread[main,5,main])--End predeploying Persistence Unit dao.create.tables.derby; session default-session; state Predeployed; factoryCount 1 
  deploy() = 1.87 sec 
   [EL Finest]: 2010-08-17 17:58:29.934--ServerSession(2279771)--Thread(Thread[main,5,main])--Begin deploying Persistence Unit dao.create.tables.derby; session default-session; state Predeployed; factoryCount 1 
   [EL Finer]: 2010-08-17 17:58:31.806--ServerSession(2279771)--Thread(Thread[main,5,main])--client acquired 

On emf.createEntityManager() we just skip deploy/login in getServerSession(), login in createEntityManagerImpl as well as deploy/login in getServerSession() in the EntityManagerImpl constructor 
because the emf.createEntityManager() does virtually nothing after this change 

EE Server testing on WebLogic 10.3.3.0 via standard @PersitenceContext injection on a SSB @EJB injected on a servlet client is OK 

Notice that a predeploy also does a deploy now - previously the deploy was only done when the client persisted or read from the persistence unit (via injection) 

Daemon Thread [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] (Suspended (breakpoint at line 314 in EntityManagerSetupImpl))	
	EntityManagerSetupImpl.deploy(ClassLoader, Map) line: 314	
	EntityManagerFactoryImpl.getServerSession() line: 157	
	PersistenceProvider.createContainerEntityManagerFactory(PersistenceUnitInfo, Map) line: 243	
	PersistenceUnitInfoImpl.createEntityManagerFactory(boolean) line: 352	
	PersistenceUnitInfoImpl.createEntityManagerFactory() line: 332	
	PersistenceUnitInfoImpl.<init>(PersistenceUnitBean, PersistenceUnitConfigurationBean, GenericClassLoader, String, URL, URL) line: 134	
	ModulePersistenceUnitRegistry(AbstractPersistenceUnitRegistry).storeDescriptors(Map, Map) line: 336	
	ModulePersistenceUnitRegistry(AbstractPersistenceUnitRegistry).loadPersistenceDescriptor(VirtualJarFile, boolean, File) line: 250	
	ModulePersistenceUnitRegistry.<init>(GenericClassLoader, ApplicationContextInternal, Module, boolean) line: 69	
	EJBModule.setupPersistenceUnitRegistry() line: 221	
	EJBModule$1.execute() line: 322	
	PersistenceUnitRegistryInitializer.setupPersistenceUnitRegistries() line: 62	
	WebAppModule.prepare() line: 398	
	ScopedModuleDriver.prepare() line: 176	
	ModuleListenerInvoker.prepare() line: 199	
	DeploymentCallbackFlow$1.next(Object) line: 507	
	StateMachineDriver.nextState(StateChange, Object[]) line: 41	
	DeploymentCallbackFlow.prepare(Module[]) line: 149	
	DeploymentCallbackFlow.prepare() line: 45	
	BaseDeployment$1.next(Object) line: 1221	
	StateMachineDriver.nextState(StateChange, Object[]) line: 41	
	EarDeployment(BaseDeployment).prepare(DeploymentContext) line: 367	
	EarDeployment.prepare(DeploymentContext) line: 58	
	DeploymentStateChecker.prepare(DeploymentContext) line: 154	
	AppContainerInvoker.prepare(DeploymentContext) line: 60	
	RedeployOperation.createAndPrepareContainer() line: 98	
	RedeployOperation.doPrepare() line: 122	
	RedeployOperation(AbstractOperation).prepare() line: 217	
	DeploymentManager.handleDeploymentPrepare(Deployment, DeploymentManager$DeploymentRequestInfo) line: 747	
	DeploymentManager.prepareDeploymentList(ArrayList, DeploymentContext) line: 1216	
	DeploymentManager.handlePrepare(DeploymentContext) line: 250	
	DeploymentServiceDispatcher.prepare(DeploymentContext) line: 159	
	DeploymentReceiverCallbackDeliverer.doPrepareCallback(DeploymentContext) line: 171	
	DeploymentReceiverCallbackDeliverer.access$000(DeploymentReceiverCallbackDeliverer, DeploymentContext) line: 13	
	DeploymentReceiverCallbackDeliverer$1.run() line: 46	
	SelfTuningWorkManagerImpl$WorkAdapterImpl.run() line: 528	
	ExecuteThread.execute(Runnable) line: 201	
	ExecuteThread.run()
Comment 8 Michael OBrien CLA 2010-08-18 08:31:15 EDT
>Fix Summary/Workaround
Essentially this fix in bug # 322585 just makes validation default to true unless disabled
- validation is off by default
- login during emf predeploy is now on by default
>workaround is to enable validation in persistence.xml
The following property is named as though the persistence unit is "only" used for validation.  
In fact it validates the persistence unit by doing a deploy just after the predeploy - without waiting for client code to login - after that it behaves normally.
This solves our issue where we may get a NPE on an unitialized descriptor's javaClass (was null) set on a Metamodel ManagedType

     <property name="eclipselink.validation-only" value="True"/>
Comment 9 Michael OBrien CLA 2010-09-03 10:48:55 EDT
Created attachment 178160 [details]
Option 7 (in use): Do a getServerSession that does a deploy/login that calls initializeDescriptors only for early emf.getMetamodel() users - em.getMetamodel() users do not login
Comment 10 Michael OBrien CLA 2010-09-03 15:19:45 EDT
>See the fix for bug # 322585 in SVN rev# 8141 for 2.2 and 8142 for 2.1.2
https://fisheye2.atlassian.com/changelog/eclipselink/?cs=8141
We now do a preemptive DB login via getServerSession to force initializeDescriptors so that a MappedSuperclass javaClass is set on the descriptor when a client does an emf.getMetamodel() or emf.getCriteriaBuilder() before at least one EntityManager is created or logged in.
Comment 11 Eclipse Webmaster CLA 2022-06-09 10:30:06 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink