I have a very curious problem when I deploy my Java EE application to Glassfish. I have an Eclipse EAR project that references a web project (containing a servlet), and an EJB project (that has one EJB) and a JPA Project (that has one @Entity). In my servlet I call the EJB, which in turn performs the following query:
final CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
final CriteriaQuery<Country> criteriaQuery = criteriaBuilder.createQuery(Country.class);
final Root<Country> root = criteriaQuery.from(Country.class);
On the third line of the above code I get an exception:
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 debugged the above mentioned Hibernate class, namely MetamodelImpl, and I see that it has registered my Entity (in the entities Map). The class name is exactly the same as the one I'm asking for (net...Country). However, this class is different from the following code which I place in the servlet:
final Class<?> countryClass = Country.class;
I say it is "different", because the 'declaredConstructors' field and the 'declaredPublicMethods' are different. In the servlet these fields are 'null' (strange, see Country.java below!), but in the MetamodelImpl class these fields contain the constructors and public methods that I have defined in the entity. Because MetamodelImpl uses a Map, it cannot find the entity amongst the registered classes because the "class" is different (i.e. stored at a different location in memory), and of course it throws the IllegalArgumentException. I have checked that what is deployed to Glassfish only ever contains one Country.class file, so this is really confusing why there are two different Class instances of the same class, and that they are different from each other!
Anyone have any idea?
For reference: Hibernate v4.3.6, EJB v3.2, Glassfish v4.1, JPA v2.1.
My Country.java entity is below. As you can see, it contains a constructor and public methods, so it astonishes me that in the servlet the class does NOT have 'declaredConstructors' or 'declaredPublicMethods'. How can this be?
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
@Entity
public class Country implements Serializable {
private static final long serialVersionUID = -3119088680575312729L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Pattern(regexp = ".[\\p{L} \\.\\[\\]\\?\\-\\(\\)]{1,30}+")
@NotNull
private String name;
public Country() {
super();
}
public String getName() {
return this.name;
}
public void setName(final String name) {
this.name = name;
}
public Integer getId() {
return this.id;
}
public void setId(final Integer id) {
this.id = id;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append(this.name);
builder.append(" (");
builder.append(this.id);
builder.append(")");
return builder.toString();
}
}