In my project I use Spring Data Lovelace, Spring 5.1.1 and Eclipselink 2.7.3 with static weaving via the com.ethlo.persistence.tools:eclipselink-maven-plugin:2.7.1.1
plugin. Also, I am using OpenJDK 11.
The build works fine and the eclipselink-maven-plugin
is executed. It generates a persistence.xml
that looks fine to me.
But when I run the tests, I get a
Caused by: java.lang.IllegalArgumentException: No [ManagedType] was found for the key class [com.example.MyEntity] in the Metamodel - please verify that the [Managed] class was referenced in persistence.xml using a specific <class>com.example.MyEntity</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.
at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.entityEmbeddableManagedTypeNotFound(MetamodelImpl.java:180)
at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:527)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:74)
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:188)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:139)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:123)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:64)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:305)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:297)
at org.springframework.data.util.Lazy.getNullable(Lazy.java:211)
at org.springframework.data.util.Lazy.get(Lazy.java:94)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:300)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:119)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1804)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1741)
... 57 more
I already tried:
<exclude-unlisted-classes>false</exclude-unlisted-classes>
into the persistence.xml
manually: makes no difference, but then again, this property is "Not applicable to Java SE persistence units" anywayseclipselink.weaving
jpa property to false
like in the Spring Data Eclipselink example project: makes no differenceUpdate:
I debugged into the eclipselink initialization and it does not "know" my entity classes. In MetadataProcessor#initPersistenceUnitClasses
, they appear (so the persistence.xml
is correctly ingested) in the classNames
list. Eclipselink then iterates over all found class names and (among others) tries to find the @Entity
annotation by calling PersistenceUnitProcessor.isEntity(..)
which in turn calls candidateClass.isAnnotationPresent("javax.persistence.Entity")
- and that returns false.
In other words: The underlying problem seems to be that Eclipselink can not see the @Entity
annotation on my entity classes (which are present, of course).
Update 2:
I enabled eclipselink logging by inserting <property name="eclipselink.logging.level" value="ALL"/>
into the persistence.xml and got this output:
[EL Warning]: metamodel: 2018-10-17 08:15:13.449--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
[EL Warning]: metamodel: 2018-10-17 08:15:13.464--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 de.viaprinto.backoffice.elasticsearch.persistence.entity.ElasticsearchIndex] will return null.
[EL Warning]: metamodel: 2018-10-17 08:15:13.464--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 de.viaprinto.backoffice.elasticsearch.persistence.entity.ElasticsearchIndex] will return null.
So, no new information there.
Update 3:
The plot thickens: I debugged into how eclipselink builds its class metadata (which it cannot find the @Entity
annotation in). It uses ASM for that instead of using reflection. To be more precise, it uses its own repackaged version of (in this case) ASM 6.2 (repackaged as org.eclipse.persistence:org.eclipse.persistence.asm:2.7.3
). After correctly finding the annotation (in ClassReader:626
) it tries to Visit the NestedMembers attribute
(ClassReader:651
) and that fails with an UnsupportedOperationException
. Eclipselink catches this exception and adds a "virtual metadata class" (MetadataAsmFactory:143
) that contains no Annotation information.
I found an issue in Spring's issue tracker that seems to describe the exact same problem. Their solution was to enable experimental ASM 7 support. No idea yet how to do that in eclipselink.
My entity classes contain a nested class (an enum, to be precise) which seems to trigger the problem.
Eclipselink uses ASM to parse the entity classes and generate metadata which in turn gets used to decide whether an entity class is actually an entity (i.e. carries the @Entity
annotation).
When encountering the "nested member" (i.e. nested enum) in my entity classes, ASM 6.2 throws an UnsupportedOperationException
which makes eclipselink discard the already collected metadata for this class and generate dummy metadata which contains no annotations. Hence the error.
There are four ways to fix this:
ASM7_EXPERIMENTAL
in eclipselink's MetadataAsmFactory$ClassMetadataVisitor
constructor. I have not tested this but according to this it should fix the issue.Apparently, this has already been fixed in eclipselink master and their 2.7 branch, so the fix should be available in the next release.