Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 338837

Summary: JPA2: Metamodel entity processing requires specified entities in persistence.xml to avoid IllegalArgumentException - The type [null] is not the expected [EntityType] for the key class
Product: z_Archived Reporter: Michael OBrien <michael.f.obrien>
Component: EclipselinkAssignee: Nobody - feel free to take it <nobody>
Status: RESOLVED FIXED QA Contact:
Severity: major    
Priority: P2 CC: eclipselink.orm-inbox, michael.f.obrien
Version: unspecifiedFlags: michael.f.obrien: documentation+
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
URL: 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
Whiteboard:
Bug Depends on: 266912, 302606, 303722, 315287    
Bug Blocks: 337034, 338709    
Attachments:
Description Flags
Reproducing Java SE client jar
none
Metamodel change to warn about unreferenced model classes for Java SE and some Java EE container managed persistence contexts
none
Full Metamodel change to warn about unreferenced model classes for Java SE and some Java EE container managed persistence contexts
none
Full Metamodel change to warn about unreferenced model classes for Java SE and some Java EE container managed persistence contexts none

Description Michael OBrien CLA 2011-03-03 12:28:21 EST
>The following specification mandated JPA 2.0 IllegalArgumentException occurs because entity classes were not processed because they are missing from the search path or not specified.
This usually occurs in Java SE environments only.
This is the result of an incomplete specification of the entities in persistence.xml for Java SE RESOURCE_LOCAL environments and possibly Java EE 6 Web Profile JTA environments.

>Occurs when running JPA 2.0 Criteria or Metamodel code where we require an EntityType like the following
        EntityType cell_ = getEntityManager().getMetamodel().entity(Cell.class);
        Root<Cell> root = getEntityManager().getCriteriaBuilder().createQuery().from(Cell.class);

DDLGenerationClient [Java Application]	
	org.eclipse.persistence.example.jpa.server.common.DDLGenerationClient at localhost:4353	
		Thread [main] (Suspended)	
			MetamodelImpl.entity(Class<X>) line: 160	
			CriteriaQueryImpl<T>(AbstractQueryImpl<T>).from(Class<X>) line: 97	
			DDLGenerationClient.checkMetamodel() line: 436	
			DDLGenerationClient.doQuery() line: 460	
			DDLGenerationClient.main(String[]) line: 445	

