Nov 8, 2018

Contexts and Dependency Injection (CDI) Inject VS @EJB in Java EE

Contexts and Dependency Injection (CDI) is a Java EE 6+ specification, which not only defines a powerful and type-safe Dependency Injection, but also introduces the concept of "contextual" references or scopes. On the other hand, dependency injection of EJB beans either by @EJB annotation or configured in the deployment descriptor (XML configuration) is string based matching. CDI also supports such a resolution of ambiguity with plain String. It even comes with a built-in qualifier for that purpose. @Named can be used to annotate the implementation, as well as the injection point, with plain String. If the string value matches at the injection point as well as at the implementation, it gets injected. The name can even be derived from the attribute name. But the recommended way to qualify and to configure the dependencies is to use typed annotations with optional attributes instead of plain strings. These annotations are called qualifiers. It’s a standard annotation marked with a @Qualifier annotation.

A client has absolutely no control over the @Stateless session bean life-cycle. It is entirely managed by the container. The opposite is true for @Stateful beans. Here, the client has to manage the entire life-cycle. A @Stateful bean is created by the container during the injection. The destruction is initiated by the client through the invocation of a business method annotated with the @Remove annotation or a container-specific timeout.

A @Stateful bean could be injected into a @Stateless bean, but the outcome would be unpredictable. The injected @Stateful instance would be directly bound to a given @Stateless bean instance.

The CDI container manages all beans inside the scope automatically for you. At the end of an HttpSession or HttpRequest, all instances associated with this scope are automatically destroyed and, thus, garbage collected.

This behavior is very different from that of Stateful session beans. A Stateful session bean instance needs to be explicitly removed by the client with the invocation of a method annotated with @Remove. It will not be automatically destroyed by the container; it is not bound to any context. If you associate a Stateful session bean with the HttpSession, you also have to care about its reliable destruction at the end or timeout of the HttpSession.

The contextual nature of CDI makes the use of beans from different scopes more natural and convenient. You can even mix and match scopes and inject beans from different scopes. The container will still care about proper life-cycle management.

The configuration of the EJB beans’ DI is similar to the use of the @Named qualifier. CDI goes far beyond that and is not limited to plain String matching. Custom qualifiers can be introduced easily and used to configure the dependency injection in a type-safe manner.

The managed beans of CDI are managed inside their scopes. The container is aware of the current scope and manages the bean instances at the same time. Having both in place, the container is able to pick the right instance and inject it consistently into your scoped beans. This is not possible with EJB beans because they are scope- and HTTP-infrastructure agnostic.

The lack of contextual capabilities in EJB beans is the biggest difference in CDI. The injected EJB proxy just points to either a pool of instances or a single bean instance for a bean annotated with the @Stateless or @Stateful annotation, respectively. CDI-managed beans are contextual and EJB beans are not. Managed beans in CDI live in well-defined scope. They are created and destroyed on demand by the container. CDI comes already with pre-defined scopes and annotations: @RequestScoped, @SessionScoped, @ApplicationScoped, and @ConversationScoped.