最近,公司的GlassFish移植項目基本告以段落,由于之前的代碼嚴重依賴于Weblogic,給移植工作帶來了很大的難度,很多實現(xiàn)方式在GlassFish中根本就沒有對應(yīng)的替代品。在經(jīng)歷了幾個月的移植之后,竟讓我對Weblogic開始產(chǎn)生好感了,作為一款商用的Application Server,Weblogic確實非常成熟,非常強大,提供了很多特性,以幫助提高程序的運行效率,但是太笨重了,訪問Admin Console極慢;GlassFish作為一款開源的Application Server,非常適合開發(fā)者使用,速度很快,并且嚴格遵照J2EE的標準,以達到平臺獨立的特性,但是確實簡陋了點,只提供了最標準的實現(xiàn),并且還存在一些明顯的BUG,社區(qū)不夠活躍,文檔、資源都很少,可能是現(xiàn)在SUN處于動亂期,連商業(yè)Support都很難聯(lián)系到。下面是我在做移植工作時,隨筆記下來的一些小經(jīng)驗,讓其他的同學(xué)們少受一些折磨,少踩一些坑。

      1、EJB Clientweblogic.jar沖突

若使用EJB Client訪問GlassFish中的EJB,需將appserv-rt.jarappserv-ext.jarappserv-deployment-client.jarjavaee.jar加入到classpath中。若classpath中存在weblogic.jar,則可能會遇到錯誤:
java.lang.NoSuchMethodError: org.omg.CosTransactions.OTSPolicy.value()S
weblogic.jarclasspath中移除即可。

      2、Transaction使用

使用SpringJtaTransactionManager需要配置兩個屬性:JtaTransactionManager userTransactionName。對于GlassFishJtaTransactionManager java:appserver/TransactionManager userTransactionName java:comp/UserTransaction。只有Bean管理的SessionBeanMDB允許使用UserTransactionEntity Bean只允許使用Container管理的transaction。如果Container管理的SessionBeanMDB使用了UserTransaction,則會出現(xiàn)錯誤:Lookup of java:comp/UserTransaction not allowed for Container managed Transaction beans

      3、HTTP Thread count

使用asadmin修改HTTP thread count后,從Admin Console上訪問,Admin Server的配置可生效,但Cluster不生效,檢查domain.xml已改變,通過asadmin查詢也已生效,應(yīng)該是GlassFish頁面展示的BUG

      4、EJB Timer的使用

GlassFish中使用EJB Timer,需要有一個獨立的XADataSource,和數(shù)據(jù)表EJB__TIMER__TBL,建表語句可在<server_path>/lib/install/databases中找到。對于developer模式,GlassFish默認使用內(nèi)置的__TimerPool,不需要你手工創(chuàng)建datasource和表;對于cluster模式,Admin Server會默認使用__TimerPoolCluster則需要單獨配置。如果讓Admin ServerCluster同時使用手工創(chuàng)建的datasource,則可能導(dǎo)致Cluster配置中的timer datasourceserver重啟后丟失,Timer Service會出現(xiàn)異常,這應(yīng)該是GlassFishBUG,目前的解決方案就是Admin Server用默認的Timer配置,Cluster用另外的配置。

      5、ClassLoader優(yōu)先加載

weblogic中,可以通過配置prefer-application-packages來優(yōu)先加載application中的類,在GlassFish中則沒有對應(yīng)的方式來控制加載順序,一個典型的場景就是:項目中采用CXF作為webservice的實現(xiàn),但GlassFish中默認使用了Metro的實現(xiàn),由于Metrojar包比application加載的早,就會導(dǎo)致CXF依賴的類庫沒有正常加載,而是使用了MetroJAX-WS的實現(xiàn)。

      6、CMP配置中的數(shù)據(jù)庫表名區(qū)分大小寫

CMPGlassFish中需要配置sun-cmp-mappings.xml,該XML中的table-name是區(qū)分大小寫的,Oracle中的表名默認是大寫的,如果這里的table-name寫成小寫,就會報找不到表的錯誤,可以通過添加一個*.dbschema文件,對表名進行適配,以減少切換數(shù)據(jù)庫時的修改操作。

      7、GlassFish的部署結(jié)果不可靠

在使用asadmin部署EAR時,如果沒有遇到極其嚴重的錯誤,部署一般都會返回成功,但這個結(jié)果并不可靠,你需要關(guān)注server.log,如果這里出現(xiàn)了錯誤,應(yīng)用程序則可能沒有真正部署成功,在運行時就會出現(xiàn)錯誤,所以要確保你的程序部署時,server.log中沒有錯誤信息。

       8、TLD路徑

 根據(jù)JSP2.1規(guī)范,tld文件不能存放在/WEB-INF/classes或者/WEB-INF/lib目錄中,特別不能放在/WEB-INF/tags目錄或子目錄中,否則會出現(xiàn)錯誤:
 exception: org.apache.jasper.JasperException: PWC6180: Unable to initialize TldLocationsCache
 root cause: org.apache.jasper.JasperException: PWC6336: Illegal TLD path /WEB-INF/tags/fn.tld, must not start with “/WEB-INF/tags”
 在
TomcatWeblogic中不會出現(xiàn)該問題,GlassFish則嚴格遵照規(guī)范,可將tld文件放置在/WEB-INF/tld目錄。

     9、注冊servlet listener

web.xml中注冊servletlistener時,在<listener>中添加多個<listener-class>不會報錯,但是只有最后一個<listener-class>生效,因此,要注冊多個listener,需要添加多個<listener>

      10、 Pass-by-reference

Weblogic中的call-by-reference能夠極大的提高本地接口調(diào)用的效率,在GlassFish中也有相應(yīng)的替代,就是pass-by-reference,可以在sun-ejb-jar.xml中對某個EJB進行配置,也可以在sun-application.xml中配置,這樣就可以對整個application中的EJB生效。

      11、HTTP錯誤消息體

HTTPErrorCode大于400,并且相應(yīng)的消息體是空時,GlassFish會自動在返回的Response中添加錯誤信息,對于使用HttpClient操作時,就可能和我們期望的Response不同,該問題的解決辦法:在往Response中寫入內(nèi)容后,調(diào)用response.getOutputStream().flush() response.flushBuffer();或者在web.xml中設(shè)置ErrorcCde對應(yīng)的ErrorPageErrorPage可以是一個空內(nèi)容的頁面。

      12、ServletRequestinputStream的使用

InputStream有一個markSupported屬性,如果該屬性為true,則支持markreset,可以多次讀取該流,反之則只能讀取一次該輸入流。一種情形就是:如果在Filter中讀取了該InputStream,則不能在Servlet中再次讀取。ServletRequest中的InputStream在不同的Server中有不同的實現(xiàn),在WeblogicmarkSupported就設(shè)為了true,在GlassFish中則為false