在Resin3下配置SpringSide的HelloWorld示例程序碰到的问题和解决方法

       因为想体验一把Spring2.0基于aop名称空间的AOP和Hibernate3.2比EJB3.0的JPA还要细致强大的annotation等等新特征,特地跑到 SpringSide(一个基于Spring核心的强大而优雅的企业快速开发框架)去下载了完整的开发包。记得要先照它介绍的方式运行起来,只要双击个.bat文件程序,数据库( HSQLDB),服务器( Tomcat5.5)就全部署好了,范例就已经跑起来了,非常吸引人。但是我一般用的是 Resin3  ,所以我打算停了Tomcat跑起我的Resin,这时候一向听话的Resin居然开始撒娇了。

      配好路径启动Resin,调试信息如下:
 1 Resin-3.0.19 (built Mon, 15 May 2006 04:50:47 PDT)
 2 Copyright(c) 1998-2006 Caucho Technology.  All rights reserved.
 3
 4   Using Resin(R) Open Source under the GNU Public License (GPL).
 5
 6   See http://www.caucho.com for information on Resin Professional,
 7   including caching, clustering, JNI acceleration, and OpenSSL integration.
 8
 9 Starting Resin on Wed, 24 Jan 2007 21:25:59 +0800 (CST)
10
11 [21:26:02.375] Server[] starting
12 [21:26:02.375] 
13 [21:26:02.375] Windows XP 5.1 x86
14 [21:26:02.375] Java 1.5.0_10-b03, 32, mixed mode, GBK, zh, Sun Microsystems Inc.
15 [21:26:02.375] resin.home = D:\resin-3.0.19
16 [21:26:02.375] server.root = null
17 [21:26:02.375] 
18 [21:26:02.484] http listening to *:8080
19 [21:26:02.546] hmux listening to localhost:6802
20 [21:26:02.765] Host[] starting
21 [21:26:03.890] com.caucho.config.LineConfigException: WEB-INF/web.xml:4: bad character fffd
22 [21:26:04.781] WebApp[http://localhost:8080/resin-doc] starting
23 [21:26:04.953] Resin started in 3000ms


      注意红色的信息,读取web.xml异常了,我四级都没过的英语也看出来了是字符错误,相信大家也看出来了吧。凭着经验判定是文件编码的问题,用eclipse打开web.xml果然中文部分有乱码。一向都觉得Resin在编码的处理上,特别是中文编码上比Tomcat5要好很多。今天怎么会出现这种奇怪的问题,带着疑问继续往下看吧。我当时想还是先跑起来再说,老老实实的把编码都转一下吧。

      告诉大家一个转文件编码最简单的办法,就是把文件用windows自带的记事本程序打开,选择菜单“文件”-“另存为”,然后在另存为的界面把文件类型选择为“所有文件”,编码选择为“UTF-8”,选择目标文件覆盖保存。

      转了编码后发现注释中有两个显示不了的字符,反正是注释索性就删掉了。修改后再次启动Resin,果然正常了。但是又出现了更郁闷的问题。部分调试信息如下:

 1 2007-01-24 22:44:02,125 ERROR [org.springframework.web.context.ContextLoader] -  < Context  initialization failed >
 2 org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from file [D:\projects\SSHelloWorld\webapp\WEB-INF\classes\spring\applicationContext.xml]; nested exception is java.lang.IllegalArgumentException: Bean name must not be empty
 3 Caused by: 
 4 java.lang.IllegalArgumentException: Bean name must not be empty
 5     at org.springframework.util.Assert.hasText(Assert.java:161)
 6     at org.springframework.beans.factory.config.RuntimeBeanReference. < init > (RuntimeBeanReference.java:58)
 7     at org.springframework.beans.factory.config.RuntimeBeanReference. < init > (RuntimeBeanReference.java:46)
 8     at org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser.parseInternal(AnnotationDrivenBeanDefinitionParser.java:76)
 9     at org.springframework.beans.factory.xml.AbstractBeanDefinitionParser.parse(AbstractBeanDefinitionParser.java:56)
10     at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:78)
11     at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1147)
12     at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1137)
13     at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:145)
14     at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:89)
15     at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:499)
16     at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:407)
17     at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:357)
18     at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
19     at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:126)
20     at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:142)
21     at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:123)
22     at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:91)
23     at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:94)
24     at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:294)
25     at org.springframework.web.context.support.AbstractRefreshableWebApplicationContext.refresh(AbstractRefreshableWebApplicationContext.java:156)
26     at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:246)
27     at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:184)
28     at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:49)
29     at com.caucho.server.webapp.Application.start(Application.java:1597)
30     at com.caucho.server.deploy.DeployController.startImpl(DeployController.java:621)
31     at com.caucho.server.deploy.StartAutoRedeployAutoStrategy.startOnInit(StartAutoRedeployAutoStrategy.java:72)
32     at com.caucho.server.deploy.DeployController.startOnInit(DeployController.java:509)
33     at com.caucho.server.deploy.DeployContainer.start(DeployContainer.java:158)
34     at com.caucho.server.webapp.ApplicationContainer.start(ApplicationContainer.java:652)
35     at com.caucho.server.host.Host.start(Host.java:385)
36     at com.caucho.server.deploy.DeployController.startImpl(DeployController.java:621)
37     at com.caucho.server.deploy.StartAutoRedeployAutoStrategy.startOnInit(StartAutoRedeployAutoStrategy.java:72)
38     at com.caucho.server.deploy.DeployController.startOnInit(DeployController.java:509)
39     at com.caucho.server.deploy.DeployContainer.start(DeployContainer.java:158)
40     at com.caucho.server.host.HostContainer.start(HostContainer.java:501)
41     at com.caucho.server.resin.ServletServer.start(ServletServer.java:977)
42     at com.caucho.server.deploy.DeployController.startImpl(DeployController.java:621)
43     at com.caucho.server.deploy.AbstractDeployControllerStrategy.start(AbstractDeployControllerStrategy.java:56)
44     at com.caucho.server.deploy.DeployController.start(DeployController.java:517)
45     at com.caucho.server.resin.ResinServer.start(ResinServer.java:485)
46     at com.caucho.server.resin.Resin.init(Resin.java)
47     at com.caucho.server.resin.Resin.main(Resin.java:624)


      一看错误是Bean name must not be empty,bean的名字不能为空?为什么啊,没听说过啊,不管是Spring的官方文档,范例还是看的书上教授的都没有听说这么一回事情啊。没天理啊,运行个HelloWorld也这么费力。。。马上抱起错误就去找Google,居然搜不到。。。(正因为GOOGLE搜索不到相关的解决,所以我特地写了这篇文章与大家分享)不会吧,难道大家都没碰到过,我的人品问题?Google也没办法找到的问题,我只好翻找Spring的源代码。查看org.springframework.util.Assert.hasText类,原来抛出java.lang.IllegalArgumentException异常不是按字面意思理解的bean名字不能为空,先汗自己!不过在这个类里面也没找到具体的原因。难道还要继续往前翻找源代码?虽然看大师们的作品是种享受,但是注定我运行HelloWorld就搞成这样?并且查源代码也不是一时能找的出问题的。

      停止服务,启动服务,停止服务,启动服务。。。反复的反复,问题依然。换回Tomcat去,一切正常。。。彻底崩溃,难道resin上跑不起Spring?Spring容器可是JAVA原生的动态代理方式实现,完全应该具备JAVA的“一次编写到处运行”。我看到的文档和书籍也无一不盛赞它的Web服务器,应用服务器无关。我想一定是哪里配置有问题,我又把每个xml配置文件都翻了个遍,依然找不出问题。

      我突然想起曾经看过的一篇关于JAVA XML的文章,好像JAVA默认的XML解析用的是Crimson,不如另一个XML解析实现Xerces ,莫非是Resin用的解析不行?抱着死马当活马医的态度配上了xerces。

      配置xerces方法如下:
      1.在VM级
      首先在CLASSPATH下放置xerces相关的包,然后在JRE\lib\目录下建一个jaxp.properties的文件,用来声名替换解析器,jaxp.properties内容如下:
 

