我认为您想从 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 对象的生命周期接口。所有主接口都必须扩展标准接口 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 方法。
无状态会话 bean 必须准确定义一个不带参数的 方法。
...
throws 子句必须包含 javax.ejb.CreateException
...
如果您的 Home 接口扩展 javax.ejb.EJBHome,则 throws 子句必须包含 java.rmi.RemoteException。如果它扩展了 javax.ejb.EJBLocalHome,则不得包含 java.rmi.RemoteException。
...
有状态会话 bean 的每个创建方法都必须命名为 create,并且它
必须匹配会话中定义的 Init 方法或 ejbCreate 方法之一
豆类。匹配的 ejbCreate 方法必须具有相同的参数数量和类型。无状态会话 bean 的创建方法必须命名为 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 的类中必须有一个匹配的方法。匹配方法必须有:
- 同名
- 相同数量和类型的参数,以及相同的返回类型。
- 会话匹配方法的 throws 子句中定义的所有异常
bean 类必须在本地接口方法的 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)
- 无论您使用的是 JBoss,都将 /server/default/lib(包含 jar 文件以便您检索 EJB 的)jar 文件添加到您的 Java 应用程序(我不知道 Sun 应用程序服务器中的哪个目录)
- 上面的实现代码
现在创建另一个战争项目
- 添加我们刚刚在上面创建的项目并添加/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();
问候,