这二天在对以前一个老的应用程序在向WAS7应用迁移调整过程中碰到了一些不常见的错误,在排错过程中尝试去寻找相似问题的解决方案却每次都无功而返,为了防止以后这类错误再次困扰大家特将排查过程与大家共同分享,具体内容如下:
(一)应用程序技术架构
首先我们先来看一看此次迁移的应用程序的技术架构总体是由Flex进行应用前端构建,采用J2EE5.0构建服务器端,采用BlazeDS实现前后端的连接,详细的技术组成内容是:
a.前端:Flex3.5+CG3
b.服务端:Spring3.0+Hibernate3+BalzeDS(基于Annotaion方式进行配置)
c.数据库:Oracle10g
d.应用环境为:WAS6.1
(二)迁移改造过程
为了配合业务需要在本次改造过程中主要改造内容是调整部分应用功能点数据源信息,在系统中主要调整了以下内容:
a.在spring中加入了新的数据源datasource,指向了新的数据源信息;
b.为新的数据源配置了HibernateSessionFactory对象,TransactionManager对象;
c.调整了部分应用功能数据层次代码,将相应的取数调整到新的数据源上。
在整个应用程序改造过程中基本是“重扩展轻改造”的原则进行,新的数据源等内容都是基于全新配置文件开展,只是在局部代码处调整了代码,同时在改造过程中采用Tomcat6作为应用测试环境,上述改造结果在Tomcat下一切正常,改造十分顺利。
(三)迁移到WAS7问题大爆发
本机的WAS应用测试环境是WAS7.0+IBM JDK1.6,在WAS上面部署其它测试应用程序一切正常,由此说明WAS7.0测试环境本身参数不存在任何问题。但当将应用程序迁移至WAS7.0后,在应用启动时在SystemOut中总是报如下错误:
[4/13/12 18:56:18:818 CST] 00000021 SystemOut O 2012-04-13 18:56:18,817 [Default : 0] WARN [org.springframework.core.io.support.PathMatchingResourcePatternResolver] - Cannot search for matching files underneath URL [bundleresource://284/com/] because it does not correspond to a directory in the file system
java.io.FileNotFoundException: URL [bundleresource://284/com/] cannot be resolved to absolute file path because it does not reside in the file system: bundleresource://284/com/
at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:204)
at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:51)
at org.springframework.core.io.UrlResource.getFile(UrlResource.java:168)
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.doFindPathMatchingFileResources(PathMatchingResourcePatternResolver.java:529)
at org.springframework.web.context.support.ServletContextResourcePatternResolver.doFindPathMatchingFileResources(ServletContextResourcePatternResolver.java:82)
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.findPathMatchingResources(PathMatchingResourcePatternResolver.java:350)
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.getResources(PathMatchingResourcePatternResolver.java:269)
at org.springframework.context.support.AbstractApplicationContext.getResources(AbstractApplicationContext.java:1156)
at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:204)
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:204)
at org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(ComponentScanBeanDefinitionParser.java:84)
at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:73)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1335)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1325)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:136)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:93)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:493)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:124)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:93)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:458)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:388)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:261)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:192)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
at com.ibm.ws.webcontainer.webapp.WebApp.notifyServletContextCreated(WebApp.java:1588)
at com.ibm.ws.webcontainer.webapp.WebApp.commonInitializationFinish(WebApp.java:350)
at com.ibm.ws.webcontainer.webapp.WebAppImpl.initialize(WebAppImpl.java:292)
at com.ibm.ws.webcontainer.webapp.WebGroupImpl.addWebApplication(WebGroupImpl.java:99)
at com.ibm.ws.webcontainer.VirtualHostImpl.addWebApplication(VirtualHostImpl.java:167)
at com.ibm.ws.webcontainer.WSWebContainer.addWebApp(WSWebContainer.java:722)
at com.ibm.ws.webcontainer.WSWebContainer.addWebApplication(WSWebContainer.java:607)
at com.ibm.ws.webcontainer.component.WebContainerImpl.install(WebContainerImpl.java:376)
at com.ibm.ws.webcontainer.component.WebContainerImpl.start(WebContainerImpl.java:668)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:1162)
at com.ibm.ws.runtime.component.DeployedApplicationImpl.fireDeployedObjectStart(DeployedApplicationImpl.java:1313)
at com.ibm.ws.runtime.component.DeployedModuleImpl.start(DeployedModuleImpl.java:611)
at com.ibm.ws.runtime.component.DeployedApplicationImpl.start(DeployedApplicationImpl.java:938)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.startApplication(ApplicationMgrImpl.java:740)
at com.ibm.ws.runtime.component.ApplicationMgrImpl$1.run(ApplicationMgrImpl.java:1312)
at com.ibm.ws.security.auth.ContextManagerImpl.runAs(ContextManagerImpl.java:4279)
at com.ibm.ws.security.auth.ContextManagerImpl.runAsSystem(ContextManagerImpl.java:4367)
at com.ibm.ws.security.core.SecurityContext.runAsSystem(SecurityContext.java:255)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.startApplicationDynamically(ApplicationMgrImpl.java:1317)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:2089)
at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.start(CompositionUnitMgrImpl.java:437)
at com.ibm.ws.runtime.component.CompositionUnitImpl.start(CompositionUnitImpl.java:122)
at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.start(CompositionUnitMgrImpl.java:380)
at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.startCompositionUnit(CompositionUnitMgrImpl.java:644)
at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.startCompositionUnit(CompositionUnitMgrImpl.java:613)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:45)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:599)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:36)
at sun.reflect.GeneratedMethodAccessor56.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:599)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:243)
at javax.management.modelmbean.RequiredModelMBean.invokeMethod(RequiredModelMBean.java:1085)
at javax.management.modelmbean.RequiredModelMBean.invoke(RequiredModelMBean.java:966)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:848)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:773)
at com.ibm.ws.management.AdminServiceImpl$1.run(AdminServiceImpl.java:1313)
at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)
at com.ibm.ws.management.AdminServiceImpl.invoke(AdminServiceImpl.java:1206)
at com.ibm.ws.management.connector.AdminServiceDelegator.invoke(AdminServiceDelegator.java:181)
at com.ibm.ws.management.connector.ipc.CallRouter.route(CallRouter.java:242)
at com.ibm.ws.management.connector.ipc.IPCConnectorInboundLink.doWork(IPCConnectorInboundLink.java:286)
at com.ibm.ws.management.connector.ipc.IPCConnectorInboundLink$IPCConnectorReadCallback.complete(IPCConnectorInboundLink.java:502)
at com.ibm.ws.ssl.channel.impl.SSLReadServiceContext$SSLReadCompletedCallback.complete(SSLReadServiceContext.java:1772)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:202)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:766)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:896)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1527)
[4/13/12 18:56:48:007 CST] 00000021 SystemOut O 2012-04-13 18:56:48,006 [Default : 0] ERROR [org.springframework.web.context.ContextLoader] - Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: URL [jar:file:/opt/IBM/WebSphere/AppServer/java/jre/lib/ext/ibmpkcs11impl.jar!/com/ibm/crypto/pkcs11impl/provider/Hash.class]; nested exception is java.lang.OutOfMemoryError
at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:237)
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:204)
at org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(ComponentScanBeanDefinitionParser.java:84)
at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:73)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1335)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1325)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:136)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:93)
等异常信息。
(四)问题排差与解决过程
根据上述错误信息显示,首先考虑怀疑是否由WAS对CLASSPATH定义与TOMCAT中存在一定的偏差引起,故将在spring对资源的定位符classpath全部调整为classpath*:/等方式,但改造完后程序旧报错。同时一直受应用在TOMCAT环境下运行正常误导,没有去排查应用程序本身存在错误的可能,而是怀疑在WAS上面部署的应用CLASSPATH需要进行相应的参数配置,于是进行了相应的参数调整,调整后错误依旧出现。经过一翻努力后,决定从错误本身开始入手,通过查阅错误引发的根源,可能肯定是由Spring在进行ApplicationContext构建过程中存在问题,然后进行分析错误的出处,发现是由org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse这个方法中抛出的,通过分析可以断定此类是由在Spring类中如下配置引起:
<context:component-scan base-package="com,san" />(主要是配合Annotation进行包的扫描)
粗一看,上述配置不存在任何问题,且本身应用程序的程序包结构就是如下所示:
但是可以确定错误就是由此处引发了的,故将扫描的base-package调整为只扫描san包,调整结束后启动应用程序一切正常,错误终于被扫除。
(五)分析
通过错误排除分析,在WAS7下面对于base-package的扫描的路径对于通配符的支持力度与TOMCAT别的容器存在一定的区别,需要小心对等,这与其Classpath的环境存在一定的联系。所以在此处建议在进行程序包结构设计是,尽量保持统一的根包结构路径设定,以避免出现不必要的麻烦与错误,这也算是一个最佳实践之一吧!
另外在错误调试过程中还发现Spring2.5版本在was7上部署时,会出现创建bean对象错误的异常,这是由Spring2.5版本的Bug引发,只需更新spring的版本即可。