何謂EJB:
 
Eenterprise JavaBean 很簡單. ㄟ~ 至少比自己寫一個具延展性(scalable), 交易性(transctional), 安全性(secure), 又能支援多人多工(concurrent) 能力的企業級伺服器相比的話. ps: 但是它"不保證"負載平衡(load-balance), 容錯(fail-over), 和叢集(clustering).
 
使用EJB, 可以研發出像積木一樣的EJB Component, 這可以讓你或其他人組合出新的或是重組到不同應用程式的元件. 你可以利用宣告的方式來設定和客制化bean (透過XML為基礎的佈署描述檔 Deployment Descriptor; DD) 來改變執行時期bean的特性. 換句話說, 就是在部署時期透過改變XML文件來改變一個bean使用底層服務的方式. EJB 不單只是寫一次到處跑(write once run anywhere), 而是寫一次到處裝(write once deploy anywhere)
 
EJB 讓人專注在商業邏輯上, 而將所有底層的服務交給EJB伺服器的供應商(Server Vendor)來解決. EJB Server提供了一堆services, such as 交易管理(Transaction management), 安全控管(Security), 多人多工(Concurrency), 網路通訊(Networking), 資源管理(Resource management), 存續管理(Persistence), 訊息服務(Messaging), 佈署時期的客制化(Deploy-time customization).
 
 
Q: EJB和J2EE有什麼不同?
A: J2EE和EJB都是對伺服器的規範, 實際上EJB是J2EE的子集合, 換句話說, 一個J2EE伺服器裡面包含一個EJB Container. 所以每個 J2EE Server 必須包含一個 EJB Container 和一個 Web Container(to run JSP & Servlet).
 
Q: 可以在Java類別裡撰寫商業邏輯程式碼, 然後在 bean 裡去呼叫這些商業邏輯方法, 這樣我就可以再利用這些商業邏輯嗎?
A: 可以, 如果你的 bean 呼叫一個不是 bean 的 Java 類別上的方法, 那個方法還是在 Container 的控制範圍之下, 所以只要關係到了 Container, 那些非 bean 的方法也會變成 bean 的一部分功能.
 
Q: 一般 javabean 和 enterprise javabean 有何不同?
A: 一般 javabean 是指一些根據命名原則所撰寫且可以被開發工具使用的可在利用元件. 且絕大部分都被利用在開發時期, 主要是為了讓一個 bean 的 event 更簡單快速的聯接上別的 bean 的方法, 或是改變instance variable value. 就像其他一般的 class 一樣, 可以在 JVM 裡面執行. 可利用在 Swing, Jini, Servlets...等, 但是一個 enterprise javabean 必須在一個 EJB Container 的控制下執行, 且在執行時期才會被交出來. 在一個 EJB 裡面絕大部分的方法都是 Container 自己去呼叫的. 而這些方法到了 Server 外就變得沒有意義了.
 
 
EJB Server 裡面的三大部分: 
 
1. EJB Object: 會干涉所有對 bean 的呼叫, 所以用戶端永遠不能跟 bean 直接交談. The EJB object is the bodyguard for the bean... it intercepts the calls coming from the client and passes the request to the Container. 這使得 server 或 container 有機會介入並加入一些底層的服務(container services).
 
2. Container services: The Container services are the things you’re paying for... the reason you’re using EJB in the first place - transactions, security, persistence, etc.
 
