日期:2014-05-16  浏览次数:20466 次

maven provided scope 及jsp的编绎问题记录

今天处理了一个很恶心的问题 ,具体现象是做健康检查的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后,世界一下子清净了。


我的异常网推荐解决方案:org.apache.jasper.JasperException: Unable to compile class,http://www.aiyiweb.com/j2ee/2308.html