我认为您想从 Sun Application Server 中的 Web 应用程序访问 EJB 应用程序(称为 EJB 模块),对吗?
好了,走吧。
当您将 EJB 部署到应用程序服务器中时,应用程序服务器会为其提供一个地址 - 称为全局 JNDI 地址 - 作为您访问它的一种方式(类似于您的地址)。它从一个应用程序服务器变为另一个。
在 JBoss Application Server 中,您可以在以下地址中看到全局 JNDI 地址(启动后)
http://127.0.0.1:8080/jmx-console/HtmlAdaptor
在 Sun Application Server 中,如果要查看全局 JNDI 地址(启动后),请执行以下操作
在以下地址访问管理控制台
http://127.0.0.1:4848/asadmin
并点击JNDI 浏览
如果您的 EJB 未在此处注册,则说明有问题
EJB 有两种形式:EJB 2.1 和 EJB 3.0。那么区别是什么呢 ?
好,好,好……
让我们从 EJB 2.1 开始
- 创建主页界面
它定义了创建、销毁和查找本地或远程 EJB 对象的方法。它充当 EJB 对象的生命周期接口。所有 home 接口都必须扩展标准接口 javax.ejb.EJBHome - 如果您使用远程 ejb 对象 - 或 javax.ejb.EJBLocalHome - 如果您使用本地 EJB 对象。
// a remote EJB object - extends javax.ejb.EJBHome
// a local EJB object - extends javax.ejb.EJBLocalHome
public interface MyBeanRemoteHome extends javax.ejb.EJBHome {
MyBeanRemote create() throws javax.ejb.CreateException, java.rmi.RemoteException;
}
Application Server 将创建 Home 对象作为您获取 EJB 对象的一种方式,仅此而已。
请注意以下事项
会话 bean 的远程主接口必须定义一个或多个 create<METHOD> 方法。无状态会话 bean 必须准确定义一个没有参数的 <METHOD> 方法。
...
throws 子句必须包括 javax.ejb.CreateException
...
如果您的 Home 接口扩展 javax.ejb.EJBHome,则 throws 子句必须包含 java.rmi.RemoteException。如果它扩展 javax.ejb.EJBLocalHome,则不得包含 java.rmi.RemoteException。
...
有状态会话 bean 的每个创建方法必须命名为 create<METHOD>,并且它必须匹配会话 bean 类中定义的 Init 方法或 ejbCreate<METHOD> 方法之一。匹配的 ejbCreate<METHOD> 方法必须具有相同的参数数量和类型。无状态会话 bean 的 create 方法必须命名为create但不需要有匹配的“ejbCreate”方法。
现在创建一个业务接口,以便在我们的 EJB 对象中定义业务逻辑
// a remote EJB object - extends javax.ejb.EJBObject
// a local EJB object - extends javax.ejb.EJBLocalObject
public interface MyBeanRemote extends javax.ejb.EJBObject {
void doSomething() throws java.rmi.RemoteException;
}
现在注意以下事项
如果您使用远程 EJB 对象,远程接口方法不得公开本地接口类型或本地主接口类型。
...
如果您的 Home 接口扩展 javax.ejb.EJBObject,则 throws 子句必须包含 java.rmi.RemoteException。如果它扩展 javax.ejb.EJBLocalObject,则不得包含 java.rmi.RemoteException。
现在我们的 EJB
public class MyBean implements javax.ejb.SessionBean {
// why create method ? Take a special look at EJB Home details (above)
public void create() {
System.out.println("create");
}
public void doSomething() throws java.rmi.RemoteException {
// some code
};
}
现在注意以下事项
它必须实现 javax.ejb.SessionBean。它定义了四种方法——上面未显示:setSessionContext、ejbRemove、ejbPassivate 和 ejbActivate。
注意我们的 bean没有实现我们的业务接口,因为 EJB 规范说:
对于接口中定义的每个方法,会话 bean 的类中必须有一个匹配的方法。匹配方法必须有:
- 同名
- 相同数量和类型的参数,以及相同的返回类型。
- 会话bean类的匹配方法的throws子句中定义的所有异常都必须在本地接口的方法的throws子句中定义。
您必须根据以下声明声明一个 ejb-jar.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd" version="2.1">
<enterprise-beans>
<session>
<ejb-name>HelloWorldEJB</ejb-name>
<home>br.com.MyBeanRemoteHome</home>
<remote>br.com.MyBeanRemote</remote>
<local-home>br.com.MyBeanLocalHome</local-home>
<local>br.com.MyBeanLocal</local>
<ejb-class>br.com.MyBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
如果您没有本地 EJB 对象,请从上面的部署描述符中删除
<local-home>br.com.MyBeanLocalHome</local-home>
<local>br.com.MyBeanLocal</local>
如果您没有远程 EJB 对象,请从上面的部署描述符中删除
<home>br.com.MyBeanRemoteHome</home>
<remote>br.com.MyBeanRemote</remote>
并放入 META-INF 目录
我们的 jar 文件将包含以下内容
/META-INF/ejb-jar.xml
br.com.MyBean.class
br.com.MyBeanRemote.class
br.com.MyBeanRemoteHome.class
现在我们的 EJB 3.0
// or @Local
// You can not put @Remote and @Local at the same time
@Remote
public interface MyBean {
void doSomething();
}
@Stateless
public class MyBeanStateless implements MyBean {
public void doSomething() {
}
}
没有其他的,
在 JBoss 中放入 jar 文件
<JBOSS_HOME>/server/default/deploy
在 Sun Application Server 访问(启动后)管理控制台
http://127.0.0.1:4848/asadmin
并访问 EJB 模块以部署您的 ejb-jar 文件
由于您在 NetBeans 中部署应用程序时遇到一些问题,我建议如下
- 创建一个简单的Java库PROJECT(一个没有main方法的简单jar)
- 添加 /server/default/lib(包含 jar 文件,以便您检索 EJB 的)jar 文件到您的 Java 应用程序,无论您使用的是 JBoss(我不知道 Sun 应用程序服务器中的哪个目录)
- 实现上面的代码
现在创建另一个战争项目
- 添加我们刚刚在上面创建的项目并添加 <JBOSS_HOME>/client(包含 jar 文件以便访问我们的 EJB)。同样,我不知道 Sun Application Server 中的哪个目录。查看它的文档。
- 看它的全局映射地址如答案顶部所示
并在您的 Servlet 或其他东西中实现以下代码,无论您使用的是 JBoss
public static Context getInitialContext() throws javax.naming.NamingException {
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
p.put(Context.URL_PKG_PREFIXES, " org.jboss.naming:org.jnp.interfaces");
p.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");
return new javax.naming.InitialContext(p);
}
或者以下无论您是否使用 Sun Application Server - 将文件 appserv-rt.jar(我不知道 Sun Application Server 中的哪个过去包含 appserv-rt.jar)放在您的类路径中
public static Context getInitialContext() throws javax.naming.NamingException {
return new javax.naming.InitialContext();
}
为了在我们的 Servlet 或其他东西中访问您的 EJB
MyBeanRemote myBean = (MyBeanRemote) getInitialContext().lookup(<PUT_EJB_GLOBAL_ADDRESS_RIGHT_HERE>);
myBean.doSomething();
问候,