2014-04-03 121 views
1

我目前对Glassfish 3.1.2.2处理EJB的方式感到困惑。Demistifying EJB注释和注入

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

在一个这样的包,我们称之为“interfaces.jar”,我有一个接口定义:

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

该接口的实现是以下内容,它包含在捆绑“beans.jar” :

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

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

InitialContext.doLookup(MyInterface.JNDI_NAME); 

现在,我正在阅读EJB 3.1规范,它说我可以采用以下方案之一:

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

因此,通过消除:

  1. 我没有@Local接口上
  2. 我没有@Local对EJB
  3. 似乎有点权
  4. 我不t在EJB上拥有@Local
  5. 我在我的EJB上有@EJB注释

因此,它似乎是情况3:

“因为它是唯一实现的EJB接口,容器假定它必须是本地业务接口。”

现在,有几个问题:

  1. 是我的接口本地或远程的一个,因为没有本地或远程的注释?
  2. 如果是本地的,我应该可以注入@EJB注释,但它会失败吗?
  3. 如果它很远,它不符合上面几行的解释吗?
  4. 如果我添加@Local@Remote,并执行JNDI查找,我会得到一个命名异常,NPE告诉我这个JNDI_NAME下没有任何东西。这怎么可能?
  5. @EJB(name = ..., beanInterface = ...)在bean类上做了什么,它如何与@Local@Remote注释交互?
+0

我很抱歉,出现了不良复制粘贴的情况。 MyInterface是接口,MyBean是实现它的ejb – Lopina

回答

1

1) 首先,让我们看看你的榜样没有“多余” @EJB批注

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

现在,您可以清楚地看到,该EJB实现了只有一个接口。正如你在第三点提到的那样,“Interface是一个没有注释的普通Java接口; EJB正在实现它”,所以MyInterface是MyBean EJB的本地业务接口。

2)

您的查询使用错误的JNDI名称:

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

您的EJB的全局JNDI名称:

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

接口,名称为 “MyInterface的” ,但是如果没有其他的bean的业务接口,这是可选的,所以你可以跳过它。

在OSGI的情况下,您必须弄清楚bean的应用程序名和模块名是什么。 在一个简单的EJB应用程序中,application-name是.ear文件的名称,module-name是.war/.jar文件的名称。如果您的模块未包装在耳朵中,应用程序名称可以跳过。

因此,例如:

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即可。

因此,从目前的豆你可以查找为新进入的业务方法:

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

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

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

beanInterface定义了创建的Bean的业务接口。如果Bean有更多的业务接口,那么你也必须定义beanName,所以容器可以确定你想创建的唯一Bean。

你可以阅读关于这个话题在这里:http://thegreyblog.blogspot.hu/2010/09/introduction-to-ejb-30-injection-and.html