【问题标题】:Call EJB3 Local bean through Remote bean from external JVM通过远程 bean 从外部 JVM 调用 EJB3 本地 bean
【发布时间】:2011-12-29 21:16:06
【问题描述】:

在使用 EJB 方面没有太多经验,我遇到了以下问题,希望你们中的某个人能提供帮助。

假设以下情况:已定义一组@Local bean 以提供对数据库的访问。这些 bean 非常简单,并且部署在 应用服务器 A (Weblogic 10.3.3) 上。我们希望通过 remote 提供对这些 local bean 的访问,并且由于我们已经设置了一个“服务”模块来提供对我们服务的外部访问,我们的想法是创建一个新的@Remote 服务,该服务使用上述local bean(通过@EJB 注入)。这些服务bean也部署在应用服务器A上。例如:

@Local
public interface DatabaseBeanLocal { doStuff(); }

@Stateless(name = "ejb/DatabaseBean", mappedName = "DatabaseBean")
public class DatabaseBean implements DatabaseBeanLocal { doStuff() { ... } ; }

@Remote
public interface ServiceBean { doSomeOtherStuff(); }

@Stateless
public class ServiceBeanImpl implements ServiceBean
{
    @EJB(name = "ejb/DatabaseBean", mappedName = "DatabaseBean")
    private DatabaseBeanLocal myDatabaseBean;

    ... methods etc. ...

}

实际使用这些remote bean 的客户端实际上运行在不同的应用服务器上; 应用服务器 B(也是 Weblogic 10.3.3)。当我们从客户端查找ServiceBean bean 时,它工作正常。但是,当我们在其上调用需要访问DatabaseBean 的方法时,调用失败。 Weblogic 服务器说它找不到 DatabaseBean 接口的 bean。

我的问题:这种设置是否可行?换句话说:Weblogic(或另一个容器)是否会将本地 bean 注入远程 bean,以便客户端获取能够在本地 bean 上调用操作的远程 bean 实例(我假设不是,但我在问无论如何要确定)?

如果没有,我想我们别无选择,只能跳过服务层并通过@Remote 直接访问上面的DatabaseBean 示例。

更新 1

在做了一些测试之后,简单地将上面的DatabaseBean 定义为@Remote 而不是@Local “修复”了这个问题。当然,这并不是真正的修复,因为它会远程调用DatabaseBean,这很荒谬,因为它与服务位于同一模块中。我开始怀疑用远程 EJB 包装本地 EJB 根本是不可能的。

更新 2

到目前为止我们发现了什么:

  • 到目前为止,我们还无法手动注入本地 EJB,因为我们实际上无法在运行时找到它。
  • Weblogic 显然不包括 JNDI 树中的本地 EJB。
  • 从部署它的 AS 外部调用 ServiceBean 仍然无法正常工作,因为对本地 EJB 的依赖永远不会被解析,或者在客户端解析,这意味着它找不到。

【问题讨论】:

  • 你配置了DatabaseBean的EJB(实现)了吗?
  • 我更新了代码以包含更多细节。

标签: java ejb-3.0 weblogic-10.x


【解决方案1】:

本地意味着 EAR 本地而不是 AS。

您的本地和远程 Bean 必须在同一个 EAR 中(不仅在同一个 AS 中)。是吗?

-- 编辑--

嗯.. 如果它们在同一个 EAR 中,那么它应该可以工作。 IE。回答您的问题“这样的设置是否可行?” 是的。

不幸的是,现在我们谈论的是纯粹而简单的调试。我要做的第一件事是尝试检查本地 bean(我猜是DatabaseBean)是否在 WebLogic 中使用 WebPhere UTC 等效项实际注册并工作(我从未在 WebLogic 中工作过)。我可以列出 100 件其他事情,您可以检查更多日志/跟踪/症状,但是,这就是调试的方式。

【讨论】:

  • 是的,他们是。我们所有的模块(用于应用服务器 A)都打包到同一个 EAR 中,然后进行部署。
  • 我的印象是,当我在应用程序服务器 B 上调用远程服务时,应用程序服务器 B 将尝试解析本地 bean 的 @EJB 注入。这显然不起作用,因为本地 bean 没有部署在 B 上,而是部署在 A 上。你确定这应该工作吗?
  • @pHk 我不确定你所说的“注射”是什么意思,我自己做了这个;不同之处在于 AS-B 是一个独立的客户端,它是 EJB-2 而不是 3。同样只是理论上,当您在远程 SLSB 的 impl(常见情况)中使用本地 EntityBean 时,您仍然可以从 AS 外部调用 SLSB。
  • 我们整天都在试验这个,但我们无法让它在 Weblogic 10.3.3 上运行。似乎 Weblogic EJB 容器拒绝/无法在远程服务中正确注入本地 bean。更重要的是,本地 EJB甚至不包括在 Weblogic 的 JNDI 树中。这可能是 Weblogic 问题而不是 EJB 问题。
【解决方案2】:

设法解决了这个问题。以下配置适用于 Weblogic 10.3.3,并允许 remote EJB 使用 local EJB,这样可以从任何地方调用远程 EJB。

最终——经过大量测试——诀窍显然是为@EJB 注释指定beanName 值,用于将本地bean 标记为远程bean 的依赖项。呵呵!

部署

  • @Local EJB 部署在 EAR-1 中的 AS-A 上(在它自己的模块/JAR 中)
  • @Remote EJB 部署在 EAR-1 中的 AS-A 上(在它自己的模块/JAR 中)
  • 调用远程服务的客户端代码部署在其自己的 EAR 存档中的 AS-B 上

注释

local EJB 是一个非常简单直接的 EJB bean,具有以下接口和实现:

@Local
public interface LocalBeanLocal {
    // Implementation omitted
}

@Stateless(name = "LocalBean")
public class LocalBean implements LocalBeanLocal {
    // Implementation omitted
}

remote EJB 还是一个相对简单的 EJB bean,只是它依赖于 LocalBean。这种依赖是通过@EJB注解来表达的;但似乎 Weblogic 需要 beanName 属性才能正确解决此依赖关系。 没有beanName 属性,调用远程EJB 对我们不起作用(从某种意义上说,当涉及本地bean 时总会出现某种错误)!

@Remote
public interface RemoteBeanRemote {
    // Implementation omitted
}

@Stateless(name = "RemoteBean")
public class RemoteBean implements RemoteBeanRemote {

    @EJB(beanName = "LocalBean")
    private LocalBeanLocal localBean;

    // Implementation omitted
}

这里显然很重要的是远程服务依赖声明 (@EJB(beanName = "LocalBean")) 中的 beanName 属性应该与本地 bean 实现中定义的 bean 名称 (@ 987654333@).

查找

获取对远程 EJB 的引用是通过传统方式完成的,似乎没有特定要求。在我们的例子中,我们通过 JNDI 查找远程服务。

【讨论】:

  • "远程服务依赖声明 (...) 中的 beanName 属性应该与本地 bean 实现中定义的 bean 名称具有相同的值 (...)" - 这听起来很合理对我来说 - 在实现中定义 bean 名称,然后注入命名为 so 的 bean,因此这些值必须相等。但是,我很感兴趣为什么您必须首先指定它。你在不同的应用服务器上测试过吗?
  • 不,我们没有——我们目前只能访问 Weblogic。完全有可能使用 JBoss AS,我们不需要指定属性,但我不知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-15
  • 2012-01-02
相关资源
最近更新 更多