近日做了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.anti-gravitydesign.com