简体   繁体   English

消除EJB注释和注入

[英]Demistifying EJB annotations and injection

I'm currently puzzled with the way Glassfish 3.1.2.2 handles EJBs. 目前,我对Glassfish 3.1.2.2处理EJB的方式感到困惑。

I have an OSGi project, which consists of many OSGi bundles (jars). 我有一个OSGi项目,其中包含许多OSGi捆绑包(罐)。 Also, there are a few WARs, including a Tapestry web application. 另外,还有一些WAR,包括Tapestry Web应用程序。

In one such bundle, let's call it "interfaces.jar", I have an interface defined: 在一个这样的包中,我们将其称为“ interfaces.jar”,我定义了一个接口:

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

The implementation of that interface is as following, and it's contained in bundle "beans.jar": 该接口的实现如下,它包含在捆绑包“ beans.jar”中:

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

I am calling it from my Tapestry WAR app via JNDI lookup: 我通过JNDI查找从我的Tapestry WAR应用程序中调用它:

InitialContext.doLookup(MyInterface.JNDI_NAME);

Now, I was reading EJB 3.1 specification, and it says that I can one of the following scenarios: 现在,我正在阅读EJB 3.1规范,它说我可以采用以下方案之一:

  1. Interface has @Local annotation; 接口具有@Local批注; EJB is implementing this interface. EJB正在实现此接口。
  2. Interface is a plain Java interface without annotation; 接口是没有注释的纯Java接口。 EJB with @Local annotation is implementing it. 具有@Local批注的EJB正在实现它。
  3. Interface is a plain Java interface without annotation; 接口是没有注释的纯Java接口。 EJB is implementing it. EJB正在实现它。
  4. Interface is a plain Java interface without annotation; 接口是没有注释的纯Java接口。 EJB with @Local annotation is not implementing it. 具有@Local批注的EJB没有实现它。
  5. EJB doesn't have any special annotations. EJB没有任何特殊的注释。

So, by elimination: 因此,通过消除:

  1. I don't have @Local on interface 我的界面上没有@Local
  2. I don't have @Local on EJB 我在EJB上没有@Local
  3. Seems somewhat right 似乎有些正确
  4. I don't have @Local on EJB 我在EJB上没有@Local
  5. I have @EJB annotation on my EJB 我的EJB上有@EJB注释

So, it seems that it's case 3: 因此,似乎是情况3:

"Because it's the only implemented interface of the EJB, a container assumes that it must be a local business interface." “因为它是EJB唯一实现的接口,所以容器假定它必须是本地业务接口。”

Now, a few questions: 现在,有几个问题:

  1. Is my interface a local or remote one, since there is no local or remote annotation? 由于没有本地或远程注释,我的接口是本地还是远程接口?
  2. If it is local, I should be able to inject it with @EJB annotation, but it fails? 如果它是本地的,我应该可以使用@EJB注释将其注入,但是失败了吗?
  3. If it's remote, it is not in compliance with the explanation a few lines above? 如果是远程的,是否不符合上面几行的说明?
  4. If I add either @Local or @Remote , and perform JNDI lookup, I get a naming exception and NPE telling me there is nothing under that JNDI_NAME . 如果我添加@Local@Remote并执行JNDI查找,则会得到一个命名异常,并且NPE告诉我该JNDI_NAME下没有任何JNDI_NAME How is that possible? 那怎么可能?
  5. What exactly does @EJB(name = ..., beanInterface = ...) do on bean class and how does it interact with @Local and @Remote annotations? @EJB(name = ..., beanInterface = ...)对bean类的作用是什么?它如何与@Local@Remote批注交互?

1.) First, let's see your example without the "unnecessary" @EJB annotation 1.)首先,让我们看一下没有“不必要” @EJB注释的示例

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

You can now see clearly, that the EJB implements only one interface. 现在您可以清楚地看到EJB仅实现了一个接口。 As you mentioned in the 3rd points, "Interface is a plain Java interface without annotation; EJB is implementing it.", so MyInterface is a Local Business Interface of the MyBean EJB. 正如您在第3点中提到的那样,“接口是没有注释的普通Java接口; EJB正在实现它。”因此MyInterface是MyBean EJB的本地业务接口。

2.) 2.)

You use wrong JNDI name for the lookup: 您使用错误的JNDI名称进行查找:

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

The global JNDI name of your EJB: EJB的全局JNDI名称:

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

The interface-name is "MyInterface", but it is optional if there are no other business interfaces for your beans, like here, so you can skip it. 接口名称为“ MyInterface”,但如果没有其他可用于您的bean的业务接口(例如此处),则它是可选的,因此可以跳过它。

You have to figure out what the application- and module-name is for your bean in case of OSGI. 对于OSGI,您必须弄清楚bean的应用程序名称和模块名称是什么。 In a simple EJB application, the application-name is the name of the .ear file, and the module-name is the name of the .war/.jar file. 在一个简单的EJB应用程序中,application-name是.ear文件的名称,而module-name是.war / .jar文件的名称。 application-name can be skipped if your module is not packaged in an ear. 如果您的模块未包装在耳边,则可以跳过application-name。

So for example: 因此,例如:

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

5.) 5.)

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

Here the @EJB annotation creates an EJB and put a reference to it into the Environment Naming Context (ENC). 在这里,@ EJB注释创建一个EJB,并将对它的引用放入环境命名上下文(ENC)中。 So it does nothing with the MyBean EJB, just expand its ENC with a new entry. 因此,它对MyBean EJB无效,只需使用新条目扩展其ENC。

So from the business method of the current bean you can lookup for that new entry: 因此,从当前bean的业务方法中,您可以查找该新条目:

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

You can locate the bean's ENC by "java:comp/env/" JNDI name. 您可以通过“ java:comp / env /” JNDI名称找到bean的ENC。

As you can see, the name parameter defines the name of the entry in the ENC. 如您所见, name参数定义了ENC中条目的名称。

The beanInterface defines the Business Interface of the created Bean. beanInterface定义了创建的Bean的业务接口。 If the Bean has more business interfaces, then you have to define beanName too, so the container could determine wich Bean you would like to create. 如果Bean具有更多的业务接口,那么您也必须定义beanName,以便容器可以确定要创建的夹心Bean。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM