EJB 全名 Enterprise JavaBean,在 Java 平臺版圖中屬於 Java EE 的範疇,EJB 3.1 則包含在 2009 年 12 月 9 日 發佈的 Java EE 6 [1] 中。雖然 Java EE 6 已經發佈有一段時間了,截至目前為止能完整支援的只有 GlassFish [2],不過這是現在進行式,我相信很快就會有各廠的支援。
在 EJB 3.1 的世界裡,EJB 分為兩類,一類是用來處理 request 的 Session Bean,另一類則是處理 message 的 Message-Driven Bean。而 Session Bean 又因功能、目的不同分成三種,個別為 Stateless Session Bean、Stateful Session Bean 及 Singleton Session Bean。這些 EJB 都運行 Server 的 EJB Container 中。
基本上和撰寫一般的 Java Bean 沒太多不同,差異在於必須以 Annotations 加註 EJB 的種類,Session Bean 必須 implements [1] 供其它 Java Code 呼叫時所使用的 Business Interface [2],而 Message-Driven Bean 則必須事先定義好對應的訊息,EJB Container 會在收到對應的訊息時自動觸發 Message-Driven Bean。
看了這麼多定義,只能說模糊還是模糊,抽象還是抽象,不如直接動手做!就選最基礎的 Stateless Session Bean 作為今天的範例!
加註了 @Remote 代表實作此 interface 的 Session Bean,可被運作於不同的 JVM 上的 Java Code 呼叫。在這個 interface 之中只宣告了一個方法 hello,沒有輸入的參數,回傳的資料型態為 String。
加註了 @Stateless 代表這個類別被定義為 EJB 中的 Stateless Session Bean。承前所述,Session Bean 必須去實作 Business Interface,所以 MyFirstSLSB 實作了 MyFirstSLSB,並定義了 hello 方法,簡單的回傳字串 "Hello EJB 3.1!"。
看了例子應該清楚很多,其實 EJB 3.1 並沒有想像中的那麼難!
如果有興趣的話,可以去找找在 EJB 3.1 之前的 Code 是長什麼樣子,我唯一的感想是
=> 難怪沒有人想用!
講了這麼多,到底什麼是 Stateless Session Bean(以下簡稱 SLSB)?這邊的 State 代表狀態,而 Stateless 就是沒有狀態。這是什麼意思呢?對一個 Java Bean "A" 而言,在某個時間點所有 A 擁有的變數所存之數值,即代表 A 在該時間點的狀態,所以 Stateless 對 Java Bean 來說,就是不保證有這樣的狀態。
簡單來說,每次呼叫 SLSB 的方法,都應該把這個 SLSB 當成全新的 SLSB,因為 SLSB 並不保證其狀態。理由是雖然我們使用是同一個變數進行呼叫,但實際上底層在呼叫方法時,會到 EJB Container 中取回一個 SLSB,但是誰能保證這個 SLSB 就是我之前呼叫過的那個 SLSB 呢?這也就是為什麼會有另一種 EJB - Stateful Session Bean。
說來說去,終於輪到說怎麼用的時刻啦!
直接來看個範例!
接著,透過 lookup,查詢要使用的 SLSB。這個字串 "idv.marsping.practice.MyFirstSLSBRemote" 就是所謂的 JNDI Name,你問為什麼我會知道喔?給一個小提示,在部屬 EJB 時,可以看一下 GlassFish 的 Console,裡頭會出現關鍵字 JNDI,那些字串就是啦,雖然有好幾種不同的格式,但是效果都相同!
依照先前所說明的,我們只能透過 Business Interface 去操作 Session Bean,於是我們呼叫 hello 並印出來!
那麼結果到底如何呢?
以上,就是我對 EJB 3.1 一點小小的心得分享~
什麼?你問我是用什麼開發的?喔喔!請愛用 NetBeans!
- Java EE 平臺有許多不同功能的套件,如:負責商業邏輯的 EJB、負責訊息服務的 JMS、負責顯示的 JSF... 等。在 EJB 3.0 後,除了提供新特性,更改進開發流程,原本必須使用 XML 進行設定的繁複作業,改以 Annotations 簡化。更多資料可參考 Wikipedia - Java EE 和 Wikipedia - EJB。
- GlassFish 原為 Sun 發佈的 Open Source 專案,後來 Sun 被 Oracle 併購,現為 Oracle 所擁有。目前完整支援 Java EE 6 的平臺僅有 GlassFish,其它 Server,如:JBoss、WebLogic 僅有部份支援。
先說說 EJB 的種類吧!
在 EJB 3.1 的世界裡,EJB 分為兩類,一類是用來處理 request 的 Session Bean,另一類則是處理 message 的 Message-Driven Bean。而 Session Bean 又因功能、目的不同分成三種,個別為 Stateless Session Bean、Stateful Session Bean 及 Singleton Session Bean。這些 EJB 都運行 Server 的 EJB Container 中。
那麼,該如何撰寫 EJB 呢?
基本上和撰寫一般的 Java Bean 沒太多不同,差異在於必須以 Annotations 加註 EJB 的種類,Session Bean 必須 implements [1] 供其它 Java Code 呼叫時所使用的 Business Interface [2],而 Message-Driven Bean 則必須事先定義好對應的訊息,EJB Container 會在收到對應的訊息時自動觸發 Message-Driven Bean。
- 依照運行的 JVM 相同與否,Session Bean 必須去實作 Local(同 JVM,加註 @Local)或 Remote(不同 JVM,加註 @Remote)Interface。EJB 3.1 中,在同 JVM 運作的 Session Bean 可不必提供 Local Interface。
- Business Interface 其實就是加註了 @Local 或 @Remote 的 Java Interface。被稱為 Business Interface 的理由是 Session Bean 並非透過 new 來取得 Object,而是向 Server 查詢取得對應的 Proxy Object,該 Proxy Object 只能執行定義在 Interface 中的 Business Method,而非 Session Bean 中所有的 Public Method,故稱為 Business Interface。
看了這麼多定義,只能說模糊還是模糊,抽象還是抽象,不如直接動手做!就選最基礎的 Stateless Session Bean 作為今天的範例!
package idv.marsping.practice;
import javax.ejb.Remote;
@Remote
public interface MyFirstSLSBRemote {
String hello();
}
這就是所謂的 Business Interface 了!import javax.ejb.Remote;
@Remote
public interface MyFirstSLSBRemote {
String hello();
}
加註了 @Remote 代表實作此 interface 的 Session Bean,可被運作於不同的 JVM 上的 Java Code 呼叫。在這個 interface 之中只宣告了一個方法 hello,沒有輸入的參數,回傳的資料型態為 String。
package idv.marsping.practice;
import javax.ejb.Stateless;
@Stateless
public class MyFirstSLSB implements MyFirstSLSBRemote {
public String hello() {
return "Hello EJB 3.1!";
}
}
叮咚~!這就是傳說中的 EJB 啦!!import javax.ejb.Stateless;
@Stateless
public class MyFirstSLSB implements MyFirstSLSBRemote {
public String hello() {
return "Hello EJB 3.1!";
}
}
加註了 @Stateless 代表這個類別被定義為 EJB 中的 Stateless Session Bean。承前所述,Session Bean 必須去實作 Business Interface,所以 MyFirstSLSB 實作了 MyFirstSLSB,並定義了 hello 方法,簡單的回傳字串 "Hello EJB 3.1!"。
看了例子應該清楚很多,其實 EJB 3.1 並沒有想像中的那麼難!
如果有興趣的話,可以去找找在 EJB 3.1 之前的 Code 是長什麼樣子,我唯一的感想是
=> 難怪沒有人想用!
什麼是 Stateless Session Bean?
講了這麼多,到底什麼是 Stateless Session Bean(以下簡稱 SLSB)?這邊的 State 代表狀態,而 Stateless 就是沒有狀態。這是什麼意思呢?對一個 Java Bean "A" 而言,在某個時間點所有 A 擁有的變數所存之數值,即代表 A 在該時間點的狀態,所以 Stateless 對 Java Bean 來說,就是不保證有這樣的狀態。
簡單來說,每次呼叫 SLSB 的方法,都應該把這個 SLSB 當成全新的 SLSB,因為 SLSB 並不保證其狀態。理由是雖然我們使用是同一個變數進行呼叫,但實際上底層在呼叫方法時,會到 EJB Container 中取回一個 SLSB,但是誰能保證這個 SLSB 就是我之前呼叫過的那個 SLSB 呢?這也就是為什麼會有另一種 EJB - Stateful Session Bean。
怎麼使用 Stateless Session Bean?
說來說去,終於輪到說怎麼用的時刻啦!
直接來看個範例!
package sampleejbtest;
import idv.marsping.practice.MyFirstSLSBRemote;
import javax.naming.InitialContext;
public class SampleEJBTest {
public static void main(String[] args) throws Exception {
InitialContext context = new InitialContext();
MyFirstSLSBRemote ejb = (MyFirstSLSBRemote) context.lookup("idv.marsping.practice.MyFirstSLSBRemote");
System.out.println(ejb.hello());
}
}
為了向 GlassFish 的 EJB Container 查找我們要使用的 SLSB,我們必須先取得 InitialContext,由於 GlassFish 是跑在本機上,所以並沒有做額外的屬性設定(小提醒:記得要把 gf-client.jar 加入 classpath 中)。import idv.marsping.practice.MyFirstSLSBRemote;
import javax.naming.InitialContext;
public class SampleEJBTest {
public static void main(String[] args) throws Exception {
InitialContext context = new InitialContext();
MyFirstSLSBRemote ejb = (MyFirstSLSBRemote) context.lookup("idv.marsping.practice.MyFirstSLSBRemote");
System.out.println(ejb.hello());
}
}
接著,透過 lookup,查詢要使用的 SLSB。這個字串 "idv.marsping.practice.MyFirstSLSBRemote" 就是所謂的 JNDI Name,你問為什麼我會知道喔?給一個小提示,在部屬 EJB 時,可以看一下 GlassFish 的 Console,裡頭會出現關鍵字 JNDI,那些字串就是啦,雖然有好幾種不同的格式,但是效果都相同!
依照先前所說明的,我們只能透過 Business Interface 去操作 Session Bean,於是我們呼叫 hello 並印出來!
那麼結果到底如何呢?
Hello EJB 3.1!
如同預期!!真開心~終於結束了 Orz...以上,就是我對 EJB 3.1 一點小小的心得分享~
什麼?你問我是用什麼開發的?喔喔!請愛用 NetBeans!
留言