I have a very basic Java EE application defined in Eclipse (one EJB, one web page with PrimeFaces, one JPA entity). It has four projects, one for the EAR, one for the EJB(s), one for JPA and one for web parts. The problem is that I've tried to configure Hibernate as the persistence framework in persistence.xml in the JPA project, and it is not completely working as I would expect. In my EJB (@Stateless) I can retrieve an EntityManager in two ways. I can retrieve it via Persistence.createEntityManagerFactory() ... entityManagerFactory.createEntityManager(), and I can retrieve it via the @PersistenceContext(unitName = "") annotation. However, only with the former does my Entity class (annotated with @Entity) get recognized when I do a query.
This code works, the "Country" entity is known to the (Hibernate) EntityManager that I get given:
final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("<unit-name>");
final EntityManager entityManager = entityManagerFactory.createEntityManager();
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Country> criteriaQuery = criteriaBuilder.createQuery(Country.class);
final Root<Country> root = criteriaQuery.from(Country.class);
but using the annotation in the same class this doesn't work (exception is thrown, see below):
@PersistenceContext(unitName = "<unit-name>")
private EntityManager entityManager;
...
final CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
final CriteriaQuery<Country> criteriaQuery = criteriaBuilder.createQuery(Country.class);
final Root<Country> root = criteriaQuery.from(Country.class);
On the last line an exception is thrown that the "Country" class is not an "Entity". Upon inspecting the injected EntityManager I can see the Country in the session and the persistence context, however, it doesn't seem to know it. Here's the exception that is thrown:
2014-10-06T16:06:29.634+0200|Severe: java.lang.IllegalArgumentException: Not an entity: class <package>.entity.Country
at org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)
at org.hibernate.jpa.criteria.QueryStructure.from(QueryStructure.java:139)
at org.hibernate.jpa.criteria.CriteriaQueryImpl.from(CriteriaQueryImpl.java:173)
at <package>.CountrySessionBean.getCountries(CountrySessionBean.java:35)
...
I have included the Hibernate jars in the EAR file as "bundled libraries", and I have also tried adding them to the "lib" folder of Glassfish. As Hibernate works with the first implementation above I'm assuming it is configured correctly with the correct jars.
My persistence.xml looks like this (and is in the JPA project under META-INF, and in turn part of the EAR):
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="<unit-name>" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>MySQLResource</jta-data-source> <!-- DEFINED IN GLASSFISH -->
<properties>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup" /> <!-- NEEDED? -->
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
...
</properties>
</persistence-unit>
</persistence>
For reference: Hibernate v4.3.6, EJB v3.2, Glassfish v4.1, JPA v2.1.
Could anyone give me a clue what I'm missing? Is some extra configuration needed? How do I tell the application where the Country entity is?
I thought adding @Entity to the entity would have it registered (it does this when I call Persistence.createEntityManagerFactory(...), however, not when the EntityManager or EntityManagerFactory is injected via Java EE/Glassfish. I've also tried adding the class with ... to the persistence.xml to no avail. When I inspect the injected EntityManager I can find the Country class in its persistence context, so it HAS been registered with it, but yet I cannot use the class in a query.