Dependency Injection in Java EE 6 Provides Unified EJB and JSF Programming Model
Dependency Injection is one of the main features of recently released Java EE 6 version. It includes JSRs 330 and 299 which were released under the Enterprise Application Technologies category in Java EE release. Dependency Injection for Java (JSR 330) provides a standardized and extensible API for dependency injection. Contexts and Dependency Injection for the Java EE Platform 1.0 (JSR 299), which builds on JSR 330, unifies and simplifies the EJB and JSF programming models. It allows enterprise beans to act as the managed beans in JSF applications, and brings transactional support to the web tier.
Standardized Annotations for Dependency Injection:
The objective of this specification is to provide a standardized and extensible API for dependency injection. The set of annotations specified by JSR 330 make injectable classes portable across frameworks. The developers no longer have to work with vendor-specific annotations using frameworks like Spring and Google Guice. Some of the annotations included in this JSR are:
- Inject: Identifies injectable constructors, methods, and fields. Constructors are injected first, followed by fields, and then methods. Also, the fields and methods in super classes are injected before those in subclasses.
- Qualifier: Identifies qualifier annotations. Qualifiers are strongly-typed keys that help distinguish different uses of objects of the same type. It is marked with @Qualifier, @Retention(RUNTIME), and typically @Documented annotations.
- Scope: Identifies scope annotations.
- Singleton: Identifies a type that the injector only instantiates once.
- Named: This is a String-based qualifier.
Contexts and Dependency Injection:
Contexts and Dependency Injection (CDI) specification builds on JSR-330 and adds much functionality to dependency injection, which includes automatic discovery and configuration of injectable classes and an API to define new injectable classes at runtime, to help integrate with third-party frameworks.
CDI unifies and simplifies the EJB and JSF programming models. It allows enterprise beans to act as JSF managed beans in a JSF application and brings transactional support to the web tier. It also allows Java EE components, including EJBs, to be bound to lifecycle events, to be injected, and to interact in a loosely coupled way by firing and observing events. This gives EJB components access to the Request, Session, and Application contexts of web tier components.
CDI helps bridge what was a major gap between the web tier of the Java EE platform and the enterprise tier. The enterprise tier, through technologies such as EJB and JPA, has strong support for transactional resources. The web tier is focused on presentation. Web tier technologies such as JSF and JavaServer Pages (JSP pages) render the user interface and display its content, but have no integrated facilities for handling transactional resources. Through its services, CDI brings transactional support to the web tier which makes it easier to access transactional resources in web applications. For example, CDI makes it easier to build a Java EE web application that accesses a database with persistence provided by JPA.
CDI builds on a new concept introduced in Java EE 6 called managed beans, which is designed to unify all of the various types of beans in Java EE 6. A managed bean is a Java class that is treated as a managed component by the Java EE container. Optionally, you can give it a name in the same namespace as that used by EJB components. A managed bean can also rely on a small number of container-provided services, mostly related to lifecycle management and resource injection. Other Java EE technologies such as JSF, EJB, and CDI build on this basic definition of a managed bean by adding services. For example, a JSF managed bean adds lifecycle scopes, an EJB session bean adds services such as support for transactions, and CDI adds services such as dependency injection. In CDI a managed bean or simply a bean is a Java EE component that can be injected into other components, associated with a context, or reached through EL expressions.
The services supported by CDI provide:
- an improved lifecycle for stateful components, bound to well-defined contexts
- a type safe approach to dependency injection
- interaction via an event notification facility
- bind interceptors to components (using javax.interceptor.Interceptor and javax.interceptor.AroundInvoke annotations)
You declare a managed bean by annotating its class with the javax.annotation.ManagedBean annotation or by using one of several CDI annotations such as a scope annotation or a qualifier annotation. Any bean can be bound to a lifecycle context, can be injected, and can interact with other beans by firing and observing events. In addition, a bean may be called directly from Java code, or it may be invoked in a unified EL expression. This enables a JSF page to directly access a bean, even a bean that is implemented as an EJB component such as a session bean.
Some of the CDI annotations are as follows:
- Model annotation identifies a Java bean as a model object in an Model-View-Controller (MVC) architecture. This is a stereotype annotation which marks a class as fulfilling a specific role within the application.
- SessionScoped annotation specifies the Session scope for the bean. The other bean scopes can be specified using RequestScoped, ConversationScoped, ApplicationScoped, or Dependent annotations.
- Produces annotation identifies a specific method as a producer method which is called whenever another bean in the system needs an injected object of the specified type.
Some of the Reference Implementation (RI) projects of JSR-299 are Apache OpenWebBeans, Resin's CanDI and JBoss' Weld framework. For more details on the dependency injection feature in JEE 6, checkout the 3-part article series (Part 1, Part2, and Part 3) published by Sun development team. DZone recently published a Refcard on CDI topic.
And it's in my opinion a bit of an overstatement that JSR-299 builds on JSR-330. JSR-330 is a shadow-JSR that was shoehorned on to JSR-299 when the JCP got tired of arguing. It didn't really add anything that JSR-299 didn't have. Except for confusion. But that's just my opinion ;-)