3. EJB: The bean has the real business logic. It has the actual functionality (method code) to do whatever it is this remote service is supposed to do (track your shopping cart, do a big calculate, update a customer’s address, etc.
 
 
 
三種 bean:
 
1. Entity: 使用一個 entity bean 來代表在永續儲存體(persistence store) 裡面的一個東西, 通常會來代表資料庫裡的某個東西, 而一個 entity bean 的一個實體(instance) 代表 table 裡的一筆資料. 一個典型的 entity 範例就是 Customer, 其中一個實體可能代表 Bo Olean(ID# 343) 而另一個 instance 可能代表 Trixia Lin (ID# 870).
 
2. Message-driven:你需要一個 JMS 用戶時就可以使用 message-driven bean. 換句話說, 它可以監聽來自 JMS 信息服務的信息. 就如同規範一樣, 用戶端永遠不可能直接呼叫 message-driven bean, 但是 message-driven bean 沒有 EJBObject, Client 必須發送一個信息給信息服務, server 會直接從信息服務取得用戶端的請求.
 
3. Session: entity bean 通常代表一個東西, 而 session bean 代表一個處理程序(process). 除了上述所有的事情以外, 都使用 session bean. 幾乎所有型態的後端服務都可以, 也通常應該要由一個 session bean 起始. 這是因為通常會使用到一種叫做 Session Facade 的 Design Pattern.
 
兩種 Session bean:
 
3-1. stateful 的 session bean: 可以在方法呼叫的過程中記住交談狀態(conversational state, 就像購物車).
 
3-2. stateless bean 一旦等到被呼叫的方法完成了以後就會直接把這個 client 給忘掉. 不過這不代表用戶端不會持續的呼叫這個 bean 來記住與前一次的方法呼叫有關的狀態. 一個stateless bean 還是可以有 instance variable, 它只是無法用來維持屬於某個特定用戶的值.
 
雖然 stateless session bean 比 stateful session bean 要來的延展性(scalable)(因為這跟 Contaniner 如何管理 stateless session bean ),  但是當你需要交談狀態時, 你應該考慮 stateful session bean, 還有就是當使用替代方法來保存時所造成的效能影響比 stateful session bean 還大的時候.
ps: 這裡指的保存狀態像是讓用戶端來保存狀態, 或用 servlet 來保存狀態, 甚至使用資料庫來保存這個用戶端災呼叫每個方法與方法之間的狀態. 
 
* Entity bean 可能代表的是在酒吧裡賣的各種飲料及每個客戶, 但是沒有調酒師, 飲料對客戶有什麼意義? 你需要有個人把實體的東西(飲料與客戶) 透過某種意義連結在一起, 那就是 session bean 要做的事情!
 
 
 
建立一個 EJB 要做的五件事情:
 
1. 撰寫具有商業邏輯的 bean class.
 
package headfirst;
import javax.ejb.*;
public class AdviceBean implements SessionBean
{
 private String [] adviceStrings = {"test", "test1", "test2", "test3"};
 public void ejbActivate() //必須實作來自 SessionBean 的 method
 {
  System.out.println("ejb activate");
 }
 public void ejbPassivate() //必須實作來自 SessionBean 的 method
 {
  System.out.println("ejb passivate");
 }
 public void ejbRemove() //必須實作來自 SessionBean 的 method
 {
  System.out.println("ejb remove");
 }
 public void setSessionContext(SessionContext ctx) //必須實作來自 SessionBean 的 method
 {
  System.out.println("session context");
 }
 
 public String getTheMessage() //來自 component 的真正的商業邏輯, 也是 Client 想呼叫的東西
 {
  System.out.println("in get advice()");
  int random = (int)(Math.random()*adviceStrings.length);
  return adviceStrings[random];
 }
 public void ejbCreate() //不來自 SessionBean, 但是是一個 EJB 規則, 必須要有這個 method
 {
  System.out.println("in jeb create()");
 }
}
 
2. 為這個 bean 寫兩個 interface (Home & Component).
 
HOME 介面: Client 使用 home interface 來要求一個對 component interface 的參照. 這個 home 是 client 為了要取得一個對 bean reference 的起始點(或至少 client 會認為這是一個 bean ). 我們可以先把 home 想像為某個製造和散佈 bean 的 reference 給 client 的工廠.
 
package headfirst;
import javax.ejb.*;
import java.rmi.RemoteException;
public interface AdviceHome extends EJBHome
{
 //create() 必須回傳一個 component interface 型態
 public Advice create() throws CreateException, RemoteException;

}
 
COMPONENT: 所有商業邏輯宣告的地方. 換句話說, 就是把所有 client 想呼叫的 method 都放在這裡.
 
package headfirst;
import javax.ejb.*;
import java.rmi.RemoteException;
public interface Advice extends EJBObject
{
 //實際的商業邏輯 必須對應到 bean class 裡面的 method
 public String getTheMessage() throws RemoteException;
}
 
Q: 為何 bean class 必須要有和 component interface 相同的 method 卻不去實作 component 呢?
 
A: 規範裡不建議這樣做, 因為:
 
1) component extends EJBObject, 而 EJBObject 不是一個標誌介面, 它是具有一些方法的, 這意味著任何一個實作 component 的 bean 也必須實作 EJBObject 的所有方法. 而且, EJBObject extends java.rmi.remote interface, 所以如果 bean 真的 implements component, 那也代表 bean 將成為一個 remote class, 這永遠都不該發生! 因此除了 server 本身以外, 永遠不應該用任何東西, 任何方式去存取 bean.
 
2) 雖然對 client 來說, 好像是直接呼叫 bean class 的 method, 但是真正來說, 是呼叫 component 的 method, 換言之, client 真正呼叫的是 EJBObject, 這是 server 在 deploy 時實作出來的. client 永遠, 永遠, 永遠不會直接跟 bean 互動.
 
