从单独的 Web 应用程序的 POJO class 引用 EJB 本地主页

Referencing EJB Local home from a POJO class of a separate web application

我正在尝试将应用程序中的 2 个 EJB 模块从 EJB2.1 移植到 EJB3.0。我正在使用 Eclipse Kepler IDE 并使用 EJB3.0 配置重新生成会话 bean。我没有使用 ejb-jar.xml,因为在 EJB 3.0 中这应该是多余的。我改为使用注释将我的 bean 标记为无状态并指定本地和本地 Home 接口。我仍然保留 Local Home 接口,因为我希望我的项目的基本结构与 EJB2.1 中的相似。迁移时,我还取消了 EJB 的 xml 绑定。

我们正在使用 WAS 7 应用程序服务器进行部署,虽然 EJB 成功部署且没有错误,但我在从一个单独的 POJO class 查找我的 Local Home 接口时遇到命名异常它需要不同的 Web 应用程序。我基本上想在引用 EJB Local Home 后调用 Local Home 接口的 create() 方法。添加以下代码示例:

会话 Bean:

@Stateless
@Local(AccessLDAPSessionLocal.class)
@LocalHome(AccessLDAPSessionLocalHome.class)
public class AccessLDAPSessionBean implements AccessLDAPSessionLocal {
//Business Logic
}

本地接口:

public interface AccessLDAPSessionLocal {
//business Interface
}

本地主页界面:

public interface AccessLDAPSessionLocalHome extends EJBLocalHome {

public AccessLDAPSessionLocal create() throws CreateException;

}

Pojo class 引用本地主页界面:

public static AccessLDAPSessionLocal getAccessLDAPSessionBean() throws NamingException, CreateException {
    if (accessLDAPSessionBean == null) {
    InitialContext context = new InitialContext();
    Object obj = context.lookup("java:global/AccessLDAP/AccessLDAPSessionBean!com.ibm.asset.hrportal.core.ejb.ldap.AccessLDAPSessionLocalHome");
        accessLDAPSessionBean = ((AccessLDAPSessionLocalHome) obj).create();
    }
    return accessLDAPSessionBean;
}

另外,我的 Local 和 Local Home 接口位于我用作 jar 文件的 EJB 客户端中,而我的会话 Bean 位于用作 EAR 的实际 EJB 中。

以下是我收到的错误:

NamingException::javax.naming.NameNotFoundException: Name global not found in context "java:".

我是否缺少某些配置导致 JNDI 查找失败?任何帮助将不胜感激。提前致谢。

我认为您查找 ejb 的方式不正确。 JNDI 名称类似于 "java:comp/env/"。 ejb-ref-name 将是您的 web.xml

的一部分

此外,在进行查找之前,您需要将 providerURL 和 factoryName 提供给上下文对象。

WebSphere Application Server 7.0 只是 EJB 3.0 的一个实现,但是 java:global 命名空间直到 EJB 3.1 才被添加,而 EJB 3.1 直到 8.0 才在 WebSphere Application Server 中实现。对于所有 EJB 3.0 实现,您将需要查找特定于供应商的绑定名称。您可以通过查看 SystemOut.log 中的 CNTR0167I 消息找到 WebSphere Application Server 绑定名称。如果您想自定义此绑定名称,请参阅知识中心的 EJB 3.0 application bindings overview 主题。

无论如何,通过绑定名称直接查找 EJB 并不是最佳做法。相反,您应该使用 EJB 引用。在 EJB 3.0 中,这意味着在 EE 托管对象(例如 servlet 或另一个 EJB)中使用这样的注释:

@EJB 
private AccessLDAPSessionLocalHome home;

在这种情况下,EJB 容器需要在包含 EJB 引用的同一应用程序中找到目标 EJB,因此您无需为 EJB 引用显式配置目标绑定名称。

如果您需要从实用程序 class 而不是 EE 托管 class 访问 EJB 引用,则使用托管 class 上的名称声明 EJB 引用(例如作为 servlet 或另一个 EJB),并从实用程序 class:

中查找它
@EJB(name = "ejb/accessHome", beanInterface = AccessLDAPSessionLocalHome.class)
public class MyServlet { ... }

public class MyUtility {
    ...
    InitialContext context = new InitialContext();
    Object obj = context.lookup("java:comp/env/ejb/accessHome");
    ...
}

您可以使用 @EJBs 注释在同一托管 EE class 上配置多个此类 EJB 引用:

@EJBs({
    @EJB(name = "ejb/accessHome", beanInterface = AccessLDAPSessionLocalHome.class),
    @EJB(name = "ejb/other" beanInterface = Other.class)
})
public class MyServlet { ... }

如果您的 EJB 打包在单独的 EAR 中,请注意这不是可移植配置。请参阅知识中心 EJB modules 主题的 "Local client views" 部分。此外,您需要为 EJB 引用显式配置绑定名称。