/** * A stateless session bean requesting that a remote business * interface be generated for it. */ @Stateless @Remote public class HelloWorldBean { public String sayHello() { return "Hello World!!!"; } }
有狀態回話bean
除了幾個SFSB的特別說明之外,有狀態回話bean(SFSB)和SLSB一樣精簡:
l 一個SFSB應該有一個方法來初始化自己(在EJB2.1中是通過ejbCreate()來實現的)。在EJB3.0的規范中建議這些初始化操作可以通過自定義方法完成,并把他們暴露在業務接口中。在使用這個bean之前由客戶端來調用相應的初始化方法。目前規范組織就是否提供一個注釋來標記某個方法用于初始化還存在爭議。
l Bean的提供者可以用@Remove注釋來標記任何SFSB的方法,以說明這個方法被調用之后bean的實例將被移除。同樣,規范組織仍然在討論是否要有一種機制來處理這種特殊的情況,即當這個方法出現異常的情況下bean的實例是否被移除。
下面是對以上問題我個人的觀點:
l 是否應該有一個注釋來標明一個方法進行初始化呢?我的觀點是――應該有,這樣容器就可以在調用其他方法之前至少調用一個方法來進行初始化。這不僅可以避免不必要的錯誤(由于沒有調用初始化方法)而且可以使容器更明確的判斷是否可以重用SFSB實例。我暫且把這個問題放一放,規范組織只考慮為一個方法提供一個注釋來聲明它是一個初始化方法。
l 對于第二個問題我的觀點也是肯定的。這有利于Bean的提供者合客戶端程序對其進行控制。只有一個遺留的問題:那就是一旦調用這個方法失敗,是否能移除這個bean 的實例?答案是不能,但是它將會在回話結束的時候被移除。
舉例來說,O/R映射模型將通過bean類中的注釋來聲明。而且此方法還會指出對應的具體表和字段。O/R映射模型提供了一套自有的SQL;而且除了提供一些基本的SQL外還支持某些高層開發的功能。比如,有一個通過@Column注釋聲明的字段columnDefinition,那么可以寫這樣的SQL:columnDefinition="BLOB NOT NULL"
.. .. @NamedQuery( name="findAllCustomersWithName", queryString="SELECT c FROM Customer c WHERE c.name LIKE :custName" ) .. .. @Inject public EntityManager em; customers = em.createNamedQuery("findAllCustomersWithName") .setParameter("custName", "Smith") .listResults();
下面列出了一些EJB QL的增強特性:
l 支持批量更新和刪除。
l 直接支持內連接和外連接。FETCH JOIN運行你指出關聯的實體,Order可以指定只查詢某個字段。
l 查詢語句可以返回一個以上的結果值。實際上,你可以返回一個依賴的類比如下面這樣:SELECT new CustomerDetails(c.id, c.status, o.count) FROM Customer c JOIN c.orders o WHERE o.count > 100
l 一種辦法是首先利用EJB文件生成類似于EJB2.1部署模式的文件(包括必要的接口和部署描述符)然后再用類似于EJB2.1的方式來部署這個EJB組件。當然,這樣產生的部署描述符可能并不標準但是它可以解決同一個容器對EJB2.1和EJB3.0兼容的問題。下面這幅圖描述了這一過程。
l 另一種方法是一種類似于jsp托放的部署模式。你可以把一個EJB文件放到一個預先定義的目錄下,然后容器會識別這個EJB并處理它,然后部署并使之可以使用。這種方法可以建立于上面那種方法之上,在支持反復部署時有很大的幫助。考慮到部署的簡單性也是EJB3.0規范的目的之一,我真誠的希望在下一個草案出來時能夠確定一個模式(至少能有一個非正式的)。
你有什么想法?
EJB3.0規范的制定正在有序的進行,為了使EJB的開發變得更加容易,EJB規范組織作出的努力是有目共睹的。就像他們說的那樣,一切對會變得簡單,但做到這一點并不容易。目前已經定義了50個注釋標記(還有幾個將在下一個草案中發布),每一個都有自己的缺省規則和其他的操作。當然,我真的不希望EJB3.0變成EJB2.1的一個翻版"EJB 3.0 = EJB 2.1 for dummies"(希望這個等式不要成立)。最后,我還是忍不住要提一些我自己的觀點:
l 首先,規范確實使反復部署變得容易了,并且有一個簡單的模式來訪問運行時環境。我還是覺得home接口應該放棄。
l 在早期的EJB規范中,實體bean用于映射一個持久化存儲。理論上(也許只是理論上)可能需要把實體bean映射到一個遺留的EIS(enterprise information system)系統中。出于將來擴展的考慮這樣作是有好處的,并且可以使更多的業務數據模型采用實體bean。也因此其伴隨的復雜性使得實體bean不被看好。在本次提交的草案中,一個實體bean只是一個數據庫的映射。并且是基于非抽象持久化模式和簡單的數據訪問模式的更加簡單開發。
l 我對模型變更持保留態度,我認為在EJB中包含SQL腳本片斷并不是個好注意。一些開發人員完全反對包含某些“SQL片段(SQLness)”(比如@Table 和 @Column注釋)。我的觀點是這些SQLness是好的,據此我們可以清楚的知道我們到底要數據庫作些什么。但是某些SQL段我看來并不是很好,比如columnDefinition="BLOB NOT NULL",這使得EJB代碼和SQL之間的耦合太過緊密了。
l 盡管對于本地SQL的支持看似很誘人,其實在EJB代碼中嵌入SQL是一個非常糟糕的主意。當然,有些辦法可以避免在EJB中硬編碼SQL,但是這應該在規范中說明,而不能是某些開發人員自己定義的模式。
l 假設@Table注釋只用于類。在運行時通過@Table注釋的name屬性定義的表名稱將必須對應一個實際的數據庫表。規范對此應該給予清楚的說明和一致的模式。
l 規范還需要更清楚的說明客戶端編程模型,尤其是普通java客戶端。規范中所有的參考都假設或者隱含的使用EJB客戶端。而且規范中對客戶端的向后兼容方面也沒有給出明確的說法。
l Transient注釋應該重新命名以避免和已有的transient關鍵字發生沖突。事實上,在這一點上我們更樂于稍微的背離一下configuration-by-exception原則并且定義一個@Persistent注釋來明確的定義持久化字段。@Persistent注釋可以僅僅是一個標記注釋或者它可以有幾個屬性來關聯O/R映射注釋。
l Web service接口:EJB規范將采用一種機制適應JSR181以便可以把一個bean實現為一個Web service并告訴Web service如何被客戶端調用。
l JSR 181計劃采用不同的機制來處理安全問題。在早期的規范中EJB建議使用一個一致的機制(MethodPermissions),但是JSR 181計劃使用一個稍微不同的方式(SecurityRoles和SecurityIdentity注釋)。同樣的RunAs注釋的定義也存在這些許差別。這一問題還在解決中最終會在J2EE層的規范中維持其一致性。