JPA/Hibernate Static Metamodel Attributes not Populated -- NullPointerException

I had the same issue and it was fixed by putting the Model and Model_ class into the same package.


I had a Java EE 6 application using EclipseLink on GlassFish with some @StaticMetamodel classes created and everything was working fine. When I switched to Hibernate 4 on JBoss 7, I started getting these NPEs too. I started investigating and I found this page:

http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/metamodel.html

It quotes the JPA 2 specification, section 6.2.1.1 which defines how the static metamodel classes should be built. For example, I found out by reading the spec that "the option of different packages will be provided in a future release of this specification". I had the metamodel classes in different packages and it worked fine on EclipseLink, but it's an extra feature, as the current standard indicates the following:

  • Metamodel classes should be in the same package as the entity classes they describe;
  • They should have the same name as the entity classes they describe, followed by an underscore (e.g. Product is the entity, Product_ is the metamodel class);
  • If an entity inherits from another entity or from a mapped superclass, its metamodel class should inherit from the metamodel class that describes its immediate superclass (e.g. if SpecialProduct extends Product, which extends PersistentObject, then SpecialProduct_ should extend Product_ which should extend PersistentObject_).

Once I followed all the rules in the spec (the above is just a summary, please refer to section 6.2.1.1 of the spec for the complete version), I stopped getting the exceptions.

By the way, you can download the specification here: http://jcp.org/en/jsr/detail?id=317 (click on "Download page" for the final release, choose to download the specification for evaluation, accept the agreement and download the file "SR-000317 2.0 Specification" - persistence-2_0-final-spec.pdf).


I can't reproduce the issue. I used some of your entities (simplified versions of JPAAlbum, JPATheme and JPATagTheme, without any interfaces), generated the metamodel classes and the following rudimentary test method (running inside a transaction) just passes:

@Test
public void foo() {
    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<JPAAlbum> query = builder.createQuery(JPAAlbum.class);

    Root<JPAAlbum> album = query.from(JPAAlbum.class);

    Assert.assertNotNull(album.get(JPAAlbum_.theme)); // no problem here

    query.where(builder.equal(album.get(JPAAlbum_.theme).get(JPATheme_.id), 1L));

    List<JPAAlbum> results = em.createQuery(query).getResultList();
}

FWIW, here is the generated SQL:

select
    jpaalbum0_.ID as ID32_,
    jpaalbum0_.AlbumDate as AlbumDate32_,
    jpaalbum0_.Description as Descript3_32_,
    jpaalbum0_.Nom as Nom32_,
    jpaalbum0_.Picture as Picture32_,
    jpaalbum0_.Theme as Theme32_ 
from
    Album jpaalbum0_ 
where
    jpaalbum0_.Theme=1

Tested with Hibernate EntityManager 3.5.6-Final, Hibernate JPAModelGen 1.1.0.Final, outside any container.

My suggestion would be to first try to reproduce (if reproducible) the problem in a JUnit test context.

PS: As a side note, I wouldn't store generated classes in the VCS.


Update: Here is a persistence.xml that you can use in a testing context:

<?xml version="1.0" encoding="UTF-8"?>
<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="MyPu" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>

    <class>com.stackoverflow.q3854687.JPAAlbum</class>
    <class>com.stackoverflow.q3854687.JPATheme</class>
    <class>com.stackoverflow.q3854687.JPATagTheme</class>

    <exclude-unlisted-classes>true</exclude-unlisted-classes>

    <properties>
      <!-- Common properties -->
      <property name="javax.persistence.jdbc.driver" value="${jdbc.driver}" />
      <property name="javax.persistence.jdbc.url" value="${jdbc.url}" />
      <property name="javax.persistence.jdbc.user" value="${jdbc.user}" />
      <property name="javax.persistence.jdbc.password" value="${jdbc.password}" />

      <!-- Hibernate specific properties -->
      <property name="hibernate.dialect" value="${jdbc.dialect}" />
      <!--
      <property name="hibernate.show_sql" value="true"/>
      -->
      <property name="hibernate.format_sql" value="true" />
      <property name="hibernate.hbm2ddl.auto" value="update" />   
    </properties>
  </persistence-unit>
</persistence>

I offer an alternative solution if putting the Model and Model_ in the same package does not work. You need to add one init() method to your class that builds the SessionFactory or EntityManager:

public class HibernateSessionFactory {
  private static SessionFactory factory;

  static {
    try {
        factory = new Configuration().configure().buildSessionFactory();
    } catch (Throwable ex) {
        throw new ExceptionInInitializerError(ex);
    }
  }

  public static SessionFactory getFactory() {
    return factory;
  }

  public static void init(){} //does nothing but elimating the NULLPOINTEREXCEPTION
}

So when you run your application from main method or a unit test you need to call HibernateSessionFactory.init(); first. Then the NullPointerException magically disappears and the application works.

This strange behaviour seems to happen when you pass a SingularAttribute around via method parameter.

Credit goes to @Can ÜNSAL who figured it all out in this question: Hibernate/JPA - NullPointerException when accessing SingularAttribute parameter