>in
    public <X> EntityType<X> entity(Class<X> clazz) {
        Object aType = this.entities.get(clazz);
        if(aType instanceof EntityType) {
            return (EntityType<X>) aType;
        } else {
-->         throw new IllegalArgumentException(ExceptionLocalization.buildMessage(


We see the following exception - which is not very descriptive of the actual issue of missing metadata because of missing entity classes found during EntityManager predeploy

[EL Finest]: 2011-03-03 12:14:36.141--ServerSession(11582167)--Thread(Thread[main,5,main])--End deploying Persistence Unit dao.create.tables.derby.client; session file:/C:/view_w36a/examples/org.eclipse.persistence.example.jpa.server.common.ddlgen/bin/_dao.create.tables.derby.client; state Deployed; factoryCount 1
Exception in thread "main" java.lang.IllegalArgumentException: The type [null] is not the expected [EntityType] for the key class [class org.eclipse.persistence.example.jpa.server.business.Cell].
	at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.entity(MetamodelImpl.java:160)
	at org.eclipse.persistence.example.jpa.server.common.DDLGenerationClient.checkMetamodel(DDLGenerationClient.java:435)
	at org.eclipse.persistence.example.jpa.server.common.DDLGenerationClient.doQuery(DDLGenerationClient.java:459)
	at org.eclipse.persistence.example.jpa.server.common.DDLGenerationClient.main(DDLGenerationClient.java:444)

>using
    <persistence-unit name="dao.create.tables.derby.client" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <!-- exclude-unlisted-classes>false</exclude-unlisted-classes-->
       <!-- class>org.eclipse.persistence.example.jpa.server.business.Cell</class-->
        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
            <property name="eclipselink.target-database" value="Derby"/>            
            <property name="javax.persistence.jdbc.url" value="jdbc:derby://127.0.0.1:1527/dataparallel;create=true"/>
            <property name="javax.persistence.jdbc.user" value="APP"/>
            <property name="javax.persistence.jdbc.password" value="APP"/>
            <property name="eclipselink.logging.level" value="ALL"/>            
            <!-- property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
            <property name="eclipselink.ddl-generation.output-mode" value="both"/-->
        </properties>
    </persistence-unit>    


>workaround is
<exclude-unlisted-classes>false</exclude-unlisted-classes>
or
<class>org.eclipse.persistence.example.jpa.server.business.Cell</class>

>result is OK with either fix
cell_ EntityType: EntityTypeImpl@672904:Cell [ javaType: class org.eclipse.persistence.example.jpa.server.business.Cell descriptor: RelationalDescriptor(org.eclipse.persistence.example.jpa.server.business.Cell --> [DatabaseTable(EL_CELL)]), mappings: 7]


>Solution:
There are two ways into this problem.
1) We specify no entities at all and also do not specify <exclude-unlisted-classes>false</exclude-unlisted-classes>
- the result of this is a completely empty metamodel
2) We specify only part of the entities via <class> properties
- the result of this is selective IllegalArgumentException errors thrown when we attempt to use the missing EntityType classes - likely in a Criteria API query

Warn both for no (0) entities found and later that a specific type was not found - possibly as a result of a missing class reference
1) warn the user that no entities were found during the predeploy so the deploy iterates nothing during metamodel.initialize - actually nothing is done during initialize
MetamodelImpl@21350241 [ 0 Types: , 0 ManagedTypes: , 0 EntityTypes: , 0 MappedSuperclassTypes: , 0 EmbeddableTypes: ]
or in 
protected void initializeCanonicalMetamodel(Metamodel model)

DDLGenerationClient [Java Application]	
	org.eclipse.persistence.example.jpa.server.common.DDLGenerationClient at localhost:3057	
		Thread [main] (Suspended)	
			MetamodelImpl.initialize() line: 363	
			MetamodelImpl.<init>(DatabaseSession) line: 109	
			MetamodelImpl.<init>(EntityManagerSetupImpl) line: 128	
			EntityManagerSetupImpl.getMetamodel() line: 2209	
			EntityManagerSetupImpl.deploy(ClassLoader, Map) line: 413	
			EntityManagerFactoryImpl.getServerSession() line: 185	
			EntityManagerFactoryImpl.getMetamodel() line: 531	
			DDLGenerationClient.initialize(String) line: 137	
			DDLGenerationClient.doQuery() line: 453	
			DDLGenerationClient.main(String[]) line: 444	

>descriptors map is empty - we need to warn the user about this
this	MetamodelImpl  (id=37)	
	session	ServerSession  (id=40)	
		descriptors	HashMap<K,V>  (id=61)	
			size	0	

2) Change the IAE for a single missing entity to suggest that the entity class may not have been found or specified (it may be on purpose)
Security note: A search for a non-existent entity class may come through a user-generated query and may be a way of testing the system for hidden classes - we may want to not print the name
>The error message needs to change from 
The type [null] is not the expected [EntityType] for the key class [class org.eclipse.persistence.example.jpa.server.business.Cell].
to something like
No [EntityType] was found for the key class [class org.eclipse.persistence.example.jpa.server.business.Cell] in the Metamodel - please verify that the Entity class was referenced in persistence.xml using a specific <class>org.eclipse.persistence.example.jpa.server.business.Cell</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.
Comment 1 Michael OBrien CLA 2011-03-03 12:46:40 EST
Created attachment 190293 [details]
Reproducing Java SE client jar
Comment 5 Michael OBrien CLA 2011-03-04 14:36:50 EST
>Point 3: a get from an empty Map should behave differently than a get where at least 1 key:value pair exist.
- we need to pick up on an empty map for ManagedType|EntityType}EmbeddableType and preemptively warn the user that the map is likely empty because the model classes were not found (in the case of a managed persistence unit at least)
- we need to differentiate between managed/unmanaged in our working
- we need to answer the question - is a persistence context without any entities/mappedSuperclasses or embeddables valid?  Or can a persistence unit exist where no classes are marked with JPA annotations?  I think in the case of the metamodel - no.
Therefore - an empty metamodel should not pass through predeploy as valid.
Comment 6 Michael OBrien CLA 2011-03-07 16:56:06 EST
>An example output during an SE persistence context where the entities are not listed (in error)

