第一個 Session Bean(單機客戶端)


在EJB中,Session Bean通常是作為商務邏輯服務的 門戶(Facade),提供服務的存取進入點,Session Bean分為Stateless與Stateful,Stateless Session Bean對任何客戶端呼叫不保留任何操作階段的狀態,而對於需要數個操作以完成服務的功能,則可採用Stateful Session Bean,它會保留客戶端目前的操作狀態直到服務完成(某個操作完成)。

在這邊,將介紹如何撰寫您第一個Session Bean,為了簡化,先介紹的是Stateless Session Bean,並用一個遠端客戶透過JNDI取得Session Bean並執行。

Session Bean的定義首先由服務介面的定義開始,例如您定義一個HelloBean服務,當中有一個doHello()的操作:
  • HelloBean.java
package onlyfun.caterpillar;

import javax.ejb.Remote;

@Remote
public interface HelloBean {
public String doHello(String message);
}

@Remote標示出,這是一個可以遠端呼叫的服務介面,另一個相對的Annotation是@Local,當Session Bean與客戶端是位於同一個容器(同一個JVM)時,不需要有如遠端呼叫時物件序列化的負擔,則可以直接設定為@Local,這在之後還會看到範例。

再來您可以實作HelloBean介面,這是實際的Session Bean類別:
  • HelloBeanImpl.java
package onlyfun.caterpillar;

import javax.ejb.Stateless;

@Stateless(name="ejb/HelloFacade",
mappedName="ejb/HelloFacade")
public class HelloBeanImpl implements HelloBean {
public String doHello(String message) {
return message + "processed....";
}
}

@Stateless標示出,這是一個Stateless Session Bean,Stateless Session Bean不保留狀態,但不表示它不可以有屬性成員,類別內部執行相關方法時所需要的共用資料,是可以設定為屬性成員的。name屬性用來為Session Bean命名,這是容器所使用的屬性名稱,而某些Server上,會使用mappedName作為Bean的JNDI映射識別名稱(例如 Glassfish),不指定的話,則以介面名稱為JNDI名稱,例如onlyfun.caterpillar.HelloBean。

到這邊,Session Bean就撰寫完成了,將之部署到Server上,接下來就可以撰寫客戶端的部份了,客戶端這邊暫且利用JNDI查找到Session Bean來示範,如下:
  • Main.java
package onlyfun.caterpillar;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

public class Main {
public static void main(String[] args) throws NamingException {
InitialContext context = new InitialContext();
Object obj = context.lookup("ejb/HelloFacade");
HelloBean hello = (HelloBean) PortableRemoteObject.narrow(
obj, HelloBean.class);
String result = hello.doHello("XD...");
System.out.println(result);
}
}

在建立InitialContext之後,指定先前設定的"ejb/HelloFacade"名稱取得Session Bean代理物件,並使用PortableRemoteObject將之narrow為HelloBean,在RMI-IIOP雙方都是使用Java序列 化技術,您可以直接使用Cast而沒有問題,但建議使用PortableRemoteObject的narrow()方法,這是為了與CORBA相容的可能性。

為了讓InitialContext知道查找的相關資訊,您需要在Classpath中包括一個jndi.properties:
  • jndi.properties
java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory
java.naming.factory.url.pkgs=com.sun.enterprise.naming
java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl
# 選用,如果伺服端不在本機的話
org.omg.CORBA.ORBInitialHost=localhost
# 選用,如果伺服端不是使用3700埠的話
org.omg.CORBA.ORBInitialPort=3700

客戶端必須在Classpath中可以找到HelloBean.class以及javaee.jar、appserv-rt.jar,執行Main類別之後,將看到以下的執行結果:
XD...processed....