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 :)
only use the ejb standard with everything beeing a stateless session bean and all consequences (like pooling, resource handling etc.)
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.
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.
@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.
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.
You can use the @EJB annotation to inject EJB references and @Resource to access datasources.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With