[EL Finest]: 2011-03-07 17:21:17.884--ServerSession(18450577)--Thread(Thread[main,5,main])--End deploying Persistence Unit dao.create.tables.derby.client; session file:/C:/view_w36a/examples/org.eclipse.persistence.example.jpa.server.common.ddlgen/bin/_dao.create.tables.derby.client; state Deployed; factoryCount 1
[EL Warning]: 2011-03-07 17:21:17.899--Thread(Thread[main,5,main])--The collection of metamodel types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.  The lookup on [class org.eclipse.persistence.example.distributed.collatz.model.UnitOfWork] will return null.
Exception in thread "main" java.lang.IllegalArgumentException: No [EntityType] was found for the key class [class org.eclipse.persistence.example.distributed.collatz.model.UnitOfWork] in the Metamodel - please verify that the [Entity] class was referenced in persistence.xml using a specific <class>class org.eclipse.persistence.example.distributed.collatz.model.UnitOfWork</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.
	at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.entityEmbeddableManagedTypeNotFound(MetamodelImpl.java:170)
	at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.entity(MetamodelImpl.java:189)
	at org.eclipse.persistence.example.jpa.server.common.DDLGenerationClient.checkMetamodel(DDLGenerationClient.java:432)
	at org.eclipse.persistence.example.jpa.server.common.DDLGenerationClient.doQuery(DDLGenerationClient.java:457)
	at org.eclipse.persistence.example.jpa.server.common.DDLGenerationClient.main(DDLGenerationClient.java:442)
Comment 7 Michael OBrien CLA 2011-03-07 17:00:09 EST
Created attachment 190603 [details]
Metamodel change to warn about unreferenced model classes for Java SE and some Java EE container managed persistence contexts
Comment 8 Michael OBrien CLA 2011-03-07 18:35:56 EST
>regression test results - with
<testsuite errors="0" failures="0" hostname="????-pc2" name="org.eclipse.persistence.testing.tests.jpa.AllCMP3TestRunModel" tests="2257" time="658.269" timestamp="2011-03-07T21:59:16">
Comment 10 Michael OBrien CLA 2011-03-08 14:31:35 EST
Created attachment 190685 [details]
Full Metamodel change to warn about unreferenced model classes for Java SE and some Java EE container managed persistence contexts
Comment 11 Michael OBrien CLA 2011-03-08 14:57:06 EST
>Test results
>Invalid use case - parameter is null
EmbeddableType cell_ = getEntityManager().getMetamodel().embeddable(null);
[EL Warning]: 2011-03-08 15:18:47.35--Thread(Thread[main,5,main])--The collection of metamodel [EmbeddableType] types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.  The lookup on [null] will return null.
Exception in thread "main" java.lang.IllegalArgumentException: No [Embeddable] was found for the null key class parameter in the Metamodel - please specify the correct key class for the metamodel [Embeddable] class and verify that the key class was referenced in persistence.xml using a specific <class/> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.

>Invalid use case - parameter is not an Entity
EmbeddableType cell_ = getEntityManager().getMetamodel().embeddable(Object.class);
[EL Warning]: 2011-03-08 15:19:36.764--Thread(Thread[main,5,main])--The collection of metamodel [EmbeddableType] types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.  The lookup on [class java.lang.Object] will return null.
Exception in thread "main" java.lang.IllegalArgumentException: No [EmbeddableType] was found for the key class [java.lang.Object] in the Metamodel - please verify that the [Embeddable] class was referenced in persistence.xml using a specific <class>java.lang.Object</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.

>Valid use case - but entities are not specified in persistence.xml
EntityType cell_ = getEntityManager().getMetamodel().entity(Cell.class);
[EL Warning]: 2011-03-08 15:20:37.331--Thread(Thread[main,5,main])--The collection of metamodel [EntityType] types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.  The lookup on [class org.eclipse.persistence.example.jpa.server.business.Cell] will return null.
Exception in thread "main" java.lang.IllegalArgumentException: No [EntityType] was found for the key class [org.eclipse.persistence.example.jpa.server.business.Cell] in the Metamodel - please verify that the [Entity] class was referenced in persistence.xml using a specific <class>org.eclipse.persistence.example.jpa.server.business.Cell</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.

>Valid use case - but entities are not specified in persistence.xml
ManagedType cell_ = getEntityManager().getMetamodel().managedType(Cell.class);
[EL Warning]: 2011-03-08 15:20:57.375--Thread(Thread[main,5,main])--The collection of metamodel [ManagedType] types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.  The lookup on [class org.eclipse.persistence.example.jpa.server.business.Cell] will return null.
Exception in thread "main" java.lang.IllegalArgumentException: No [ManagedType] was found for the key class [org.eclipse.persistence.example.jpa.server.business.Cell] in the Metamodel - please verify that the [Managed] class was referenced in persistence.xml using a specific <class>org.eclipse.persistence.example.jpa.server.business.Cell</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.
Comment 12 Michael OBrien CLA 2011-03-08 15:51:31 EST
        EntityType cell_ = getEntityManager().getMetamodel().entity(Cell.class);      
	with <!-- exclude-unlisted-classes>false</exclude-unlisted-classes-->
