28 October 2011

org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken

In Oracle Weblogic Server - Version: 9.2 to 10.3.6 when shutting down managed server(s) the following error may occurs:

CharScanner; panic: ClassNotFoundException: org.hibernate.hql.ast.HqlToken

or when trying to run an application using HQL with antlr as parser, the following stacktrace may appear:

org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken [ from org.example.hibernate.Customer]
at org.hibernate.hql.ast.HqlLexer.panic(HqlLexer.java:57)
at antlr.CharScanner.setTokenObjectClass(CharScanner.java:340)
at org.hibernate.hql.ast.HqlLexer.setTokenObjectClass(HqlLexer.java:31)
at antlr.CharScanner.(CharScanner.java:51)
at antlr.CharScanner.(CharScanner.java:60)
at org.hibernate.hql.antlr.HqlBaseLexer.(HqlBaseLexer.java:56)
at org.hibernate.hql.antlr.HqlBaseLexer.(HqlBaseLexer.java:53)
at org.hibernate.hql.antlr.HqlBaseLexer.(HqlBaseLexer.java:50)
at org.hibernate.hql.ast.HqlLexer.(HqlLexer.java:26)
at org.hibernate.hql.ast.HqlParser.getInstance(HqlParser.java:44)
at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:242)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:157)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:112)
at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:77)
at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:57)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:112)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1627)
at org.example.hibernate.HQLSample.selectCustomer(HQLSample.java:41)
at Test.doGet(Test.java:38)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:821)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:300)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:184)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3717)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3681)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2277)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2183)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1454)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:178)

Cause
Classloading issues with antlr library bundled with WebLogic Server that is not compatible with Hibernate 3.

Solution
It is necessary to use antlr 2.7.6 (this version works, however more details of which version should be check with Hibernate as being a third party tool).

There are 4 possible workarounds for this classloading issue:

1. Package antlr.jar into WEB-INF/lib and add the following tag to weblogic.xml
    (this works for war alone or packaged into an ear).
<container-descriptor>
    <prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>

2. If it is an ear file then put antlr.jar at APP-INF/lib (or at web application level: WEB-INF/lib) and modify weblogic-application.xml adding the following tag:
<prefer-application-packages>
    <package-name>antlr.*</package-name>
</prefer-application-packages>

3. Change property hibernate.query.factory_class from hibernate configuration file (hibernate.cfg.xml).
    (if hibernate.query.factory_class doesn't exist then this value is assigned by default):
<property name="hibernate.query.factory_class"
 value="org.hibernate.hql.ast.ASTQueryTranslatorFactory">
</property>

to a different parser (classic):

<property name="hibernate.query.factory_class" 
value="org.hibernate.hql.classic.ClassicQueryTranslatorFactory">
</property>

4. Set at server classpath level antlr library before WLS classpath.
    (warning: this is the less recommended option because it impacts the whole WLS and may affect another modules).

    In setDomainEnv.cmd (or any of the start-up scripts) set the next value at the end of the file, referring to antlr library's location:

set CLASSPATH=C:\jars\antlr-2.7.6.jar;%CLASSPATH%

References
http://download.oracle.com/docs/cd/E21764_01/web.1111/e13706/classloading.htm
http://community.jboss.org/wiki/HibernateCoreMigrationGuide30#weblogic

1 comment :

indigo said...

Excellent summary of the problem and its solutions!

Blog Archive

Disclaimer

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.