Stateless Session Bean 是 EJB 3 最基礎、最常用的元件類型,適合無狀態業務邏輯處理。本文從開發環境建置、專案建立、介面與 Bean 實作、打包部署、客戶端呼叫,完整呈現第一個 EJB 3 專案的誕生流程。
JBoss 4.2+ 預設僅綁定 127.0.0.1,遠端存取需指定 -b 參數:
run.bat -b 0.0.0.0 # 綁定所有網卡,接受任意 IP 連線
run.bat -b 192.168.1.100 # 綁定特定 IP
Eclipse 運行配置:
Run Configurations → Arguments → VM arguments 加入:-b 0.0.0.0

未設定 -b 時遠端呼叫會拋出:
Connection refused: connect / CommunicationException
MyEJBpackage service;
import java.util.List;
import javax.ejb.Remote;
import entity.Greeting;
@Remote
public interface Greeter {
String greet(String message);
List<Greeting> getAllGreetings();
}
package entity;
import java.io.Serializable;
public class Greeting implements Serializable {
private int id;
private String name;
// getter/setter 略
// 實作 Serializable 才能跨 JVM 傳遞
}
package service;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import entity.Greeting;
@Stateless
public class GreeterBean implements Greeter {
@Override
public List<Greeting> getAllGreetings() {
List<Greeting> list = new ArrayList<Greeting>();
Greeting g1 = new Greeting(); g1.setId(12); g1.setName("bill gates"); list.add(g1);
Greeting g2 = new Greeting(); g2.setId(334); g2.setName("李寧"); list.add(g2);
return list;
}
@Override
public String greet(String message) {
return "您好 " + message;
}
}
@Stateless:聲明為無狀態 Session Bean@Remote (在介面上):聲明為遠端業務介面SessionBean 介面、無需 ejbCreate 等回呼方法 (EJB 2.x 遺物)Eclipse 配置 JBoss Runtime 後,儲存檔案自動編譯打包部署至 $JBOSS_HOME/server/default/deploy:
MyEJB.jar
├── entity/
│ └── Greeting.class
├── service/
│ ├── Greeter.class
│ └── GreeterBean.class
└── META-INF/
├── MANIFEST.MF
└── jboss.xml (Eclipse 自動生成,可指定 JNDI 名稱)
package test;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import service.Greeter;
public class Client {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.setProperty(Context.PROVIDER_URL, "192.168.17.105:1099");
prop.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
InitialContext ctx = new InitialContext(prop);
Greeter greeter = (Greeter) ctx.lookup("GreeterBean/remote");
System.out.println(greeter.greet("李寧"));
System.out.println(greeter.getAllGreetings().get(0).getName());
}
}
專案 src 目錄建立 jndi.properties:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory java.naming.provider.url=192.168.17.105:1099
客戶端簡化為:
InitialContext ctx = new InitialContext();
Greeter greeter = (Greeter) ctx.lookup("GreeterBean/remote");
System.out.println(greeter.greet("李寧"));
System.out.println(greeter.getAllGreetings().get(0).getName());
您好 李寧 bill gates
必須加入 $JBOSS_HOME/client 目錄下所有 JAR 至 Classpath:
| 部署單元 | 預設 JNDI 名稱 | 範例 |
|---|---|---|
| EAR | 耳名/Bean名/remote | MyEnterprise/GreeterBean/remote |
| JAR | Bean名/remote | GreeterBean/remote |
| 錯誤 | 原因 | 解決 |
|---|---|---|
Connection refused | JBoss 未啟動或 -b 參數錯誤 | 檢查 JBoss 進程、確認 -b 0.0.0.0 |
ClassNotFoundException: org.jnp.interfaces.NamingContextFactory | 客戶端缺少 jnp-client.jar | 加入 $JBOSS_HOME/client 所有 jar |
NameNotFoundException: GreeterBean not bound | JNDI 名稱錯誤或 Bean 未部署 | 查看 JBoss JMX Console → JNDIView 確認實際綁定名稱 |
InvalidInvocationException | 序列化版本不匹配 | 確保客戶端與伺服端共用相同介面/實體類別 JAR |