Duplicate Entity class names causes Exception in Query

#1

I have two Entities which have the same class name but reside in different packages, only one of them is mentioned in the persistence.xml.

I a NamedQuery I use the unqualified class name of one of these entities. If I execute that query I get an exception;

 

Caused by: com.objectdb.o.InternalException: Unexpected internal exception
at com.objectdb.o.JPE.h(JPE.java:163)
at com.objectdb.o.ERR.f(ERR.java:68)
at com.objectdb.o.OBC.onObjectDBError(OBC.java:1456)
at com.objectdb.jpa.JpaQuery.getSingleResult(JpaQuery.java:664)
at objdbTest.Singleton.findItem(Singleton.java:62)
at objdbTest.SLSBObjDb.findItem(SLSBObjDb.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5367)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:801)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:862)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:801)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:371)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5339)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5327)
at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:206)
... 40 more
Caused by: java.lang.NullPointerException
at com.objectdb.o.MST.aY(MST.java:866)
at com.objectdb.o.MST.aX(MST.java:848)
at com.objectdb.o.MST.aW(MST.java:809)
at com.objectdb.o.MST.aU(MST.java:724)
at com.objectdb.o.BQI.Ut(BQI.java:123)
at com.objectdb.o.PRG.ab(PRG.java:601)
at com.objectdb.o.QRM.US(QRM.java:259)
at com.objectdb.o.MST.US(MST.java:888)
at com.objectdb.o.WRA.US(WRA.java:286)
at com.objectdb.o.WSM.US(WSM.java:113)
at com.objectdb.o.QRR.g(QRR.java:225)
at com.objectdb.o.QRR.b(QRR.java:144)
at com.objectdb.jpa.JpaQuery.getSingleResult(JpaQuery.java:657)
... 64 more

Here is the class doing the query on objdbTest.Item

package objdbTest;

import ....

@Entity
@NamedQueries({
@NamedQuery(name = "objdbTest.Singleton.getItem", query = "SELECT o FROM Item o WHERE o.cachedKey = :cachedKey"),
@NamedQuery(name = "objdbTest.Singleton.count", query = "SELECT COUNT(x) FROM Item x")
})
public class Singleton implements Serializable {

public static Singleton getInstance(EntityManager em) {
  Singleton c = em.find(Singleton.class, "1");
  if (c == null) {
   c = new Singleton();
   em.persist(c);
  }
  return c;
}

@Id
protected String id = "1";

@SuppressWarnings("unused")
// used by JPA
@Version
private int version;

@Basic
protected java.lang.Integer lastInstance;


public void generateItems(EntityManager em, int howMany) {
  if (lastInstance == null) {
   lastInstance = 0;
  }
  int endCnt = lastInstance + howMany;
  int startCnt = lastInstance;
  while (endCnt > startCnt) {
   startCnt++;
   Item item = new Item(this, startCnt);
   em.persist(item);
   lastInstance = startCnt;
  }
}

public Item findItem(EntityManager em, int which) {
  TypedQuery<Item> q = em.createNamedQuery("objdbTest.Singleton.getItem", Item.class);
  q.setParameter("cachedKey", Integer.toString(which));
  try {
   return q.getSingleResult();
  } catch (NoResultException e) {
   return null;
  }
 
}

public long howManyItemsExist(EntityManager em) {
  TypedQuery<Long> q = em.createNamedQuery("objdbTest.Singleton.count", Long.class);
  q.setFlushMode(FlushModeType.AUTO);
  try {
   return q.getSingleResult();
  } catch (javax.persistence.NoResultException ex) {
   return -1;
  }
}

private static final long serialVersionUID = 2215109025397291357L;
}

If I change the query to 

@NamedQuery(name = "objdbTest.Singleton.count", query = "SELECT COUNT(x) FROM objdbTest.Item x")

everything works fine.

 

The persistence.xml is 

 

<persistence-unit name="Experiment8objPU" transaction-type="JTA">
     <provider>com.objectdb.jpa.Provider</provider>
     <class>objdbTest.Singleton</class>
  <class>objdbTest.Item</class>
     <properties>
       <property name="javax.persistence.jdbc.url" value="C:/development/ObjectDb/objectdb-2.2.9_04/db/ObjectTestApp.odb"/>
       <property name="javax.persistence.jdbc.user" value="admin"/>
       <property name="javax.persistence.jdbc.password" value="admin"/>
     </properties>
  </persistence-unit>

 

The notes on my previous thread described the attached projects

#2

Every entity class should have its own name - using the same entity name for two different entity classes is not allowed in JPA. See the Entity Class Names section in the manual.

But of course, ObjectDB should not throw a NullPointerException in this case.

I will try to run your test.

ObjectDB Support
#3

Build 2.2.9_05 includes an attempt to fix the NullPointerException.

The fix is based on the stack trace rather than on the test case since running the test project seems complicated and may require installation of software, etc.

ObjectDB Support
#4

I will try it at soon as my box reboots following an (large) upgrade.

The example is not as complex as it looks. If you have an Eclipse EE install ( I have helios ) you only need install the glassfish 3.1 plugin and then load the projects.

