@Inject, @EJB, @Local, @Remote, @LocalBean, etc... : confused?

I have the following configuration:

  • 1 EAR on one GF containing 2 EJB-JARs with EJB components.
  • 1 WAR on another Glassfish server (=> other JVM) containing web components accessing the EJB components.
  • I have 2 EJB business services in each EJB-JAR of my EAR, and they are all developped like this:

    @Remote
    public interface ServiceAItf {
        ...
    }
    
    @Stateless
    @Local
    public class ServiceAImpl implements ServiceAItf {
        ...
    }
    

    In my WAR, I access the EJB components via an explicit "InitialContext.lookup" on the remote interface.

    In my EAR, I am quite confused about the best practice for injection, in terms of performance, architecture, and so on...

    I have the following questions:

  • As you can see, I have declared the annotation "@Local" on the service implementation without defining the local interface. Is it correct? At least I have no error at deployment. But maybe I should use the "@LocalBean" annotation instead? I suppose that the "@LocalBean" annotation simply allows to invoke the implementation directly as a "Local" EJB, but you have to use the implementation in your code like this:

    @Stateless @Local public class ServiceBImpl implements ServiceBItf { @EJB private ServiceAImpl serviceA; ... }

  • What is the best way to inject one EJB into another one? It works like this:

    @Stateless @Local public class ServiceBImpl implements ServiceBItf { @EJB private ServiceAItf serviceA; ... }

  • But from what I noticed, the "serviceA" injected is the remote proxy, while it is in the same JVM within the same EAR file. So I suppose that there will be an impact on the performance. That's why I have tried to inject the service like this:

    @Stateless
    @Local
    public class ServiceBImpl implements ServiceBItf {
        @Inject
        private ServiceAItf serviceA;
        ...
    }
    

    But it doesn't work in GF, I have the following exception:

    WELD-001408 Unsatisfied dependencies for type [...] ...
    

    I then tried to create a local interface, and the injection via the annotation "@Inject" works when both services

    Even if I create a local interface like this, the service is not injected via the annotation "@Inject" but is null:

    @Local
    public interface ServiceALocalItf {
        ...
    }
    

    I read a lot of articles where it is highly recommended to use "@Inject" instead of "@EJB" when it is for a local invocation. That leads me to the following question: in which case the "@Local" EJB invocation is recommended (or simply used)?

    After all this analysis, I come to the following conclusion:

  • For each service, I create a "@Local" and a "@Remote" interface.
  • From WAR to EJB-JAR of EAR, make a JNDI lookup to the remote interface.
  • From EJB-JAR to EJB-JAR, make an injection via "@EJB" to the local interface.
  • For two services within the same EJB-JAR, make an injection via "@Inject" to the local interface.
  • What do you think about it? Is it correct?


    As you can see, I have declared the annotation "@Local" on the service implementation without defining the local interface. Is it correct?

    With EJB 3.1, the requirement for local interfaces was dropped. No need to write them unless you explicitly need them.

    What is the best way to inject one EJB into another one?

    Couple of things to write here:

    With Java EE 6, Java Enterprise has changed. A new JSR defines a so-called managed bean (don't confuse with JSF managed beans) as a sort of minimum component that can still benefit from the container in terms of dependency injection and lifecycle management. This means: If you have a component and "just" want to use DI and let the container control its lifecycle, you do not need to use EJBs for it. You'll end up using EJBs if - and only if - you explicitly need EJB functionality like transaction handling, pooling, passivation and clustering.

    This makes the answer to your question come in three parts:

  • Use @Inject over @EJB, the concept of CDI (a) works for all managed beans (this includes EJBs) and (b) is stateful and therefore far superior over pure @EJB DI
  • Are you sure that you need EJBs for your components?
  • It's definitely worthwhile to have a look at the CDI documentation

  • @Inject annotation is used for java beans(POJOs) while @EJB annotation is used for enterprise java beans. When a container inject an ejb provided by @EJB annotation to another bean it also controls that ejb's lifecycle, performs pooling for stateless beans and so on(when bean which is going to be injected is not deployed the reference will be null). If you use @Inject annotation CDI mechanism simply find and create an instance of injected resource like with new operator(if the implementation of interface which is going to be injected doesn't exist the reference will be null). You can use qualifiers with @Inject annotation to choose different implementation of injected interface.

    链接地址: http://www.djcxy.com/p/58774.html

    上一篇: 我们应该如何避免这种注入异常?

    下一篇: @Inject,@EJB,@Local,@Remote,@LocalBean等......:困惑?