日期:2014-05-16 浏览次数:20496 次
今天处理了一个很恶心的问题 ,具体现象是做健康检查的ok.jsp不能从java编绎成class文件,访问时,不报错,页面一片空白。
最终的原因是对java-j2ee这个jar包依赖的的scope写错了,将provided写成了provide了,导致最终打的WAR包里含有这个java-j2ee.jar。
?
这里记录下导致问题的原因:
1.为什么provided写成了provide,java-j2ee.jar打进了WAR包的lib中:
大概看了一下maven-war-plugin和maven本身的代码,它们是将scope的关键字用字符串的方式来管理的,没有用枚举类。
在打包时,只是判断以下两种情况?"provided".equals(scope) 和"test".equals(scope)不会打到最终的包里去,其它的均作为运行时需要的包。因此,也就解释了java-j2ee.jar出现在WAR包的lib中。
2.为什么ok_servlet.java没有编绎为ok_servlet.class:
日志中打出来的是
?
org.apache.jasper.JasperException: Unable to compile class for JSP: An error occurred at line: 24 in the generated java file The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory Stacktrace: at org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:92) at org.apache.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:330) at org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:415) at org.apache.jasper.compiler.Compiler.compile(Compiler.java:308) at org.apache.jasper.compiler.Compiler.compile(Compiler.java:286) at org.apache.jasper.compiler.Compiler.compile(Compiler.java:273) at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:566) at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:316) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:336) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
?原先思路是,是不是classloader 找到了错误的类,优先加载了webApp下java-j2ee.jar中的JspFactory。但是跟踪jboss启动过程中加载类的日志,jboss_home/server/default/lib下的jsp-api.jar肯定是先加载的,应用的配置也是和jboss的共享classloader。再说运行过程中根本都没有加载webApp下的java-j2ee.jar,也就无所谓classloader加载到错误 的类了,因为classloader加载的是正确的类;
?
后来,又仔细看了一下错误日志:Unable to compile class for JSP,想到可能是使用javac编绎java时,出现的编绎错误。
难道是在JSP编绎时,优先去找webapp中的lib下的jar包,再是其它的?
问了公司一个对容器有很深造诣的同学后,了解到,原来在j2ee规范中,有对容器运行时编绎java文件,查到依赖顺序的说明,webapp下的lib + bootstrap> 运行目录下的lib(如果使用的默认的,那就是jboss_home/server/default/lib) >tmp?
(说明:这个规范要找时间看一下,咳,没文化,真可怕呀)
根据这个规则,webapp下的lib中的java-j2ee.jar中的JspFactory是个低版本的类,如果编绎时,优先找到它,那肯定会报找不到方法的编绎错误了。
?
将provide 改 为provided后,世界一下子清净了。