Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency Injection EJB 3 - too many choices?

We are starting a new project based on EJB 3.0. I have a "spring" based background (and love it), so for me loose coupling and testability is a big must have. This post should not be about "ejb vs. spring". It would be perfect if you already have real project experience with this.

here is some example code to demonstrate the problem:

client -> ejb -> collaborator 1 -> collaborator .. -> collaborator n

<!-- language: java -->
@Stateless
public class SampleService {

    // or @Inject via CDI
    // or @Autowired via Spring
    @EJB // or just use a stateless session bean via EJB 3.0
    private Bank bank;

    // same for this component
    @EJB
    private Calculator calc;

    // both collaborators must be settable from outside, to make everything testable (and mockable)

    /**
     * sample "business service" called from client
     */
    public void debit(BigDecimal amount){
        calc.calculate(amount.subtract(new BigDecimal(100)));
        bank.debit(amount);
    }

}

// or via @Component (Spring), or CDI?
@Stateless // or Stateless Session bean with optional @Service/@Singleton annotation?
public class Calculator {
    public void calculate(BigDecimal subtract) {
        // calculate stuff....
    }
}

// or via @Component (Spring), or CDI?
@Stateless // or Stateless Session bean with optional @Service/@Singleton annotation?
public class Bank {
    public void debit(BigDecimal amount) {
        // ...
    }
}

i want to know what is the best way to implement dependency injection for all the collaborators and their collaborators in ejb 3.0? collaborators in this sense can be very very small dedicated classes.

we have discussed the the following options so far and like always don't have a proper conclusion yet :)

  1. only use the ejb standard with everything beeing a stateless session bean and all consequences (like pooling, resource handling etc.)

  2. use stateless session beans as "business components" (entry points) and from there on

a) spring wired dependencies (via "jboss snowdrop" integration)

b) CDI wired dependencies (via WELD for ejb 3.0 and jboss eap 5.1)

i don't need to know how i can use the beans in a unit test. the answer i am after is what is the best approach to wire up all the dependencies inside the running appserver (spring vs. guice vs. CDI vs. EJB). i only need to know the graph from the outer EJB ("business entry point") downwards. so everything outside (servlets, frontend etc.) is not scope of this question :)

please, assume EJB 3.0 and jboss eap 5.1 are set for the project :)

looking forward to your answers and hopefully some project based knowledge.

like image 535
Marcel Avatar asked Mar 14 '11 09:03

Marcel


People also ask

What is EJB dependency injection?

EJB 3.0 specification provides annotations, which can be applied on fields or setter methods to inject dependencies. EJB Container uses the global JNDI registry to locate the dependency. Following annotations are used in EJB 3.0 for dependency injection. @EJB − used to inject other EJB reference.

What is the difference between @inject and @EJB?

@Inject is more general than EJB and is part of CDI specification. So if you want to use @Inject, you need an implementation of it in your server. For POJOs (not EJBs) you have to use @Inject.

Which annotation is used to inject an EJB into another EJB?

Like resource injection, you can inject Session bean references into another EJB or other managed class using annotations or deployment XML. If you prefer annotations you can use @javax. ejb. EJB annotations to inject either remote or local EJB references.

Which annotation is used to inject an datasource into an EJB?

You can use the @EJB annotation to inject EJB references and @Resource to access datasources.


2 Answers

If you need method level transaction management, security, concurrency management or any other services that a session bean can offer then make them EJB session beans. You can start out with managed beans and then make them session beans as and when you need to.

If you want to inject these session beans into managed beans (which in CDI is anything in a jar file that contains a beans.xml file in the meta-inf directory) then use @EJB. If you want to inject a plain managed bean into a session bean use @Inject.

If you want to inject remote session beans (or any Java EE remote resource) then this link explains how you can do this via an adapter class. Essentially it keeps all of your nasty strings for lookups etc in one place and allows you then to treat these remote resources just like any other injectable bean (via the @Produces annotation on the adapter member variables). You don't have to do this but it is recommended.

Typesafe resource injection

like image 102
user695654 Avatar answered Sep 17 '22 23:09

user695654


I would definitely vote against mixing frameworks.

I'm working on a project that is hooked on EJB, Spring and JBoss Seam (and also has half-Flex, half-JSF front-end). A true technology zoo!
Anyway, wiring it all together is not the worst part, those frameworks have flexible injection capabilities. Testing is also more or less bearable.
The most painful was to get rid of memory leaks caused by different lifecylce models, synchronize transaction, and clean up threading behavior.

Now we're moving to pure Java EE 6 (getting rid of Spring, Flex and shifting from Seam to CDI). So far we're really pleased with the results. BTW, I'm not criticizing Spring. Stick with either Java EE or Spring stack, mixing them is just asking for trouble.

like image 39
Yuri Avatar answered Sep 20 '22 23:09

Yuri