java - 揭秘 EJB 注释和注入(inject)

标签 java jakarta-ee ejb jndi tapestry

我目前对 Glassfish 3.1.2.2 处理 EJB 的方式感到困惑。

我有一个 OSGi 项目,它由许多 OSGi 包(jar)组成。此外,还有一些 WAR,包括 Tapestry Web 应用程序。

在一个这样的包中,我们将其称为“interfaces.jar”,我定义了一个接口(interface):

public interface MyInterface() {
    public static final String JNDI_NAME = "java:global/MyInterface";
    void myMethod();
}

该接口(interface)的实现如下,它包含在包“beans.jar”中:

@Stateless
@EJB(name = MyInterface.JNDI_NAME, beanInterface = MyInterface)
public class MyBean implements MyInterface() {
    void myMethod() {
        ...
    }
}

我通过 JNDI 查找从我的 Tapestry WAR 应用程序调用它:

InitialContext.doLookup(MyInterface.JNDI_NAME);

现在,我正在阅读 EJB 3.1 规范,它说我可以执行以下场景之一:

  1. 接口(interface)有@Local注解; EJB正在实现这个接口(interface)。
  2. Interface是一个没有注解的普通Java接口(interface);带有@Local注释的EJB正在实现它。
  3. Interface是一个没有注解的普通Java接口(interface); EJB 正在实现它。
  4. Interface是一个没有注解的普通Java接口(interface);带有 @Local 注释的 EJB 未实现它。
  5. EJB 没有任何特殊注释。

所以,通过消除:

  1. 我的界面上没有@Local
  2. 我在 EJB 上没有 @Local
  3. 似乎有点正确
  4. 我在 EJB 上没有 @Local
  5. 我的 EJB 上有 @EJB 注释

所以,看来是情况 3:

"Because it’s the only implemented interface of the EJB, a container assumes that it must be a local business interface."

现在,有几个问题:

  1. 由于没有本地或远程注释,我的接口(interface)是本地接口(interface)还是远程接口(interface)?
  2. 如果是本地的,我应该能够使用 @EJB 注解注入(inject)它,但是失败了?
  3. 如果是远程的话,是不是不符合上面几行的解释?
  4. 如果我添加 @Local@Remote,并执行 JNDI 查找,我会收到命名异常,NPE 告诉我该 JNDI_NAME 下没有任何内容。这怎么可能?
  5. @EJB(name = ..., beanInterface = ...) 在 bean 类上到底做什么?它如何与 @Local@Remote 注解交互?

最佳答案

1.) 首先,让我们看看没有“不必要的”@EJB 注释的示例

@Stateless
public class MyBean implements MyInterface() {
    void myMethod() {
        ...
    }
}

您现在可以清楚地看到,EJB 仅实现一个接口(interface)。正如您在第 3 点中提到的,“Interface 是一个没有注释的普通 Java 接口(interface);EJB 正在实现它。”,因此 MyInterface 是 MyBean EJB 的本地业务接口(interface)。

2.)

您使用错误的 JNDI 名称进行查找:

@Stateless
public class MyBean implements MyInterface() {
    ...

EJB 的全局 JNDI 名称:

java:global[/app-name][/module-name]/MyBean[!interface-name]

接口(interface)名称是“MyInterface”,但如果您的 bean 没有其他业务接口(interface),那么它是可选的,就像这里一样,因此您可以跳过它。

对于 OSGI,您必须弄清楚您的 bean 的应用程序名称和模块名称是什么。 在简单的 EJB 应用程序中,应用程序名称是 .ear 文件的名称,模块名称是 .war/.jar 文件的名称。如果你的模块没有封装在ear中,application-name可以跳过。

例如:

new InitialContext().lookup("java:global/myModuleName/MyBean");

5.)

@Stateless
@EJB(name = "MyInterface", beanInterface = MyInterface.class)
public class MyBean implements MyInterface() {
    void myMethod() {
        ...
    }
}

此处,@EJB 注释创建一个 EJB 并将对其的引用放入环境命名上下文 (ENC) 中。因此它对 MyBean EJB 不执行任何操作,只是用一个新条目扩展其 ENC。

因此,您可以从当前 bean 的业务方法中查找该新条目:

    void myMethod() {
        new InitialContext().lookup("java:comp/env/MyInterface")
    }

您可以通过“java:comp/env/”JNDI 名称找到 bean 的 ENC。

如您所见,name 参数定义 ENC 中条目的名称。

beanInterface定义了创建的Bean的业务接口(interface)。如果Bean有更多的业务接口(interface),那么你还必须定义beanName,以便容器可以确定你要创建哪个Bean。

您可以在此处阅读有关此主题的信息:http://thegreyblog.blogspot.hu/2010/09/introduction-to-ejb-30-injection-and.html

关于java - 揭秘 EJB 注释和注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22840851/

相关文章:

java - 如何阻止 JFace 组合框在窗口调整大小时调整大小?

java - Google App Engine 在构建 Web 应用程序方面有多好?

java - WebLogic,选择JDK

java - 将 Bean 类注入(inject) JBOSS 7.1 中连续运行的 ServletContextListener

java - 我可以向 JTable 列标题添加按钮吗?

java - 实现 Java Swing 工作线程时出现问题

java - Java EE 中的抽象类和 Servlet

java - 决定请求类的类型?

oracle - EJB 事务与 Oracle 事务

java - 无接口(interface) View 和 @Local-ejbs 在相同或不同的 JVM/服务器中?