应用服务器-Jboss To Websphere迁移

发表于:2007-05-25来源:作者:点击数: 标签:服务器-JBoss应用迁移websphere
近日做了jboss 服务器 到websphere服务器的迁移工作,我们刚开始的时候估计太过乐观,认为都是j2ee架构上的应用服务器,应该在1~2天内能够完成这个工作,但实际上,最终我们用了将近2周的时间才完成此工作。迁移过程中遇到了很多典型的问题,所以觉得有必要

近日做了jboss服务器websphere服务器的迁移工作,我们刚开始的时候估计太过乐观,认为都是j2ee架构上的应用服务器,应该在1~2天内能够完成这个工作,但实际上,最终我们用了将近2周的时间才完成此工作。迁移过程中遇到了很多典型的问题,所以觉得有必要总结一下:

 

环境:jboss-tomcat 3.2.6 ,数据库oracle9i ,工作流部分到ejb,struts+hibernate架构,表现层用到jstl ,

 

迁移环境:WSAD 5.1.2 、websphere 5.1(更新到5.1.0.4)

 

整个应用基本上是xxx.war(web应用)+yyy.jar(ejb模块)组成一个ear包

 

 

 

1. oracle的LOB字段类型在websphere上的问题

我们EJB模块中有一个Entity Bean其中有一个字段使用了oracle 的long raw类型(long和row long数据类型在8i以后就不推荐使用了),此字段类型在websphere上不能很好的被支持(5.1以及最新的6.0版本上都存在这个问题),具体表现为:在读取此字段的时候会抛出PMGR6031E: SQLException when trying to get resultSet column x as a byte这样的异常。

 

解决办法是将数据库的long raw转换成blob的字段类型,并且将websphere5.1的版本更新到5.1.0.4(参考资料2)以上,最好不要更新到最新的5.1.1以上的版本,因为我们迁移的过程中发现我们将websphere更新到5.1.1.4的版本时存在一些奇怪的问题,例如中文乱码、数据库写入时报告插入的值长度过大的问题(这些问题在5.1.0.4和5.1.0.5上不存在)。

 

小技巧:在oralce上将long raw的数据类型转换成blob

 

1. 先将要转换的表备份,参照命令:exp用户名/密码@服务名 file=备份文件名 tables=表名

 

2. 将现有的表清空(delete from 表名)

 

3. 用alter将现有的表的long raw类型修改为blob (alter table 表名 modify(列名 blob) )

 

4. 导入数据库数据,在cmd下用imp命令导入先前备份的数据,加上ignore=y 的参数,忽略掉创建表的错误 ,参照命令:imp 用户名/密码@服务名 file=备份文件名 tables=表名 ignore=y

 

小结:在CMP中应该尽量避免使用LOB类型的字段。

 

 

 

2. EJB中SessionBean调用EntityBean出现错误信息为WTRN0062E: 在全局事务中发生非法尝试使用多个仅有一阶段能力的资源 的异常。

解决办法(参考资料3):

 

1. 如果ejb模块中使用的是同一个数据源,那么将它们的jndi的引用用同一种方式,要不全部是直接的jndi引用,或者是java:comp/env/…的引用方式,在 部署描述编辑器中(ejb-jar.xml)- >概述- >WebSphere 绑定- >JNDI - CMP 连接工厂绑定 将容器授权类型换成Per_Connection_Factory。

 

2. 如果你的EJB模块中引用了不同的数据源,而且在某些方法中你许哟阿同时使用到这些不同的数据源的时候,那么上面的方法可能就不适合你了,应该要换成XA data source 的驱动方式。并且代码可能也要做相应的更改。请参考后面的参考资料

 

3. web应用中 jsp 的page contentType的不能重复的问题

在tomcat中,如果a.jsp包含b.jsp,那么a.jsp和b.jsp两个文件上都要加上< %@ page contentType="text/html;charset=GBK" % >,否则jsp页面上会出现中文乱码,然而在websphere上,如果a.jsp和b.jsp上都存在< %@ page contentType="text/html;charset=GBK" % >的话,那么将抛出异常:不能出现多个 contentType', 出现这种情况,

 

 

 

解决方法为:将b.jsp中的< %@ page contentType="text/html;charset=GBK" % >去掉。

 

用以上的方法解决的话,会导致你的web应用程序代码在jboss和websphere不一致, 如果你想保持在jboss和websphere版本上的兼容的话,可以采用如下的方式。在servlet2.4的规范中,利用jsp-config 来制定pageEncoding为gbk(参考资料3),这样的话,在jsp页面中都不需要加上< %@ page contentType="text/html;charset=GBK" % >,在tomcat4.1以上的版本就已经支持servlet2.4了,但是在websphere5.1上只支持j2ee1.3,servlet支持到2.3,不支持2.4,最新的websphere 6支持j2ee1.4(servlet支持到2.4),如果你想在websphere5.1上保持应用程序和jboss上兼容的话,那么你可以在两个种版本中应用不同的web.xml,即在websphere5.1的版本上用servlet2.3的规范、jboss的tomcat中用servlet2.4的规范。

 

