1

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.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Raoul
  • 133
  • 3
  • 15
  • If I inject an EntityManagerFactory via the PersistenceUnit(unit-name="") annotation I get a Hibernate implementation, but this implementation doesn't seem to know about my Country entity. How can there be two Hibernate implementations, one which DOES know the entity, and one which DOESN'T know the entity??? Presumably the PersistenceContext annotation gets you the persistence implementation of Glassfish, whereas using PersistenceUnit you get your own application's persistence implementation, or at least I think I read that somewhere... – Raoul Oct 06 '14 at 14:57
  • With any EntityManager, injected or not, this DOES work. So it looks like injection is working, and the object is recognized and available to Hibernate. But for the injected EntityManagers it doesn't seem to be available using the class name, or at least that's what it now looks like... final Query query = this.entityManager.createQuery("SELECT c FROM Country c"); final List resultList = query.getResultList(); – Raoul Oct 06 '14 at 16:34
  • Problem continued here: [link](http://stackoverflow.com/questions/26238508/jpa-entity-class-instances) – Raoul Oct 08 '14 at 14:08

1 Answers1

0

OK, so it looks like the problem has to do with the fact that I somehow have two instances of the Entity class. This explains why I can query using query language, but not using the Entity class itself. I've traced the code to MetamodelImpl that looks in a map of entities, but because the class it has registered (correctly) is not the same as the one used in criteriaQuery.from(). I've searched for multiple instances of the class in the folder where the Java EE application is deployed, but I haven't found multiple instances of the class itself. So possibly it has to do with classloading and/or the fact that the application contains multiple sub-projects (jpa, web, ejb) each referencing the Entity class, or perhaps due to Eclipse either in how it deploys or how it builds the separate parts...

In any case, the problem doesn't seem one of JPA, Hibernate, EJB, etc.

Raoul
  • 133
  • 3
  • 15