Analysis and Solution of hibernate and anlr loading conflicts in Weblogic environment, weblogicanlr
The company's application projects often encounter such problems during customer deployment. In order to avoid adding configuration during deployment, it took some time to find the ultimate solution to this problem (solution 2: Modify org. hibernate. hql. ast. hqlLexer source code ). Here, we will record the analysis solution of this problem.
I. Problem description:
1. Exception information:
'Weblogic. kernel. Default (self-tuning) ']… Org. hibernate. QueryException: ClassNotFoundException: org. hibernate. hql. ast. HqlToken [ At org. hibernate. hql. ast. HqlLexer. panic (HqlLexer. java: 57) At anlr. chartlr. setTokenObjectClass (CharScanner. java: 340) At org. hibernate. hql. ast. HqlLexer. setTokenObjectClass (HqlLexer. java: 31) At anlr. chartings. <init> (chartings. java: 51) At anlr. chartings. <init> (chartings. java: 60) At org. hibernate. hql. anlr. HqlBaseLexer. <init> (HqlBaseLexer. java: 56) At org. hibernate. hql. anlr. HqlBaseLexer. <init> (HqlBaseLexer. java: 53) At org. hibernate. hql. anlr. HqlBaseLexer. <init> (HqlBaseLexer. java: 50) At org. hibernate. hql. ast. HqlLexer. <init> (HqlLexer. java: 26) At org. hibernate. hql. ast. HqlParser. getInstance (HqlParser. java: 44) At org. hibernate. hql. ast. QueryTranslatorImpl. parse (QueryTranslatorImpl. java: 242) Atorg. hibernate. hql. ast. QueryTranslatorImpl. doCompile (QueryTranslatorImpl. java: 157) At org. hibernate. hql. ast. QueryTranslatorImpl. compile (QueryTranslatorImpl. java: 111) At org. hibernate. engine. query. HQLQueryPlan. <init> (HQLQueryPlan. java: 77) At org. hibernate. engine. query. HQLQueryPlan. <init> (HQLQueryPlan. java: 56) At org. hibernate. engine. query. QueryPlanCache. getHQLQueryPlan (QueryPlanCache. java: 72) At org. hibernate. impl. SessionFactoryImpl. checkNamedQueries (SessionFactoryImpl. java: 402) At org. hibernate. impl. SessionFactoryImpl. <init> (SessionFactoryImpl. java: 352) At org. hibernate. cfg. Configuration. buildSessionFactory (Configuration. java: 1294) |
2. query the anlr package under the weblogic installation directory:
3. The application references the jars of hibernate3 and antl_2.7.6.
Ii. Cause Analysis
View the source code of hibernate and anlr based on the above exception information:
Code for org. hibernate. hql. ast. HqlLexer:
Public VoidSetTokenObjectClass (String cl ){
Super. SetTokenObjectClass (HqlToken.Class. GetName ());
}
AboveSuperThe. setTokenObjectClass method is defined in the anlr. charclasses class:
Public VoidSetTokenObjectClass (String paramString ){
Try{
This. TokenObjectClass = Utils.LoadClass(ParamString );
}Catch(ClassNotFoundException localClassNotFoundException ){
Panic ("ClassNotFoundException:" + paramString );
}
}
The key part of this method: Utils.LoadClass(ParamString); that is, when hibernate parses hql, it will use this tool to load the org. hibernate. hql. ast. HqlToken class (that is, the setTokenObjectClass method in the HqlLexer class ). What will happen here? Please refer to Utils.LoadClassSource code:
Static{
If("True". Using signorecase (System.GetProperty("Antl_do_not_exit", "false ")))
UseSystemExit=False;
If("True". Using signorecase (System.GetProperty("Antl_use_direct_class_loading", "false ")))
UseDirectClassLoading=True;
}
/** Thanks to Max Anderson at JBOSS and Scott Stanchfield */
Public StaticClass loadClass (String name)ThrowsClassNotFoundException {
Try{
ClassLoader contextClassLoader = Thread.CurrentThread(). GetContextClassLoader ();
If(!UseDirectClassLoading& ContextClassLoader! =Null){
ReturnContextClassLoader. loadClass (name );
}
ReturnClass.ForName(Name );
}
Catch(Exception e ){
ReturnClass.ForName(Name );
}
}
From the above Code, the Class Loader for loading the org. hibernate. hql. ast. HqlToken class is the weblogic startup Class Loader (whether it is Thread.CurrentThread(). GetContextClassLoader () or Class.ForName,WhereClass.ForNameThe Reflection. getCallerClass () Class Loader is used, that is, anlrClass Loader), Not the application class loader. The anlr jar package already exists in the Weblogic class path. The system will give priority to the anlr package in weblogic, but there is no hibnate jar package in the weblogic class path, so the org. hibernate. hql. ast. the HqlToken class throws ClassNotFoundException: org. hibernate. hql. ast. the HqlToken is abnormal.
Iii. Solutions
Solution 1: Modify the anlr loading priority in the weblogic class loader.
This solution is not always effective (especially when multiple projects are deployed in an osgi project or the same weblogic domain). Of course, the success rate is also above 95% Based on the situations encountered by the author. If this solution is ineffective, solution 2 can be used.
Solution 2: Modify the source code of org. hibernate. hql. ast. HqlLexer:
The org. hibernate. hql. ast. HqlToken class is loaded directly using the classload class of hibernate:
Put the original code:
PublicVoidSetTokenObjectClass (String cl ){
Super. SetTokenObjectClass (HqlToken.Class. GetName ());
}
Change to: Assign the hqltoken classThis. tokenObjectClass
Public void setTokenObjectClass (String cl ){
This. tokenObjectClass = HqlToken. class;
}