新的问题,如果只在websphere5.1上使用的话,a.jsp用静态方式包含b.jsp文件的话,由于只能在a.jsp上用< %@ page contentType="text/html;charset=GBK" % >,b.jsp上不能加上此行语句。如果b.jsp文件也需要单独进行访问的话,那么b.jsp文件将会出现乱码。

 

解决方法:由于b.jsp可以单独访问,所以b.jsp是可以独立a.jsp存在的,那么就不应该用静态包含(< %@include ...)应该将a.jsp换成动态包含b.jsp的方式(< jsp:include.../ >)

 

 

 

4. 标签的问题

1.在webspehre5.1中,不允许在同一个页面中包含相同描述符的标签,比如a.jsp通过< %include..的方式包含了b.jsp文件,并且这两个文件都包含了相同的标签描述的话,例如都包含了< %@ taglib uri="/WEB-INF/tld/c.tld" prefix="c" % >的话。那么websphere将会抛出 org.xml.sax.SAXParseException: 已经为元素“jsp:root”指定了属性“xmlns:c” 异常。

 

但在tomcat上,这种方式是可以的。

 

解决方法是去掉重复的的标签引用。

 

 

 

2.jboss的xml解析器与websphere的xml解析器不同,造成某些taglib使用上出错

 

例如:< c:when >

 

………

 

< /c:when >(有一个空格在其中)

 

这段代码在jboss上是正常的,但在websphere会出现异常,将< /c:when >中的空格去掉,异常排除

 

 

 

5. servlet api实现不一致的问题

由于sun 公司只发布servlet的实现标准,具体的实现由应用服务器去完成,所以在不同应用服务器上的实现标准有所差异。

 

例如request.getRequestURL()方法

 

我们将test.action 通过配置文件映射到test.jsp文件上,test.jsp的内容为:

 

< % request.getRequestURL()% >

 

如果你在浏览器中输入地址http://localhost:8080/test.action,在jboss下返回的值是http://localhost:8080/test.action,而在websphere5.1上将返回的是解析过以后的真是的jsp地址:http://localhost:8080/test.jsp

 

查找servlet的api文档,上面也说得模棱两可,所以应用服务器厂商就按各自不同的理解去实现了。

 

象这种问题只能是更改程序,换其它的方式实现了。

 

6. websphere 应选用良好EAR包结构

Websphere对类库的加载比较严格,在一个应用中最好不要包含不同版本的相同类库包,请检查WEB-INF/lib下的jar包。

 

在websphere上部署应用一定要采用ear的方式发布上去。所以如果在web应用上你的附件管理是用文件的方式来管理的话,那么在程序设计上应该考虑到附件保存地址的可配置性,最好不要放在web容器下面,否则在以后的维护升级上可能会照成一些麻烦,因为web要打包以后才能部署上去,所以你就需要获得客户那边最新的附件信息,然后打包再进行部署。

 

解决方法:

 

1.使用绝对地址(可配置),但这样做仿佛不够优美

 

2.用数据库来保存附件信息,这样改变了原有的程序设计,可能需要修改比较多的程序

 

3.(未测试过)用一个单独的war包来保存这些可变的应用程序数据,这样部署的时候不更新此war包就可以了

 

总结:

 

Websphere基本上是严格的遵守j2ee规范来做的,所以牺牲了部分兼容性,比如websphere的JDK你是不能重新指定的,只能用它自带的版本,并且不同版本的websphere都是基于j2ee版本上的,was5.1只支持到j2ee1.3,was6.0才支持j2ee1.4,如果你要用到j2ee1.4的特性就必须使用was6.0。在部署方面,websphere对程序具有一定的侵入性, wsad需要产生大量的部署代码,例如EJB方面会产生RMIC代码,这些代码是被安排到你程序包下面,我个人觉得。

 

部署期间如果遇到问题,请先到http://www-128.ibm.com/developerworks/cn 网站上查找,大部分问题在这上面都能找到。

 

参考资料:

 

1.将J2EE应用程序移植到WebSphere应用程序服务器

 

http://www-128.ibm.com/developerworks/cn/websphere/library/techarticles/0408_baigang/part1.html

 

http://www-128.ibm.com/developerworks/cn/websphere/library/techarticles/0408_baigang/part2.html

 

http://www-128.ibm.com/developerworks/cn/websphere/library/techarticles/0408_baigang/part3.html

 

2.http://www-1.ibm.com/support/docview.wss?rs=180&uid=swg27004980

 

3.http://www.developer.ibm.com/isv/tech/faq/individual?oid=2:84043

 

4.tomcat include中文问题解决方法

 

http://www.matrix.org.cn/thread.shtml?forum_id=14&view_id=21142

 

5. 使用 WebSphere Studio 将 CMP 实体 Bean 字段映射到 CLOB 列

 

http://www-128.ibm.com/developerworks/cn/websphere/library/techarticles/0405_beaton/0405_beaton.html

原文转自:http://www.ltesting.net