1 javax.xml.parsers.DocumentBuilderFactory = org.apache.xerces.jaxp.DocumentBuilderFactoryImpl 
2 javax.xml.parsers.SAXParserFactory = org.apache.xerces.jaxp.SAXParserFactoryImpl


注意:必须建立此文件显示声明,如果只是引入了xerces的相关包,由于JDK的Class Loader的优先级关系,还是会很顽固的使用Crimson。

      2.在web服务器级(Resin3.0.19为例)
      把xerces相关包放入容器的CLASSPATH中(Resin主目录下的lib目录),然后在配置文件resin.conf(Resin主目录下的conf目录中resin.conf文件)中的server节点中加入如下XML代码:

1 < system-property  javax.xml.parsers.DocumentBuilderFactory ="org.apache.xerces.jaxp.DocumentBuilderFactoryImpl" />
2   < system-property  javax.xml.parsers.SAXParserFactory ="org.apache.xerces.jaxp.SAXParserFactoryImpl" />



       声明调用xerces实现XML解析。

       JAVA XML相关内容推荐参阅:
   http://www-900.ibm.com/developerWorks/cn/xml/x-injava/index.shtml

   http://www-900.ibm.com/developerWorks/cn/xml/x-injava2/index.shtml

   http://www-900.ibm.com/developerWorks/cn/xml/x-databdopt/part2/index.shtml

   http://www-900.ibm.com/developerWorks/cn/xml/x-databdopt/part1/index.shtml


      我在Resin中配置好xerces后,启动。WebApplicationContext初始化正常,Struts初始化正常,一切正常,终于看到了界面。

      然后我又想刚才web.xml中的错误会不会也是因为没有用xerces的原因,把原来没修改的web.xml又拷了一个过来,启动依然报同样的错,仔细再看文件里面确实在最开始的注释中有两个错误的字符,不知道SpringSide的大侠们是故意的还是不小心弄错了。。。删除错误字符启动,成功!

      总结如下:
      1. web.xml中是以为确实存在错误的字符导致web容器无法初始化,修改文件后就正常了。
      2. Resin读取Spring的配置文件必须显示采用xerces,否则无法初始化Spring容器。建议配置服务器级的xerces。
      3. 平时开发和学习过程中应广泛涉猎,拓宽知识面。碰到问题大胆假设,联想,细心调试。最后再纠根问底,彻查明白。
      4. 遇到问题不轻易放弃,多思考,多总结,多记录。

 

施伟 2007-01-25 00:29 发表评论

你可能感兴趣的:(java,spring,xml,bean,Web)