users@glassfish.java.net

Cannot have a jpa persistent object query inside a static init block

From: <glassfish_at_javadesktop.org>
Date: Sat, 12 Jan 2008 22:22:45 PST

I encountered a problem with the jpa in Glassfish that was very difficult to solve. I may some changes in (what I thought was) a completely separate area and received this stack trace:

32 [httpWorkerThread-4848-0] ERROR User - User not found.
javax.persistence.PersistenceException: Exception [TOPLINK-28019] (Oracle TopLink Essentials - 2.0 (Build b58g-fcs (09/07/2007))): oracle.toplink.essentials.exceptions.EntityManagerSetupException
Exception Description: deploy for PersistenceUnit [Spellscape] failed. Close all factories for this PersistenceUnit.
Internal Exception: java.lang.NullPointerException
        at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:216)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:93)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:126)
        at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:99)
        at com.sun.enterprise.util.EntityManagerWrapper._getDelegate(EntityManagerWrapper.java:346)
        at com.sun.enterprise.util.EntityManagerWrapper.createQuery(EntityManagerWrapper.java:660)
        at com.spellscape.main.RegisteredUser.get(RegisteredUser.java:51)
        at com.spellscape.main.Spellscape.init(Spellscape.java:32)
        [...]

From the stack trace I assumed that there was some problem with the User table in the database, however that was not the case. I found no help using Google to search for the key parts of the stack trace.

I undid my previous changes and slowly went forward until I found what triggered the error. I found that the problem appears and disappears with the removal of the @Entity annotation from an unrelated class (Impact.java). As apart of my debugging I deleted the database table for that class and re-started the server. (Note that I restarted the server and I didn't re-run the program. Had I re-ran the program the databases would have been created and I would not have see the below (helpful) stack trace).

Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0 (Build b58g-fcs (09/07/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: Table/View 'ABILITY' does not exist.
Error Code: -1
Call: SELECT NAME, DTYPE FROM ABILITY WHERE (NAME = CAST (? AS VARCHAR(32672) ))
        bind => [com.spellscape.ability.Impact]
Query: ReportQuery(com.spellscape.ability.Ability)
        at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:319)
[...]
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:508)
        at com.sun.enterprise.util.QueryWrapper.getSingleResult(QueryWrapper.java:212)
        at com.spellscape.ability.Ability.getInstance(Ability.java:27)
        at com.spellscape.ability.Impact.<clinit>(Impact.java:12)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:247)
        at oracle.toplink.essentials.internal.security.PrivilegedAccessHelper.getClassForName(PrivilegedAccessHelper.java:112)
[...]
        at com.sun.enterprise.util.EntityManagerWrapper.createQuery(EntityManagerWrapper.java:660)
        at com.spellscape.main.RegisteredUser.get(RegisteredUser.java:51)
        at com.spellscape.main.Spellscape.init(Spellscape.java:30)

This stack trace shows that some class loading is occurring during what appears to be some entity management initialisation routines. So apparently the first time that an object entity query is executed there is an initialisation period where all entity classes are loaded. When a class is loaded its static block is executed. In one of my classes there was a static initialisation block and inside that block was an object entity query. This query was then executed while the entity management was part way through its initialisation and caused a problem.

Therefore it appears that I cannot have an entity class that has a static block that performs a database request. (Or more accurately I can't have more than one class which does this.)

This problem was very difficult to solve and better error reporting in Glassfish is needed.

Q. Is this another compromise that one must make to use jpa or is it a bug in Glassfish?
[Message sent by forum member 'dannycron' (dannycron)]

http://forums.java.net/jive/thread.jspa?messageID=253578