[EL Warning]: 2011-03-08 16:18:37.339--Thread(Thread[main,5,main])--The collection of metamodel [EntityType] types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.  The lookup on [class org.eclipse.persistence.example.jpa.server.business.Cell] will return null.
Exception in thread "main" java.lang.IllegalArgumentException: No [EntityType] was found for the key class [org.eclipse.persistence.example.jpa.server.business.Cell] in the Metamodel - please verify that the [Entity] class was referenced in persistence.xml using a specific <class>org.eclipse.persistence.example.jpa.server.business.Cell</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.
	with <exclude-unlisted-classes>false</exclude-unlisted-classes>
cell_ EntityType: EntityTypeImpl@3190337:Cell [ javaType: class org.eclipse.persistence.example.jpa.server.business.Cell descriptor: RelationalDescriptor(org.eclipse.persistence.example.jpa.server.business.Cell --> [DatabaseTable(EL_CELL)]), mappings: 7]

        EmbeddableType cell_ = getEntityManager().getMetamodel().embeddable(Object.class);
[EL Warning]: 2011-03-08 16:09:43.197--Thread(Thread[main,5,main])--The collection of metamodel [EmbeddableType] types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.  The lookup on [class java.lang.Object] will return null.
Exception in thread "main" java.lang.IllegalArgumentException: No [EmbeddableType] was found for the key class [java.lang.Object] in the Metamodel - please verify that the [Embeddable] class was referenced in persistence.xml using a specific <class>java.lang.Object</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.

        // when would you get a non-null type but with the wrong type
        ManagedType cell_ = getEntityManager().getMetamodel().managedType(Cell.class);
	with <!-- exclude-unlisted-classes>false</exclude-unlisted-classes-->
[EL Warning]: 2011-03-08 16:18:01.033--Thread(Thread[main,5,main])--The collection of metamodel [ManagedType] types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.  The lookup on [class org.eclipse.persistence.example.jpa.server.business.Cell] will return null.
Exception in thread "main" java.lang.IllegalArgumentException: No [ManagedType] was found for the key class [org.eclipse.persistence.example.jpa.server.business.Cell] in the Metamodel - please verify that the [Managed] class was referenced in persistence.xml using a specific <class>org.eclipse.persistence.example.jpa.server.business.Cell</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.
	with <exclude-unlisted-classes>false</exclude-unlisted-classes>
cell_ EntityType: EntityTypeImpl@14779369:Cell [ javaType: class org.eclipse.persistence.example.jpa.server.business.Cell descriptor: RelationalDescriptor(org.eclipse.persistence.example.jpa.server.business.Cell --> [DatabaseTable(EL_CELL)]), mappings: 7]

        EmbeddableType cell_ = getEntityManager().getMetamodel().embeddable(null);
[EL Warning]: 2011-03-08 16:07:44.311--Thread(Thread[main,5,main])--The collection of metamodel [EmbeddableType] types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.  The lookup on [null] will return null.
Exception in thread "main" java.lang.IllegalArgumentException: No [EmbeddableType] was found for the null key class parameter in the Metamodel - please specify the correct key class for the metamodel [Embeddable] class and verify that the key class was referenced in persistence.xml using a specific <class/> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.

        // wrong type but existing
        EmbeddableType cell_ = getEntityManager().getMetamodel().embeddable(Cell.class);
[EL Warning]: 2011-03-08 16:10:52.045--Thread(Thread[main,5,main])--The collection of metamodel [EmbeddableType] types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.  The lookup on [class org.eclipse.persistence.example.jpa.server.business.Cell] will return null.
Exception in thread "main" java.lang.IllegalArgumentException: No [EmbeddableType] was found for the key class [org.eclipse.persistence.example.jpa.server.business.Cell] in the Metamodel - please verify that the [Embeddable] class was referenced in persistence.xml using a specific <class>org.eclipse.persistence.example.jpa.server.business.Cell</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.
Comment 13 Michael OBrien CLA 2011-03-08 15:59:38 EST
Created attachment 190696 [details]
Full Metamodel change to warn about unreferenced model classes for Java SE and some Java EE container managed persistence contexts
Comment 14 Michael OBrien CLA 2011-03-08 16:21:47 EST
>SVN rev# 9102
https://fisheye2.atlassian.com/changelog/eclipselink?cs=9102
Comment 15 Eclipse Webmaster CLA 2022-06-09 10:27:31 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink