(by huihoo.org 趙晨希,zhaochenxi@vip.sina.com)
1.JBoss簡介
JBoss是一個運行EJB的J2EE應用服務器。它是開放源代碼的項目,遵循最新的J2EE規范。從JBoss項目開始至今,它已經從一個EJB容器發展成為一個基于的J2EE的一個web 操作系統(operating system for web),它體現了J2EE規范中最新的技術,并且它還在the JavaWorld Editors' Choice 2002評選中獲得“最佳Java應用服務器”大獎。無論是學習還是應用,JBoss為我們提供了一個非常優秀的平臺。有關JBoss的詳細信息請參閱其主頁http://www.jboss.org。
剛開始使用JBoss進行EJB開發時,由于可供參考的資源不是很多,所以有一個比較困難的起步階段。JBoss的配置和使用沒有提供圖形向導界面,所以開發部署EJB相對比較復雜。本文通過盡量具體的演示來對JBoss3.0下的EJB開發和部署的進行一個簡單的介紹,從而使剛開始使用JBoss的用戶可以很快地進入到真正的J2EE應用開發中。
由于本文主要介紹JBoss3.0中不同類型EJB的配置和部署,不對基本的EJB開發做太多的描述,所以希望讀者具有J2EE和EJB的經驗。想要了解有關信息請查閱參考資料1。
2.JBoss3.0中基本的ejb配置和部署
根據J2EE規范的要求,一個基本的ejb jar包使用的描述文件是ejb-jar.xml。web應用的war包使用的是web.xml。企業應用的ear包使用的是application.xml。這些配置文件都是中性的和平臺無關的。同時應用服務器可以使用一些其他的配置文件用于描述特定服務器的相關信息。在JBoss中這樣的文件有jboss.xml,jboss-web.xml等。JBoss容器中這些文件不是必須的,如果提供了那么jboss.xml和ejb-jar.xml放在同一目錄下,jboss-web.xml和web.xml放在同一目錄下。關于jboss.xml和jboss-web.xml的規范請參考JBoss安裝目錄下docs/dtd/目錄下的對應的DTD文件。
2.1 JBoss中關于EJB客戶端的配置:
調用EJB的客戶端可以是JSP、Servlet或客戶端應用程序。如果客戶端和服務器不在同一個Java VM上,那么在客戶端必須提供一個jndi.properties文件告訴客戶端進行有關JNDI命名服務的信息,并且把這個文件所在目錄設定到環境變量classpath中。
以下是一個jndi.properties的樣例:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=localhost:1099 (服務器地址和端口號)
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
通過這個文件和JBoss的一些客戶端類庫,就可以使用JBoss提供的EJB對象服務了。
2.2 JBoss中部署EJB:
首先介紹JBoss容器中部署各類EJB對象的兩種方法。下面的演示以Session Bean為例,客戶端是一個本機上的web應用。這里不對演示程序進行具體介紹。
第一種方式:
把開發好的ejb jar包和web應用的war包公共放在deploy目錄下。
演示1:不需要jboss.xml文件和其他任何特殊的設置。
ejb-jar.xml:
<ejb-jar>
······
<ejb-name>ejbtest</ejb-name>
······
</ejb-jar>
客戶端:web應用中對web.xml不需要添加ejb信息,不需要jboss-web.xml文件。引用ejb對象的jsp文件如下:
······
InitialContext ctx = new InitialContext();
Object objref = ctx.lookup("ejbtest"); //使用<ejb-name> beanHome=(zcxejb1Home)PortableRemoteObject.narrow(objref,ejbtestHome.class);
······
演示2:使用jboss.xml文件。
在缺省情況下JBoss的JNDI服務將通過ejb-jar.xml中<ejb-name>XXX</ejb-name>中的XXX來使用EJB的home interface。但是如果有多個ejb對象在相同的ejb jar包中,在ejb-jar.xml中通過<ejb-name>XXX</ejb-name>就可能不能很好的表示某一個ejb對象,所以一般我們希望可以提供一些附加的信息,例如采用這樣的格式"[應用名]/[bean名]"來引用一個EJB對象。這時JNDI服務就可能不能正確地找到你的ejb對象,我們就需要使用jboss.xml文件,通過它實現jndi 名到ejb名的重定向。這個文件必須和ejb-jar.xml一起放到META-INFO目錄下。
ejb-jar.xml:
<ejb-jar>
······
<ejb-name>ejbtest</ejb-name>
······
</ejb-jar>
jboss.xml:
<jboss>
<ejb-name>ejbtest</ejb-name>
<jndi-name>example/ejbtest</jndi-name>
</jboss>
客戶端:需要使用新的jndi名進行ejb定位。
······
InitialContext ctx = new InitialContext();
Object objref = ctx.lookup("example/ejbtest"); //使用<jndi-name> beanHome=(zcxejb1Home)PortableRemoteObject.narrow(objref,ejbtestHome.class);
······
第二種方式:
把ejb和web應用包裝成一個企業應用包。部署ear時可以簡單地把通過application.xml描述ejb jar包和web應用的war包,同樣在web.war中不需要提供特殊的信息就可以和第一種方式一樣使用ejb對象??蛻舳舜a也不需要進行改動。這里不再舉例說明。
此外我們可以進行更進一步的部署,這時需要使用到web.xml和jboss-web.xml。jboss-web.xml是JBoss提供的一個針對web應用進行配置的文件。jboss-web.xml和web.xml一起放在web應用的WEB-INF目錄下。
演示1:改動web.xml文件,添加<ejb-ref>標記,不使用jboss-web.xml文件。
(注意<ejb-ref>包括內部引用和外部引用。如果是同一個單元的可以通過<ejb-link>直接進行引用,而不用提供其他信息。)
web.xml:
······
<ejb-ref>
<ejb-ref-name>ejb/ejbtest</ejb-ref-name> <!--采用sun推薦的命名方式-->
<ejb-ref-type>Session</ejb-ref-type>
<home>org.zcx.test.zcxejb1Home</home>
<remote>org.zcx.test.zcxejb1</remote>
<ejb-link>ejbtest</ejb-link> <!--必須和被應用的ejb-name匹配-->
</ejb-ref>
······
客戶端:由于在web.xml中引入ejb引用描述這時ejb定位發生了變化:
······
InitialContext ctx = new InitialContext();
Object objref = ctx.lookup("java:comp/env/ ejb/ejbtest "); //使用java:comp/env命名空間 beanHome=(zcxejb1Home)PortableRemoteObject.narrow(objref,ejbtestHome.class);
······
演示2:聯合使用web.xml和jboss-web.xml
web.xml
······
<ejb-ref>
<ejb-ref-name>ejb/ejbtest</ejb-ref-name> <!--采用sun推薦的命名方式-->
<ejb-ref-type>Session</ejb-ref-type>
<home>org.zcx.test.zcxejb1Home</home>
<remote>org.zcx.test.zcxejb1</remote>
</ejb-ref>
······
jboss-web.xml
<ejb-ref>
<ejb-ref-name> ejb/ejbtest </ejb-ref-name>
<jndi-name> example/ejbtest </jndi-name> <!-- 這里對應ejb對象的jndi名-->
</ejb-ref>
客戶端:
nitialContext ctx = new InitialContext();
Object objref = ctx.lookup("java:comp/env/ ejb/ejbtest "); beanHome=(zcxejb1Home)PortableRemoteObject.narrow(objref,ejbtestHome.class);
以上的所有演示說明了ejb-jar.xml、jboss.xml、web.xml、jboss-web.xml之間的基本關系和它們的使用方式。它們是部署各類ejb對象的關鍵文件。接下來介紹針對不同類型的ejb對象所需要的特殊配置。
3.JBoss3.0中對于CMP2.0 Entity Bean的有關配置
JBoss3.0中JBossCMP引擎實現了EJB2.0 CMP2.0規范。JBoss3.0以前的版本CMP的引擎是Jaws,它通過standardjaws.xml和jaws.xml進行有關的配置。在新的JBossCMP引擎中Jboss3.0通過standardjbosscmp-jdbc.xml和josscmp-jdbc.xml來配置Entity Bean。JBoss3.0首先處理standardjbosscmp-jdbc.xml然后根據ejb jar中是否提供jbosscmp-jdbc.xml來做進一步處理。通過standardjbosscmp-jdbc.xml和jbosscmp-jdbc.xml可以為entity bean的部署提供如下的功能有:
l 指定所使用的數據源和對應的類型映射
l 指定一些引擎關心的屬性
l 指定引擎如何創建和管理數據庫表的原則
l 描述finder和ejbSelect方法
l 指定屬性和字段的類型映射
這里主要根據standardjbosscmp-jdbc.xml/jbosscmp-jdbc.xml介紹CMP2.0的配置方法。JBoss中原有的Jaws引擎的配置方法和新的JBossCMP的配置方法類似。這些文件的具體的信息可以參考JBoss安裝路徑下\docs\dtd中對應的DTD文件。
3.1增加新的數據源
JBoss自帶的數據庫是Hypersonic數據庫,我們可以增加一些新的數據源。具體的步驟很簡單,參照Jboss安裝目錄下\docs\examples\jca中的*-service.xml文件可以增加找到對應類型的數據庫配置樣本文件。以mysql-service.xml文件為例,它可以配置一個MySQL數據庫作為Entity Bean的數據源。以下演示創建一個名為MySQLDS的MySQL數據源。
圖一是配置好的mysql-service.xml文件的一段代碼樣本,通過屬性設置可以定制數據源的名稱和有關連接的其他屬性。注意該文件中所有name屬性必須保持一致。
圖一 mysql-servic.xml的樣本代碼
在配置好這個文件后,把它部署在JBoss的deploy目錄下,把對應的jdbc驅動也放在lib目錄下。重新啟動Jboss就會加載這個新的數據源。
3.2 Entity Bean 對數據源的使用
第一種方式:
直接改動standardjbosscmp-jdbc.xml。把原有的數據源java:/DefautlDS屏蔽掉使用新的數據源java:/MySQLDS。(Java前綴是必須的。)不需在其他地方作改動。JBoss會實現新的數據源做為缺省的數據源。圖二是一個配置好的文件片斷。
圖二 standardjbosscmp-jdbc.xml的樣本代碼
第二種方式:
由于有可能不同的Entity Bean使用不同的數據源,而不是都使用同樣的缺省配置,所以必須為單獨的Entity Bean提供定制數據源信息的支持。這時不需要改動standardjbosscmp-jdbc.xml文件,可以通過在Entity Bean的jar包中META-INFO目錄下添加新的部署文件jbosscmp-jdbc.xml來完成。通過這個文件可以描述特定的Entity Bean的關于數據源的配置信息。圖三是一個配置好的文件片斷。
圖三 jbosscmp-jdbc.xml的樣本代碼
4.JBoss3.0中對于Message Driven Bean的配置
在JBoss中開發MDB需要使用JMS功能。JMS是Sun公司開發的面向消息的中間件API。它的主要目的是創造一種統一的面向消息編程的JavaAPI,從而避免使用提供商特定的API?,F在有幾種不同的JMS系統可供使用。JBoss3.0中提供的是JBossMQ。
4.1 JBoss3.0中配置JMS服務
在JBoss3.0中與JMS服務相關的配置文件包括兩個文件:jbossMQ-service.xml和jbossMQ-destinations-service.xml。jbossMQ-service.xml配置了jbossMQ服務中的核心對象信息。一般我們不需要處理這個配置文件。jbossMQ-destinations-service.xml用于定義具體應用所需的目的地信息。通過編輯它我們可以創建新的Topic和Queue用于具體的JMS應用的目的地。在JBoss中創建應用特定的Topic和Queues的步驟比較簡單,參照jbossMQ-destinations-service.xml文件格式在該文件中添加自己應用程序所需的Topic名為myTestAppTopic和Queue名為myTestAppQueue。如圖四所示。
圖四 jbossMQ-destinations-service.xml的樣本代碼
4.2 JBoss3.0中EJB使用JMS服務的配置
在開發MDB 時要在部署文件中指定所使用的JMS服務中的目的地信息。JBoss中通過ejb-jar.xml和jboss.xml共同說明。在jboss.xml中通過<destination-jndi-name>標記描述所使用的目的地信息。
Ejb-jar.xml
<message-driven>
<ejb-name>HelloTopicMDB</ejb-name>
<ejb-class>org.zcx.test.HelloMDB</ejb-class>
<message-selector></message-selector>
<transaction-type>Container</transaction-type>
<message-driven-destination>
<destination-type>javax.jms.Topic</destination-type>
<subscription-durability>NonDurable</subscription-durability>
</message-driven-destination>
</message-driven>
jboss.xml
<message-driven>
<ejb-name>HelloTopicMDB</ejb-name>
<configuration-name>Standard Message Driven Bean</configuration-name>
<destination-jndi-name>topic/myAppTestTopic</destination-jndi-name>
</message-driven>
客戶端:
······
Context context = new InitialContext();
// Get the connection factory
// Create the connection
// Create the session
······
// Look up the destination
topic = (Topic)context.lookup("topic/myTestAppTopic");
// Create a publisher
// Publish the message
······
5.JBoss3.0中EJB使用JavaMail服務的配置。
由于JBoss提供了JavaMail服務的實現,所以在JBoss中使用JavaMail是非常方便地。它所需要配置的是mail.service文件。這個文件非常地簡單不用多介紹。按照mail.service文件的的注釋就可以順利地完成配置。
圖五是使用JavaMail服務的一個sessionBean的代碼片斷
圖五 使用javamail的樣本代碼
以上通過例子簡單的介紹了JBoss3.0中Session Bean、Entity Bean 和Message Drive Bean 最基本的配置和部署方法,通過這些介紹現在已經可以在JBoss中進行基本的EJB應用的開發了。本文中對于EJB應用中比較復雜的一些配置像權限設置、資源管理和CMP2.0中的眾多配置等都沒有涉及到,希望大家可以在不斷的實踐和交流中更好地掌握JBoss的使用和配置。