1

我有一个.ear包含几十个 EJB jar 文件的文件。

每个 EJB jar 文件中都有几十个 EJB。

每个 EJB 中都有@EJB引用,没有其他信息(没有name属性等)。

目前一切正常:碰巧对于任何给定的@EJB带注释的注入目标,文件中都存在一个具体的 EJB.ear来填充插槽。

由于各种原因,我需要引入更多包含 EJB 的 EJB jar 文件,这些 EJB 也可以填充其中的一些插槽。

因此,我需要告诉我的 Java EE 容器将哪个 EJB 注入到哪个插槽中存在冲突。

我熟悉ejb-jar.xml用于覆盖 EJB 引用的部署描述符机制,但如果这是我唯一的办法,我正在考虑更改可能成千上万的这些条目。

我注意到在application.xml模式版本 6中也支持其中的<ejb-local-ref>元素,这以某种抽象的方式是我想要的。但我无法弄清楚如何利用这些元素来做我想做的事。

在某个抽象的完美世界中,我想以某种方式在某个地方说,“嘿,Java EE 容器,当你看到这样的@EJB-annotated 字段时:

@EJB
SomeType bean;

...请注入其中的beanNameEJB fred。在这个应用程序的任何地方。”我该怎么做?

4

2 回答 2

4

没有标准的方法可以做到这一点,据我所知,没有通用的特定于供应商的方法来做到这一点。

这是我试图在 EJB 3.1 中为 EJB 和 JPA refs 加入的东西:如果注入点使用默认规则工作,因为只有一个SomeTypebean,但有一天SomeType会添加第二个 bean……直言不讳,你重新冲洗 :)@PersistenceContext@PersistenceUnitrefs也存在这个问题。这个想法是/是有一些“这是标准部署描述符中的默认SomeType选项实现,并使人们摆脱这些情况。

我们仍应将其纳入规范。如果这是您的问题,我将重新发布该提案,如果您可以跟进有关这对您来说有多大的噩梦的信息,我几乎可以保证我们将为 EJB.next 解决此问题。

获取您的规范 xml

目前,一种可能的方法是在 TomEE 中使用 flag 临时部署此 ear openejb.descriptors.output=true。TomEE/OpenEJB 实际上会为您提供应用程序的所有有效部署描述符。如果您的应用程序与您所说的一样大,可以为您节省几个小时或几天。在内部,我们 1) 读入部署描述符,2) 使用注释“填写”部署描述符。结果是我们有一个树,它是每个 EJB 模块的“元数据”规范集。设置openejb.descriptors.output=true标志后,我们会将这些 ejb-jar.xml 文件中的每一个写入磁盘并记录位置。

一旦您掌握了 ejb-jar.xml 文件,您就可以随意修改并返回到 GlassFish,也许会有更好的运气。

覆盖:控制您的引用计数

至于如何在 Java EE 中实际管理这一点,您必须了解如何成功地覆盖引用。在注释引用如何转换为 xml 方面需要了解一些关键信息。目标是有 1 个参考而不是 N。

当您的参考文献未命名时:

package org.some.awesome.code;

public class Foo {

    @EJB
    SomeType orange;

...有一个固定规则,它的默认名称必须是org.some.awesome.code.Foo/orange. 类名和包成为名称的一部分,以便为您提供最细粒度的覆盖控制。以下 xml 将覆盖此引用:

<ejb-local-ref>
  <ejb-ref-name>org.some.awesome.code.Foo/orange</ejb-ref-name>
  <local>org.some.awesome.code.SomeType</local>
  <ejb-link>Fred</ejb-link>
</ejb-local-ref>

此引用现在将链接到SomeType具有 beanName 'Fred' 类型的 EJB。

这样做的缺点是,如果您有 100 个这样的引用并且想要全部更改它们,则需要 xml 中的 100 个声明才能这样做。

如果不更改代码,就无法解决这个问题——这就是我的“将其用作默认值”建议的价值所在,它允许一个 xml 更改来处理所有 100 个案例而无需更改代码。就像能够通过部署描述符说“当我在我的代码中不具体时,我的意思是使用 X”一样简单。

也许通过仅使用类型在 xml 中声明覆盖是合法的,如下所示:

<ejb-local-ref>
  <local>org.some.awesome.code.SomeType</local>
  <ejb-link>Fred</ejb-link>
</ejb-local-ref>

如前所述,这目前是不合法的。

更改您的代码

有一些代码更改方法可用,但其中之一是为每个@EJBref 赋予相同的名称。然后你最终会得到 1 个引用而不是 N。

package org.some.awesome.code;

public class Foo {

    @EJB(name "purple")
    SomeType orange;

这里引用的名称是明确给出的,因此在 xml 中覆盖它可以更简单地完成,如下所示:

<ejb-local-ref>
  <ejb-ref-name>purple</ejb-ref-name>
  <local>org.some.awesome.code.SomeType</local>
  <ejb-link>Fred</ejb-link>
</ejb-local-ref>

如果有 100 个@EJB(name="purple")引用,则所有引用都将被上述声明覆盖。

结论

简短的回答,目前没有简单的出路。您正在查看大量的 xml 或大量的代码更改。

从长远来看,我们有望改进规范的这一部分,以便人们在超出默认匹配规则时不会受到惩罚。

于 2013-07-26T18:54:36.573 回答
0

我目前正在解决同样的问题。我正在研究覆盖 JNDI 上下文的可能性,以便它提供标准实例之外的其他实例。您只需将系统属性java.naming.factory.initial(例如在 jndi.properties 中)设置为您的实现并将实现放在根类路径中。然后在工厂中使用重写的查找方法创建自己的上下文版本。听起来很简单,但我已经为此纠结了好几天。

于 2014-08-08T09:07:49.487 回答