3) 透過 component interface 的 implements EJBObject(由 server 製作出來的 EJBObject ), 也就是 remote object, 它會干預所有對這個 bean 的 business logic method 的呼叫. 
 
4) 所以我們透過 server 來檢查 component interface 與 bean class 的 method 是互相吻合的.
 
 
重點來了!!
1. component interface  has to implements EJBObject.
2. this bean has to implement SessionBean, and can't implements component.
3. verify the same methods of bean & component via a deployment tool.
 
3. 建立一個 XML 的 Deployment Descriptor; DD, 來告訴 server:  是哪一種 bean, 和如何管理它. 必須將它命名為 ejb-jar.xml. DD 必須放在一個稱為 META-INF 的目錄下.
 
4. 將這個 bean, 兩個 interface, 和 Deployment Descriptor 放進一個 ejb-jar檔(一個 ejb-jar 檔案裡面可能會有一個以上的 EJB, 但是只會有一個 DD). 
 
ps: 以上4個步驟都是 Bean Provider (bean 開發人員) 需要做的.
 
5. 利用 server vendor 所提供的工具把這個 bean deploy 到 server 上. 其實這步驟包含了兩各步驟:
5-1. 組成應用程式(Application Assembly): 整合不同的 bean 跟一個 DD 放在一個全新的 ejb-jar 檔. 在整合的階段, 也需要加入一些 Bean Provider 不知道的事情到 DD 裡面.
5-2. 佈署(Deployment): deployment 的兩個關鍵部份就是:
5-2-1) 命名 bean, 所以 client 會知道如何找到 bean.
5-2-2) 讓 bean 進入到 container 的控管範圍.
 
 
 
EJB 參與人員的腳色與責任:
 
Bean Provider:
應交付事項: ejb-ja 檔案.
責任: 撰寫 bean 的原始碼.
特性: 知道 business logic.
 
Application Assembler:
應交付事項: ejb-ja 檔案(加上 bean provider 資訊成為應用程式組合資訊). 同時也有可能建立 client 和定義與其他元件的互動關係, 如: JSP.
責任: 結合一個或多個 EJB 到一個更大的應用程式. 有時會扮演 bean provider 的腳色, 將新的和現存的 bean 混合在一起建立一個 application. 並為這個 application 定義安全控管和交易特性.
特性: 知道 business logic. 但不需要像 bean provider 寫那麼多的程式.
 
Deployer:
應交付事項: 對特定的運作環境客制化 EJB, 然後 deploy 到 server.
責任: 將 Application Assembler 交付的東西拿來研究裡面的佈署敘述, 然後解決任何依賴到外部的東西. 如果 bean 依賴在某個資源上, 這各 deployer 必須從 bean provider 對應的邏輯名稱再對應到這個 server 上真正的資源名稱. 簡單的說: 當 Bill 撰寫 bean 的原始碼時候並不知道它會被放到 Dick 的 server 上. Bill 為 Database server 捏造了一個假的名稱, 而 Dick 必須將這個假的 Database 名稱連接到真實的東西上.
特性: 知道 server 裡的設定, 還必須知道如何將 bean provider 和 application assembler 提供的 Deployment descriptor 做怎樣的修正.
 
Container 和 Server Vendor:
應交付事項: EJB 共容伺服器, 佈署工具, EJB 執行環境.
責任: 按規範實作出相容的 Container 或 Server.
特性: 分散式物件與交易, 和底層低階系統服務的專家.
 
 
 
Client 必須要做的 5 件事:
 
1. 取得一個對 JNDI InitialContext 的 reference.
 
2. 使用 InitialContext 去 lookup 那個 bean 的 home interface. 換句話說, 就是使用在 deploy 時所給的 JNDI 名字去 lookup.
 
3. Narrow 和 Cast 我們透過 lookup 傳回來的東西, 而這個東西實作了 home interface.
 
4. 呼叫在這個 home interface 上的 create(), 去取得一個對 component interface 的 reference.
 
5. 呼叫 component interface 上的 business logic method.
 
 
 
 
 
 
 
arrow
arrow
    全站熱搜

    Kalin 發表在 痞客邦 留言(0) 人氣()