love fish大鵬一曰同風起,扶搖直上九萬里

          常用鏈接

          統計

          積分與排名

          friends

          link

          最新評論

          使用EJB3.O簡化EJB開發(全中文)(轉)

          使用EJB3.O簡化EJB開發??? 原著:Debu Panda

          我們引入EJB來構造分布式的組件。它誕生之時是為了解決所有CORBA的問題和復雜性。經歷過幾次重要的版本更新和增加許多特性之后,EJB已經成為了J2EE的核心。在早期,很多開發人員沉迷于EJB甚至在沒有任何意義的情況下在他們的工程中使用EJB。而當他們發現所使用的工程并沒有質的變化后,譴責EJB成了一種趨勢。

          開發EJB從來沒有變得簡單甚至在早期的EJB版本規范中變得更加復雜。EJB由于其的復雜性和重量級特性而被比作一只大象。學多開發人員感覺EJB象一個油炸圈餅上多余的一層甜糖漿。在現在low carb和Atkins diet大行其道的今天,EJB專家委員會也沒有選擇余地的發布了體現low carb的EJB規范來簡化EJB的開發。EJB3.0專家委員會在2004Javaone大會上發布了稱之為EJB3.0第一個公開規范的輕量級模型的范例圖。

          第一眼看到EJB的新模型感覺很不錯。在這篇文章中我們將討論EJB3.0如何使用一個更小而精致的裝配來吸引開發者的。在接下來的文章中我們將來討論EJB3.0是怎樣簡化持久性模型的。

          整理缺陷

          在我們開始對EJB3.0帶來的新特性進行討論之前,讓我們先分析一下現在EJB模型的復雜繁瑣。

          • 現在的EJB模型需要建立許多組件接口和實現許多不必要的回滾方法。
          • 組件接口需要實現 EJBObject 或者 EJBLocalObject ,并且處理許多不必要的異常。
          • EJB的部署描述復雜而容易出錯。
          • 基于EJB模型的容器持久化管理的開發和管理過于復雜。許多基礎的特征未考慮到,比如使用數據庫序列和EJBQL定義一個主鍵的標準方法就非常有限。
          • EJB組件不像是面向對象的,比如在使用繼承和多態時就有太多限制。
          • 一個主要的EJB的缺點是你不能脫離EJB容器測試一個EJB模型且不能在容器內調試一個EJB,這對開發者無疑是一個可怕的事情。
          如果你使用EJB你需要熟悉調用和查找EJB的復雜過程。顯然,你僅僅要在程序中使用EJB但你卻必須知道JNDI詳細的細節。

          簡化開發者的觀點

          如果你使用現有版本的EJB你會懂得開發一個如HelloWorld的簡單的EJB程序是多么困難。你至少需要兩個接口,一個bean類和一個部署描述文件。大多數的開發者希望知道為什么我需要所有這些。IDEs(開發環境工具)象OracleJDeveloper, EclipseXDoclet簡化了開發者的做這些普通的工作開發周期,可是在EJB在你部署到所選擇的容器中之前,編譯類和打包部署文件依然是開發人員的工作。

          EJB3.0試圖從以下方面簡化復雜性:

          ·???????? 不必定義接口和部署的描述文件,這些可以由容器使用metadata annotations生成。

          ·???????? 使用常用的Java類作為EJB的類和常用的EJB業務接口。

          元數據描述(Metadata Annotations)

          EJB3.0非常倚重Metadata Annotations。Metadata Annotations已經成為JSR 175標準并且將是J2SE 5.0的一部分。Annotations是一種對象變成的屬性,非常類似與XDoclet。可是不像XDoclet那樣需要預先編譯,Annotations由Java編譯器在需要編譯的時候編譯。(依賴于@Retention的開始時間)。在開發人員的觀點,Annotations就如同一個公有的并可以作為類,域,方法,參數,本地變量,構造,枚舉和包一樣使用的修改量。你可以在你的Java代碼中附帶特殊的屬性使用Annotations來生成代碼,自動編寫文檔代碼,或者提供如在運行期間增強業務層安全或特殊業務邏輯的特殊服務。J2EE1.5(5.0)的目標是簡化開發人員使用Annotations因此而可能產生一套的Annotations模板。Annotations使用@來標記,如下:

          ? @Author("Debu Panda")

          ? @Bean

          ? public class MySessionBean

          EJB3.0為了簡化開發因此使用Metadata Annotations來產生許多如接口一樣的人為因素和使用Annotations來替代部署描述文件。

          使用 POJOs 和 POJIs

          在規范條件中,JavaBeans和接口經常分別的涉及到簡單Java對象(POJOs)和簡單Java接口(POJIs)。這些不必要的如Home接口的人為因素已經被去掉。

          開發人員必須在javax.ejb包中實現一個EJB接口(會話bean,實體bean或消息驅動bean)或者選擇在bean的實現類中使用Annotation。你可以使用無狀態,狀態,消息驅動或者實體去注釋一個bean類。例如,如果你定義一個無狀態EJB作為HelloWorld,你可以如下定義EJB:

          @Remote

          ? @Stateless public class HelloWorldBean {

          ?public String sayHello(String s)

          ? { System.out.println("Hello: "+s; }

          ? }

          EJB的接口無論遠程的還是本地的都不必再實現EJBObjectEJBLocalObject。你要么為EJB提供業務接口并且實現bean類中的接口,要么需要在部署的時候生成這些接口。雖然會話bean和消息驅動bean的接口是必須的,但是實體bean的接口是可選的。如果你沒有為你的會話bean實現一個接口,那么它會自動為你生成一個。所生成的接口是本地的還是遠程的取決于你在bean類中的Annotations。如果你仔細看看上面的代碼范例,@Remote很明顯是用來為你的HelloWorld生成一個遠程接口。如果需要,你可以在你的EJB中同時生成遠程和本地接口。

          在上面的例子中,很明顯開發人員不必再做那些如定義接口和實現回滾方法等這些普通的工作。

          生成接口的名字來源于bean實現類的名字。生成接口對開發人員來說非常有用。但是我并沒有看到任何如Oracle 的JDeveloper的這些IDE立即實現這種生成接口功能。

          規范中沒有明確EJB查找時客戶端的需求是什么,也沒有明確我們如何保持這些EJB需要調用的接口。基于以下幾個情況下的原因我將不推薦使用生成接口:

          ·???????? 生成接口的名字來源于bean的名字

          ·???????? 如果你不愿意在EJB中暴露出一些方法而生成接口將默認暴露出所有的方法。

          ·???????? 你需要在客戶端使用接口來調用EJB.

          去掉回滾方法的需求。

          EJB2.1和更早版本需要實現很多即使對于每個EJB你不需要的一些生命周期的方法,如ejbPassivate, ejbActivate, ejbLoad, ejbStore等等。例如,在無狀態會話bean中不需要ejbPassivate但是你還是得實現它的方法。現在EJB3.0中類似的常用Java類實現這些生命周期的方法都變成為可選擇的。如果你在EJB中實現任何回滾容器都會調用這些方法。

          唯一的異常是在你可以使用Removeannotations時一個狀態會話bean的業務方法的ejbRemove方法是狀態會話bean。如果你使用這個annotations它將在完成annotations方法后(無論正常或非正常)提示容器移除狀態會話bean實例。例如,你可以指定以下的方式去在checkOut方法執行后移除一個狀態會話bean實例。

          @Stateful public class Cart {

          ...

          ...

          @Remove public void checkOut() {

          ...

          }

          }

          Annotations與部署描述的比較

          在前面我們討論到EJB中不再需要部署描述而由annotations代替。每個部署描述的屬性都將被選擇一個默認值,而開發人員在直到他們想改變這些屬性的默認值之前不必為這些屬性指定值。這些也能用來為bean的類自身指定使用的annotations。EJB3.0規范為開發人員使用bean類型,接口類型,資源引用,事務屬性,安全等等定義了一組metadata annotations。例如,如果我們可以如下為一個特殊的EJB定義使用資源引用:

          @Resource(name="jdbc/OracleDS", resourceType="javax.sql.DataSource")

          J2EE的提供商如Oracle, BEA, IBM將增加屬性annotations在他們指定的部署描述中,開發人員將可以使用這些annotations去避免使用部署描述。這看起來對開發人員十分具有吸引力,特別對XML描述是已經感到厭惡的開發人員,他們早就恨透并想脫離老的那種描述方式,但依然有一些問題使得我們在正式使用annotations時需要謹慎對待。

          • 它違背了我們輕便應用程序的目標,因為如果一個EJB如果使用一個提供商指定的部署描述,在重新編譯或打包EJB的時候它必須多次改變。
          • 部署描述對EJB模板提供了全局觀點使得組裝和部署的時候不必考慮單獨的EJB,他們將每個部署需求擰在一起,并且在部署完成之前描述是無效或者不可自動生成的。這對部署員來說是個可怕的事情。
          • 部署描述在EJB模板中被相關工具用來定義EJBs,當你試圖整合一個和另一個容器的時候非常有用。EJB3.0規格同樣主張在部署描述中使用重載annotations的方式。可是在規范里并沒有提到重載annotations的細節。

          無疑擺脫部署描述將使得新的開發者開發更加容易,但是如果使用不當這也將造成管理上的可怕問題。

          簡化持久化容器管理

          CMP實體bean將成為EJB3.0使得開發人員強制使用的一個主要的檢查方式。持久化框架象如OracleAS TopLink, 開源的Hibernate已經成為不像實體bean本質上的復雜和重量級的開發J2EE持久化框架應用的被大家喜愛的方式。 EJB3.0采納了如TopLinkHibernate輕量級的持久化模式來簡化容器持久化管理,這些聽起來更讓開發人員們欣喜。讓我們簡單的瀏覽一下實體bean的計劃,我們將在另外的文章中討論持久化改進的細節。

          實體bean作為POJOs已經改頭換面,實體bean將不在需要組件接口。實體bean現在看起來是支持繼承和多態的純粹的對象。

          下面的是關于實體bean源代碼

          @Entity public class Employee{

          ? private Long empNo;

          ? private String empName;

          ? private Address address;

          ? private Hashmap projects = new Hashmap();

          ? private Double salary;

          ? @Id(generate=SEQUENCE) public Long getEmpNo() {

          ? return empNo;

          ? }

          ? protected void setEmpNo(Long empNo) {

          ? this.empNo = empNo;

          ? }

          ? public String getEmpName() {

          ? return EmpName;

          ? }

          ? public void setEmpName(String EmpName){

          ? this.EmpName = EmpName;

          ? }

          ? @Dependent public Address getAddress() {

          ? return address;

          ? }

          ? public void setAddress(Address address) {

          ? this.address = address;

          ? }

          ? public Set getProjects() {

          ? return projects;

          ? }

          ? public void setProjects(Set projects) {

          ? this.projects = projects;

          ? }

          ? public Double getSalary() {

          ? return salary;

          ? }

          ? public void setSalary(Double salary) {

          ? this.salary = salary;

          ? }

          ? ....

          ? }

          如果你仔細看這些代碼,你可以發現在現在的實體beanbean類是一個具體的類而不再是一個抽象類。

          EJB QL和實體beanSQL查詢做了多項改進。類似于Hibernate的新的實體管理API和簡化版的TopLink的會話API被建議用來處理實體bean的操作,也就是實體bean的創建,釋放,查找。

          我們將在深入的文章中進一步對建議CMP實體bean的細節做更多的驗證。

          簡化EJB客戶端

          即使應用中EJB是序列化的,使用EJB也就是尋找和調用也是非常復雜的。J2EE 1.4 EJB 3.0規范致力于簡化EJB客戶端。

          如果目前你希望使用EJB你必須在部署描述中定義EJB引用或者EJB本地引用,尋找到EJB然后調用。如果我們希望調用HelloWorld EJB,你可以按照下面的簡單方法調用EJB使用已存在的實現。

          如下在部署描述中找到EJB指示的定義

          <ejb-ref>

          ? <ejb-ref-name>HelloWorldEJB</ejb-ref-name>

          ? <ejb-ref-type>Session</ejb-ref-type>

          ? <home>hello.HelloWorldHome</home>

          ? <remote> hello.HelloWorld</remote>

          ? </ejb-ref>

          然后按照如下方法尋找EJB.你需要明確處理EJB查找和建立一個bean實例時的異常。

          try

          ? {

          ??? Context context = new InitialContext();

          ?????????????? HelloWorldHome helloHome =

          ?????????????? ? (HelloWorld)PortableRemoteObject.narrow(context.lookup

          ???? ("java:comp/env/ejb/HelloWorldEJB"), HelloWorldHome.class);

          ?????????????? HelloWorld hello = helloHome.create();

          ?????????????? ? ....

          ?? }

          ??? catch(RemoteException e)

          ?????????????? {

          ?????????????? ? System.err.println("System/communication error: " + e.getMessage());

          ?????????????? }

          ?????????????? catch(NamingException e)

          ?????????????? {

          ?????????????? ? System.err.println("Communication error: " + e.getMessage());

          ?????????????? }

          ?????????????? catch(CreateException e)

          ?????????????? {

          ?????????????? ? System.err.println("Error creating EJB instance: " + e.getMessage());

          ?????????????? }

          如一個環境變量的變化一樣,EJB3.0建議使用安放injection的方法查找和調用EJB.

          下面我們使用安放injection的方法在另一個EJB查找HelloWorldEJB

          @Inject private void setSessionContext(SessionContext ctx)

          ? {

          ? this.ctx = ctx

          ? }

          ? ...

          ? myHello = (HelloWorld)ctx.lookup("java:comp/env/ejb/HelloWorldEJB");

          如果你仔細查看上面的代碼,它依賴的injection使用@Injectset來的指定對SessionContext方法的annotationsinjection 方法將可以在業務方法被EJB調用前被容器調用來設定EJBContext

          另一個injected HelloWorld會話bean的直接的范例可以簡化為使用

          @EJB public HelloWorld myHello,這將使得myHelloHelloWorld bean的實例injected

          你可以使用依賴的injection來查詢任何類型的環境和資源參考如DataSource, JMS, Mail, Web Service等等。

          容器外部測試可行性

          一個現在EJB開發者所關注的不僅僅是EJB開發的復雜,也包括了測試的可怕之處。開發和測試EJB必須需要一個EJB容器并且開發人員必須熟悉最終部署平臺才可以執行測試。這對于許多只在一個主要平臺開發的企業開發人員來說不是主要問題,但是對于支持多個開發商平臺并且要在維護的多個環境中測試EJBISV們來說是個大問題。EJB3.0規范承諾將提供在容器外測試的功能,但是這點在這次的規范中遺漏掉了。

          結論

          雖然還有很多關于打包,裝配和重要的API細節沒有在這個規范中提及,但是諸多的建議使得EJB3.0規范讓企業級Java開發人員看起來是恨有前途的。通過這些無疑是從開發人員到服務供應商都將幫助減少開發的復雜性。下面就要看服務提供商們怎么實現,并使得EJB3.0成為企業級應用一個引人矚目的選擇。

          Author Bio 作者自述

          Debu PandaOracle應用服務開發小組的主要管理者,他的在EJB容器和事務管理上取得過很多成就。他已經有13年的IT產業的經驗并在多家雜志和技術出版社刊登過很多著作。

          ?

          翻譯問題:

          由于部分英文名詞未敢枉自翻譯,所以留英文原詞在文中

          Cleaning up the Dirty Laundry?????? 整理缺陷

          low carb

          Atkins diet

          metadata annotations???? ?????????????? 元數據描述

          Simplifying Client View for EJBs?? 簡化EJB客戶端

          dependency injection???????? ?????????? 依賴型injection

          setter injection????????????? ?????????????? 安放injection

          ISV Independent software vendor 獨立軟件供應商

          posted on 2006-06-30 11:49 liaojiyong 閱讀(506) 評論(0)  編輯  收藏 所屬分類: EJB

          主站蜘蛛池模板: 灌云县| 商丘市| 安国市| 盐源县| 资中县| 镇远县| 乐至县| 龙泉市| 瓮安县| 乡宁县| 象州县| 井陉县| 萨迦县| 东丽区| 汤原县| 上林县| 韩城市| 深水埗区| 大同市| 海淀区| 嘉荫县| 辽源市| 赤城县| 武清区| 峨眉山市| 沈丘县| 无为县| 绥棱县| 浪卡子县| 镇雄县| 通河县| 双江| 邵阳市| 鹿邑县| 称多县| 博爱县| 丹寨县| 旅游| 杭锦旗| 咸宁市| 册亨县|