I have further problems of this nature. I am trying to load the same classes into 2 different PUs. This works fine with one JPA Provider like Eclipselink, but with ObjectDb as well I am getting the class not found error again ( I have removed the 2nd mode project and duplicate class names ). The error goes away when I use qualified names, but Eclipselink does not like qualified names. If I use the @Entity(name="anothername") syntax Eclipselink works fine with "anothername" but OjectDb does not. Any suggestions? At the momment I am working on generating 2 jars with identical content but renaming the classes are renamed e.g. Point -> ODBPoint and ELPoint

#5

Please try to isolate the problem and provide a console test case, similar as possible to the simple test case in the posting instructions.

ObjectDB Support
#6

I tried it with the latest build and so far it works without having to use qualified entity names.

Sorry, I didn't see that you only want console test apps!

Thanks for your help.

BTW the @Unique annotations for non @id attributes makes our JP QL fly!

#7

Sorry it appears this is an intermittent exception

 

I get the following exception

Caused by: com.objectdb.o._PersistenceException: Type NoIdQueryMapItem is not found
at com.objectdb.o._PersistenceException.b(_PersistenceException.java:45)
at com.objectdb.o.JPE.g(JPE.java:140)
at com.objectdb.o.ERR.f(ERR.java:59)
at com.objectdb.o.OBC.onObjectDBError(OBC.java:1456)
at com.objectdb.jpa.JpaQuery.getSingleResult(JpaQuery.java:664)
at uk.co.his.experiment8.model.noIdQuery.NoIdQuerySingleton.getNumberOfMapItems(NoIdQuerySingleton.java:116)
at uk.co.his.experiment8.ejb.Tests.generateMap(Tests.java:119)
at uk.co.his.experiment8.ejb.Tests.prime(Tests.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5367)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:801)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:862)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:801)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:371)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5339)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5327)
at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:206)
... 40 more
Caused by: com.objectdb.o.TEX: Type NoIdQueryMapItem is not found
at com.objectdb.o.MSG.e(MSG.java:107)
at com.objectdb.o.TRS.g(TRS.java:208)
at com.objectdb.o.SYR.n(SYR.java:239)
at com.objectdb.o.SYR.k(SYR.java:171)
at com.objectdb.o.QRC.<init>(QRC.java:147)
at com.objectdb.o.QRM.US(QRM.java:245)
at com.objectdb.o.MST.US(MST.java:892)
at com.objectdb.o.WRA.US(WRA.java:286)
at com.objectdb.o.WSM.US(WSM.java:113)
at com.objectdb.o.QRR.g(QRR.java:225)
at com.objectdb.o.QRR.b(QRR.java:144)
at com.objectdb.jpa.JpaQuery.getSingleResult(JpaQuery.java:657)
... 65 more

when executing query

@NamedQuery(name = "uk.co.his.experiment8.model.noIdQuery.NoIdQuerySingleton.numberOfMapItems", query = "SELECT COUNT(x) FROM NoIdQueryMapItem x")})

as follows;

 

@Override
public int getNumberOfMapItems(EntityManager em) {
  Query q = em.createNamedQuery("uk.co.his.experiment8.model.noIdQuery.NoIdQuerySingleton.numberOfMapItems");
  //ObjectDb demands we flush transaction to db if we wish to see its results
  q.setFlushMode(FlushModeType.AUTO);
  try {
   long l = (Long) q.getSingleResult();
   if(l > Integer.MAX_VALUE) return -1;
   int i = (int) l;
   return i;
  } catch (javax.persistence.NoResultException ex) {
   return -1;
  }
}

I will attempt to reproduce this in  a console app. 

 

In this particular run no other JPA provider or other PU is being used ... I took that out immediately I started getting them problem... 

There are also NO duplicate class names.

 

 

#8

This is a common exception and a test case would probably not be necessary.

If the database is empty and the type is not specified in the persistence unit - then the type is unknown.

Before running the query - you may introduce the class, using:

    em.getMetamodel().entity(NoIdQueryMapItem.class);

Please use separate forum threads for different problems.

ObjectDB Support
#9

Looking at http://www.objectdb.com/database/forum/174 

I tried adding an explicit inspection of the EntityType using the metamodel

public IMapItem getMapItem(Integer cachedKey, EntityManager em) {
  Metamodel metamodel = em.getMetamodel();
  EntityType<NoIdQueryMapItem> type2 = metamodel.entity(NoIdQueryMapItem.class);
  if(type2 == null) {
   System.err.println("CRASH!");
  }
  else {
   System.err.println("So far NoIdQueryMapItem is there!");
  }
  Query q = em
   .createNamedQuery("uk.co.his.experiment8.model.noIdQuery.NoIdQuerySingleton.uniqueMapItem");
  q.setParameter("cachedKey", cachedKey.toString());//ObjectDb demands we flush transaction to db if we wish to see its results
  q.setFlushMode(FlushModeType.COMMIT);
  //q.setHint(QueryHints.CACHE_USAGE, CacheUsage.CheckCacheThenDatabase);
  /* q.setLockMode(LockModeType.OPTIMISTIC); */
  try {
   java.lang.Object r = q.getSingleResult();
   return (NoIdQueryMapItem) r;
  } catch (javax.persistence.NoResultException ex) {
   return null;
  }
}

Reply