首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JBoss 4.x 上開發首個 EJB 2.x 應用:完整專案結構、原始碼與部署實戰

     編輯:Java 相關知識

專案背景與動機

雖 EJB 3.0 已大幅簡化開發模型,但理解 EJB 2.x 架構對維護舊系統、掌握 EJB 演進歷史仍有價值。本文記錄在 JBoss 4.x 上從零構建首個 Stateless Session Bean 完整流程。

專案目錄結構

E:.
│  build.xml
│
└─src
   ├─META-INF
   │  application.xml
   │  ejb-jar.xml
   │  jboss.xml
   │
   ├─powerwind
   │  ClientServlet.java
   │  Hello.java
   │  HelloBean.java
   │  HelloHome.java
   │
   └─WEB-INF
      jboss-web.xml
      web.xml

核心 Java 原始碼

1. Remote 介面 Hello.java

package powerwind;

import java.rmi.RemoteException;
import javax.ejb.EJBObject;

public interface Hello extends EJBObject {
    public String sayHello() throws RemoteException;
}

2. Home 介面 HelloHome.java

package powerwind;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;

public interface HelloHome extends EJBHome {
    public Hello create() throws RemoteException, CreateException;
}

3. Bean 實作類 HelloBean.java

package powerwind;

import java.rmi.RemoteException;
import javax.ejb.*;

public class HelloBean implements SessionBean {

    private SessionContext context;

    public void ejbCreate() throws EJBException, RemoteException {}
    public void ejbActivate() throws EJBException, RemoteException {}
    public void ejbPassivate() throws EJBException, RemoteException {}
    public void ejbRemove() throws EJBException, RemoteException {}

    public void setSessionContext(SessionContext newContext) throws EJBException {
        context = newContext;
    }

    public String sayHello() throws EJBException {
        return "Hello from ejb";
    }
}

4. 客戶端 Servlet ClientServlet.java

package powerwind;

import java.io.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import javax.servlet.*;
import javax.servlet.http.*;

public class ClientServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        String message = null;

        try {
            InitialContext ic = new InitialContext();
            Object obj = ic.lookup("HelloEJB");
            HelloHome home = (HelloHome) PortableRemoteObject.narrow(obj, HelloHome.class);
            Hello hello = home.create();
            message = hello.sayHello();
        } catch (Exception e) {
            e.printStackTrace();
        }

        out.println(message);
        out.flush();
        out.close();
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

部署描述檔

ejb-jar.xml (EJB 標準描述檔)

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar>
  <enterprise-beans>
    <session>
      <ejb-name>HelloEJB</ejb-name>
      <home>powerwind.HelloHome</home>
      <remote>powerwind.Hello</remote>
      <ejb-class>powerwind.HelloBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>
    </session>
  </enterprise-beans>
  <assembly-descriptor>
    <container-transaction>
      <method>
        <ejb-name>HelloEJB</ejb-name>
        <method-name>*</method-name>
      </method>
      <trans-attribute>Required</trans-attribute>
    </container-transaction>
  </assembly-descriptor>
</ejb-jar>

jboss.xml (JBoss 專用綁定)

<?xml version="1.0" encoding="UTF-8"?>
<jboss>
  <enterprise-beans>
    <session>
      <ejb-name>HelloEJB</ejb-name>
      <jndi-name>HelloEJB</jndi-name>  <!-- 客戶端 lookup 使用此名稱 -->
    </session>
  </enterprise-beans>
</jboss>

application.xml (EAR 封裝描述檔)

<?xml version="1.0" encoding="UTF-8"?>
<application>
  <display-name>HelloEJBApp</display-name>
  <module>
    <ejb>hello-ejb.jar</ejb>
  </module>
  <module>
    <web>hello-web.war</web>
  </module>
</application>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
  <servlet>
    <servlet-name>ClientServlet</servlet-name>
    <servlet-class>powerwind.ClientServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ClientServlet</servlet-name>
    <url-pattern>/client</url-pattern>
  </servlet-mapping>
</web-app>

jboss-web.xml

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
  <context-root>hello</context-root>
</jboss-web>

Ant 建構腳本 build.xml 關鍵片段

<property name="jboss.home" value="D:/jboss-4.0.5"/>
<property name="dist.dir" value="dist"/>

<target name="package-ear" depends="compile,war">
  <ear destfile="${dist.dir}/HelloEJB.ear" appxml="src/META-INF/application.xml">
    <fileset dir="${dist.dir}" includes="hello-ejb.jar,hello-web.war"/>
  </ear>
</target>

<target name="deploy" depends="package-ear">
  <copy file="${dist.dir}/HelloEJB.ear" 
        todir="${jboss.home}/server/default/deploy" overwrite="true"/>
</target>

部署與驗證步驟

  1. 啟動 JBoss:run.bat -c default (或 all 配置)
  2. 執行 Ant 部署:ant deploy,EAR 複製至 server/default/deploy
  3. 觀察 JBoss 控制台日誌,確認 HelloEJB 綁定至 JNDI HelloEJB
  4. 瀏覽器訪問 https://localhost:8080/hello/client
  5. 頁面顯示:「Hello from ejb」即成功

EJB 2.x 核心概念回顧

概念說明本例體現
Home 介面生命週期管理 (create/find/remove)HelloHome.create()
Remote 介面業務方法定義,RMI-IIOP 分散式語義Hello.sayHello()
Bean 類實作 SessionBean/EntityBean 介面,容器回調方法ejbCreate/Activate/Passivate/Remove
PortableRemoteObject.narrowRMI-IIOP 類型安全轉換,跨 JVM 必須Servlet 中 lookup 後 narrow
JNDI 名稱jboss.xml 指定綁定名,客戶端 lookup 關鍵HelloEJB
容器管理事務 (CMT)assembly-descriptor 宣告事務屬性Required (預設)

常見部署錯誤與解決

  1. NameNotFoundException: HelloEJB not bound → 檢查 jboss.xml jndi-name 與 Servlet lookup 名稱一致
  2. ClassCastException on narrow → 確認 ejb-jar.xml home/remote 介面全限定名正確
  3. EJB not found in JNDI → EAR 結構錯誤,ejb-jar.xml 應在 EJB JAR 的 META-INF 目錄
  4. TransactionRolledbackException → 業務方法拋出 RuntimeException 導致容器回滾

總結

EJB 2.x 雖需撰寫 Home/Remote 介面、Bean 類、多個 XML 描述檔、處理 RMI-IIOP 窄化轉換,但其嚴格的元件模型、容器管理服務 (事務、安全、並發、持久化) 為企業級分散式應用提供了強有力的結構保證。本範例展示了最小化的 Stateless Session Bean 完整生命週期。對於維護存量 EJB 2.x 系統的開發者,熟練掌握此部署流程與除錯技巧仍是核心基本功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved