Friday, January 08, 2010

Contexts and Dependency Injection for Java EE (CDI) - Part 1

(See details: http://www.theserverside.com/tt/articles/content/DependencyInjectioninJavaEE6/article.html)
Contexts and Dependency Injection for Java EE (CDI) - JSR 299.
Leader: Gavin King

CDI is the de-facto API for comprehensive next-generation type-safe dependency injection for Java EE, which aims to synthesize the best-of-breed dependency injection features from solutions like Seam, Guice and Spring while adding many useful innovations of its own.

Java EE 5
What you can do is:
  • Injecting container resources such as JMS connection factories, data sources, queues, JPA entity managers, entity manager factories and EJBs via the @Resource, @PersistenceContext, @PersistenceUnit and @EJB annotations into Servlets, JSF backing beans and other EJBs.


  • What you could not is:
  • Injecting EJBs into Struts Actions or JUnit tests and you could not inject DAOs or helper classes that were not written as EJBs because they do not necessarily need to be transactional.

  • More broadly, it was difficult to integrate third-party/in-house APIs or use Java EE 5 as a basis to build such APIs that are not just strictly business components.


  • CDI is designed to solve in a highly type-safe, consistent and portable way that fits the Java philosophy well.

    Comparison with existing technologies.
  • Spring IoC - CDI is likely to feel more type-safe, futuristic and annotation-driven.

  • Seam - CDI has a lot more advanced features.

  • Guice - CDI is perhaps more geared towards enterprise development than it.


  • CDI enhances the Java EE programming model in two more important ways - both of which come from Seam.
  • First, it allows you to use EJBs directly as JSF backing beans.

  • Second, CDI allows you to manage the scope, state, life-cycle and context for objects in a much more declarative fashion, rather than the programmatic way most web-oriented frameworks handle managing objects in the request, session and application scopes.


  • CDI has no component model of its own but is really a set of services that are consumed by Java EE components such as managed beans, Servlets and EJBs.

    Managed beans are a key concept introduced in Java EE 6 to solve some of the limitations when using Java EE 5 style resource injection.

    A managed bean is just a bare Java object in a Java EE environment. Other than Java object semantics, it has a well-defined create/destroy life-cycle that you can get callbacks for via the @PostConstruct and @PreDestroy annotations. Managed beans can be explicitly denoted via the @ManagedBean annotation, but this IS NOT ALWAYS needed, especially with CDI. From a CDI perspective, this means that almost any Java object can be treated as managed beans and so can be full participants in dependency injection.

    Traditional JSF backing beans are now managed beans.
    All EJB session beans are now also redefined to be managed beans with additional services (thread-safety and transactions by default).

    Servlets are NOT yet redefined to be managed beans.

    CDI also integrates with JSF via EL bean name resolution from view technologies like Facelets and JSP as well as automatic scope management.

    CDI's integration with JPA consists of honoring the @PersistenceContext and @PersistenceUnit injection annotations, in addition to @EJB and @Resource.

    Note
    CDI DOES NOT directly support business component services such as transactions, security, remoting, messaging and the like that are in the scope of the EJB specification.

    JSR 299 utilizes the Dependency Injection for Java (JSR 330) specification as its foundational API, primarily by using JSR 330 annotations such as @Inject, @Qualifier and @ScopeType. Led by Rod Johnson and Bob Lee, JSR 330 defines a minimalistic API for dependency injection solutions and is primarily geared towards non-Java EE environments.

    CDI essentially adapts JSR 330 for Java EE environments while also adding a number of additional features useful for enterprise applications.



    Dependency Injection Basics


    @Stateless
    public class BidService {
    @Inject
    private BidDao bidDao;

    public void addBid (Bid bid) {
    bidDao.addBid(bid);
    }
    }

    public class DefaultBidDao implements BidDao {
    @PersistenceContext
    private EntityManager entityManager;

    public void addBid (Bid bid) {
    entityManager.persist(bid);
    }
    }

    public interface BidDao {
    public void addBid (Bid bid);
    }


    The bid DAO managed bean is being injected into the bid service EJB session bean via the @Inject annotation. CDI resolves the dependency by looking for any class that implement the BidDao interface. When CDI finds the DefaultBidDao implementation, it instantiates it, resolves any dependencies it has (like the JPA entity manager injected via @PersistenceContext) and injects it into the EJB bid service. Since no explicit bean scope is specified for either the service or the DAO, they are assumed to be in the implicit dependent scope.

    Qualifiers are additional pieces of meta-data that narrow down a particular class when more than one candidate for injection exists.

    @Stateless
    public class BidService {
    @Inject @JdbcDao
    private BidDao bidDao;
    ...
    }

    @JdbcDao
    public class LegacyBidDao implements BidDao {
    @Resource(name="jdbc/ActionBazaarDB")
    private DataSource dataSource;
    ...
    }


    Context Management Basics

    Every object managed by CDI has a well-defined scope and life-cycle that is bound to a specific context. As CDI encounters a request to inject/access an object, it looks to retrieve it from the context matching the scope declared for the object. If the object is not already in the context, CDI will get reference to it and put it into the context as it passes the reference to the target. When the scope corresponding to the context expires, all objects in the context are removed.

    Available Scope Definition
    Dependent, ApplicationScoped, RequestScoped, SessionScoped, ConversationScoped

    Besides the built-in scopes above, it is also possible to create custom scopes via the @Scope annotation

    @Named
    @RequestScoped
    public class BidManager {
    @Inject
    private BidService bidService;
    ...
    }

    @Stateless
    public class BidService {
    @Inject
    private BidDao bidDao;

    @Inject
    private BiddingRules biddingRules;
    ...
    }

    @ApplicationScoped
    public class DefaultBiddingRules implements BiddingRules {
    ...
    }


    @Named annotation makes the bid manager accessible from EL.



    JSR 330 defines a minimalistic API for dependency injection solutions and is primarily geared towards non-Java EE environments. In particular, it does not define scope types common in server-side Java such as request, session and conversation. It also does not define specific integration semantics with Java EE APIs like JPA, EJB and JSF.

    No comments: