I need to manage 2 databases in my application. For it, i have developed a sample application using EclipseLink Composite Persistence Unit feature.
However during my tests i notice a strange behaviour:
- basics jpa operations (persist, merge, remove or JPQL code) work perfectly
- but when i use the criteria api, EclipseLink return me the following error:
java.lang.IllegalArgumentException: No [EntityType] was found for the key class [com.example.common.entity.ThirdParty] in the Metamodel - please verify that the [Entity] class was referenced in persistence.xml using a specific <class>com.example.common.entity.ThirdParty</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.
at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.entityEmbeddableManagedTypeNotFound(MetamodelImpl.java:177)
at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.entity(MetamodelImpl.java:198)
at org.eclipse.persistence.internal.jpa.querydef.CommonAbstractCriteriaImpl.internalFrom(CommonAbstractCriteriaImpl.java:113)
at org.eclipse.persistence.internal.jpa.querydef.AbstractQueryImpl.from(AbstractQueryImpl.java:246)
at com.example.data.dao.ClientTest.testSelectByCriteria(ClientTest.java:125)
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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
This is the code of my sample (basically 2 entities and one Junit test)
My composite persistence.xml:
<persistence-unit name="testPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="testPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jar-file>file://D:\projects\prj-archetypes\trunk\workspace\sample\sample-common\target\sample-common-0.0.1-SNAPSHOT.jar</jar-file>
<properties>
<property name="eclipselink.composite-unit" value="true" />
</properties>
</persistence-unit>
My member persistence.xml, located on sample-common-0.0.1-SNAPSHOT.jar:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="memberPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.commons.entity.AbstractEntity</class>
<class>com.example.common.entity.ThirdParty</class>
<class>com.example.common.entity.Address</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/H2default" />
<property name="javax.persistence.jdbc.user" value="sa" />
<property name="javax.persistence.jdbc.password" value="" />
<!-- <property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.H2Platform"
/>
-->
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />
<property name="eclipselink.logging.level" value="FINEST" />
</properties>
</persistence-unit>
My entities, also on sample-common-0.0.1-SNAPSHOT.jar:
ThirdParty:
package com.example.common.entity;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.Generated;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import com.example.common.Gender;
import com.commons.entity.AbstractEntity;
/**
* ThirdParty entity.
*/
@Entity
public class ThirdParty
extends AbstractEntity
{
/**
* Constructor.
*/
public ThirdParty()
{
super();
}
/**
* Serial version UID.
*/
private static final long serialVersionUID = 1L;
/**
* firstname.
*/
@Column(name = "FIRST_NAME", nullable = false)
@NotNull
private String firstName;
/**
* last name.
*/
@Column(name = "LAST_NAME", nullable = false)
@NotNull
@Size(max = 30)
private String lastName;
/**
* Birth date.
*/
@Column(name = "BIRTH_DATE", nullable = false)
@NotNull
@Temporal(TemporalType.TIMESTAMP)
private Date birthdate;
/**
* last name.
*/
@Column(name = "AGE", nullable = false, precision = 0)
@NotNull
private Integer age;
/**
* ThirdParty civility.
*/
@Column(name = "CIVILITY", nullable = false)
@NotNull
@Enumerated(EnumType.STRING)
private Gender civility;
/**
* addressList.
*/
@OneToMany(mappedBy = "thirdParty", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private List<Address> addressList = new ArrayList<Address>();
/**
* Get firstName.
* @return String
*/
public String getFirstName()
{
return firstName;
}
/**
* Set firstName.
* @param firstName String
*/
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
/**
* Get lastName.
* @return String
*/
public String getLastName()
{
return lastName;
}
/**
* Set lastName.
* @param lastName String
*/
public void setLastName(String lastName)
{
this.lastName = lastName;
}
/**
* Get birthdate.
* @return Date
*/
public Date getBirthdate()
{
Date tempDate = birthdate;
if (tempDate != null)
{
tempDate = (Date) birthdate.clone();
}
return tempDate;
}
/**
* Set birthdate.
* @param birthdate Date
*/
public void setBirthdate(Date birthdate)
{
if (birthdate == null)
{
this.birthdate = null;
}
else
{
this.birthdate = (Date) birthdate.clone();
}
}
/**
* Get age.
* @return Integer
*/
public Integer getAge()
{
return age;
}
/**
* Set age.
* @param age Integer
*/
public void setAge(Integer age)
{
this.age = age;
}
/**
* Get civility.
* @return Gender
*/
public Gender getCivility()
{
return civility;
}
/**
* Set civility.
* @param civility Gender
*/
public void setCivility(Gender civility)
{
this.civility = civility;
}
/**
* Get addressList.
* @return Address
*/
public List<Address> getAddressList()
{
return addressList;
}
/**
* Set addressList.
* @param addressList Address
*/
public void setAddressList(List<Address> addressList)
{
this.addressList = addressList;
}
/**
* Add addressList.
* @param addressList Address
*/
public void addAddressList(Address addressList)
{
this.addressList.add(addressList);
}
}
Address entity:
package com.example.common.entity;
import javax.annotation.Generated;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.commons.entity.AbstractEntity;
/**
* Address entity.
*/
@Entity
public class Address
extends AbstractEntity
{
/**
* Serial version UID.
*/
private static final long serialVersionUID = 1L;
/**
* street.
*/
@Column(name = "STREET")
private String street;
/**
* City.
*/
@Column(name = "CITY")
private String city;
/**
* Zipcode.
*/
@Column(name = "ZIPCODE", precision = 0)
private Integer zipcode;
/**
* Third Party.
*/
@ManyToOne
private ThirdParty thirdParty;
/**
* Get street.
* @return String
*/
public String getStreet()
{
return street;
}
/**
* Set street.
* @param street String
*/
public void setStreet(String street)
{
this.street = street;
}
/**
* Get city.
* @return String
*/
public String getCity()
{
return city;
}
/**
* Set city.
* @param city String
*/
public void setCity(String city)
{
this.city = city;
}
/**
* Get zipcode.
* @return Integer
*/
public Integer getZipcode()
{
return zipcode;
}
/**
* Set zipcode.
* @param zipcode Integer
*/
public void setZipcode(Integer zipcode)
{
this.zipcode = zipcode;
}
/**
* Get thirdParty.
* @return ThirdParty
*/
public ThirdParty getThirdParty()
{
return thirdParty;
}
/**
* Set thirdParty.
* @param ThirdParty
*/
public void setThirdParty(ThirdParty thirdParty)
{
this.thirdParty = thirdParty;
}
}
And finally the JUnit test class:
package com.example.data.dao;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.sopra.banking.example.common.Gender;
import com.sopra.banking.example.common.entity.Address;
import com.sopra.banking.example.common.entity.ThirdParty;
import junit.framework.Assert;
public class ClientTest
{
private static EntityManagerFactory emf;
private static EntityManager em;
private static EntityTransaction tx;
@BeforeClass
public static void initEntityManager()
throws Exception
{
emf = Persistence.createEntityManagerFactory("testPersistenceUnit");
em = emf.createEntityManager();
}
@AfterClass
public static void closeEntityManager()
throws SQLException
{
em.close();
emf.close();
}
@Before
public void initTransaction()
{
tx = em.getTransaction();
}
@Test
public void testInsert()
throws ParseException
{
// Create an instance of ThirdParty
ThirdParty thirdParty = new ThirdParty();
// Create an instance of Address
Address address = new Address();
// set address
address.setCity("Annecy");
address.setStreet("street");
address.setZipcode(74000);
ArrayList<Address> addresses = new ArrayList<Address>();
addresses.add(address);
// set client
thirdParty.setCivility(Gender.MISTER);
thirdParty.setAge(17);
thirdParty.setBirthdate(new SimpleDateFormat("yyyy-MM-dd").parse("2011-01-01"));
thirdParty.setFirstName("firstName");
thirdParty.setLastName("lastName");
thirdParty.setAddressList(addresses);
address.setThirdParty(thirdParty);
// Persists the client in DB
tx.begin();
em.persist(thirdParty);
tx.commit();
Assert.assertNotNull("ID should not be null", thirdParty.getId());
}
@Test
public void testSelectById()
throws ParseException
{
ThirdParty thirdParty = em.find(ThirdParty.class, 1);
Assert.assertEquals(true, true);
}
@Test
public void testSelectAll()
throws ParseException
{
Query query = em.createQuery("SELECT t FROM ThirdParty t");
List<ThirdParty> thirdParties = query.getResultList();
Assert.assertEquals(true, true);
}
@Test
public void testSelectByCriteria()
{
CriteriaBuilder qb = em.getCriteriaBuilder();
CriteriaQuery<ThirdParty> criteriaQuery = qb.createQuery(ThirdParty.class);
Root<ThirdParty> thRoot = criteriaQuery.from(ThirdParty.class);
criteriaQuery.select(thRoot);
List<ThirdParty> thirdPartyList = em.createQuery(criteriaQuery).getResultList();
Assert.assertEquals(true, true);
}
}
testInsert, testSelectAll and testSelectById work well but testSelectByCriteria crashes with the error trace on the beginning of my post.
During debug i notice that typeMap is empty on class:
org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl on method entityEmbeddableManagedTypeNotFound
private void entityEmbeddableManagedTypeNotFound(Map typeMap, Object aType, Class clazz, String metamodelType, String metamodelTypeName) {
// 338837: verify that the collection is not empty - this would mean entities did not make it into the search path
if(typeMap.isEmpty()) {
AbstractSessionLog.getLog().log(SessionLog.WARNING, SessionLog.METAMODEL, "metamodel_type_collection_empty_during_lookup", clazz, metamodelTypeName);
}
// A null type will mean either the metamodel type does not exist because it was not found/processed, or the clazz is not part of the model
if(null == clazz) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
"metamodel_class_null_type_instance_for_null_key",
new Object[] { metamodelTypeName, metamodelType}));
} else {
if(null == aType) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
"metamodel_class_null_type_instance",
new Object[] { clazz.getCanonicalName(), metamodelTypeName, metamodelType}));
} else {
Has anyone ever encountered this problem, it seems managed entites are not visible because the map
Map<String, EntityTypeImpl<?>> entities
is empty.
I try to generate metamodel classes following this procedure jpa-metamodels-with-maven but call using Criteria still failing.