Contexts and Dependency Injection for the Java EE Platform (CDI), JSR 299 is a technology that supplies a powerful set of services to Java EE components. These services allow Java EE components, including EJB session beans and JavaServer Faces (JSF) managed beans, to be bound to lifecycle contexts, to be injected, and to interact in a loosely coupled way by firing and observing events. Perhaps most significantly, CDI unifies and simplifies the EJB and JSF programming models. It allows enterprise beans to replace JSF managed beans in a JSF application.
In essence, 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.
For example, using EJB and JPA you can easily build an application that interacts with a database, commits or rolls back transactions on the data, and persists the data. The web tier, by comparison, 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.
For example, using EJB and JPA you can easily build an application that interacts with a database, commits or rolls back transactions on the data, and persists the data. The web tier, by comparison, 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. This can make it a lot easier to access transactional resources in web applications. For example, CDI makes it a lot easier to build a Java EE web application that accesses a database with persistence provided by JPA.
Let's look at some key parts of a web application that uses CDI services. The application, which processes user login and user logout requests, includes both JSF and EJB components. Here is the code for an input form on a JSF page that displays a login prompt for the web application:
As you can see from the code, the login prompt displays fields for a user to enter a user name and password. It also displays a Login button and a Logout button. Notice the unified expression language (EL) expressions such as
#{credentials.username} and #{login.login}. These expressions refer to beans, named credentials and login.Note that 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. So 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.
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. So 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.
You declare a managed bean by annotating its class with the
For example, you can turn a POJO into a stateful session bean by adding a
javax.annotation.ManagedBean annotation or by using one of several CDI annotations such as a scope annotation or a qualifier annotation. The annotation-based programming model makes it possible for a bean to begin as a POJO and later become another type of Java EE component such as an EJB component — perhaps to take advantage of more advanced functionality, such as transactional and security annotations or the instance pooling facility offered by EJB containers. For example, you can turn a POJO into a stateful session bean by adding a
@Stateful annotation to the object. Clients that use CDI to access a bean are unaffected by the bean's transition from POJO to EJB.Any bean can be bound to a lifecycle context, can be injected, and can interact with other beans in a loosely coupled way by firing and observing events. In addition, a bean may be called directly from Java code, or as in this example, 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.
In this application, a bean named
Credentials has a lifecycle that is bound to the JSF request. The Credentials bean is implemented as a JavaBean as follows:To request CDI services, you annotate a Java EE component with CDI annotations. The
@Model annotation is a CDI annotation that identifies the Credentials bean as a model object in an Model-View-Controller (MVC) architecture. The annotation, which is built into CDI, is a stereotype annotation. A stereotype annotation marks a class as fulfilling a specific role within the application.The application also includes a
Login bean whose lifecycle is bound to the HTTP session. The Login bean is implemented as an EJB stateful session bean, as follows:The
@Stateful annotation is an EJB annotation that specifies that this bean is an EJB stateful session bean. The @TransactionAttribute and @RolesAllowed annotations are also EJB annotations. They declare the EJB transaction demarcation and security attributes of the annotated methods.The
In particular, EJB components are not aware of the request, session, and application contexts of web tier components such as JSF managed beans, and do not have access to the state associated with those contexts. In addition, the lifecycle of a stateful EJB component cannot be scoped to a web-tier context.
@SessionScoped annotation is a CDI annotation that specifies a scope for the bean. All beans have a scope that determines the lifecycle of its instances and the instances of the bean that are made visible to instances of other beans. This is an important feature because components such as EJB components do not have a well-defined scope. In particular, EJB components are not aware of the request, session, and application contexts of web tier components such as JSF managed beans, and do not have access to the state associated with those contexts. In addition, the lifecycle of a stateful EJB component cannot be scoped to a web-tier context.
By contrast, scoped objects in CDI exist in a well-defined lifecycle context that is managed by the Java EE container. Scoped objects may be automatically created when needed and then automatically destroyed when the context in which they were created ends.
Significantly, the state of a scoped object is automatically shared by clients that execute in the same context. This means that clients such as other beans that execute in the same context as a scoped object see the same instance of the object. But clients in a different context see a different instance.
The
Significantly, the state of a scoped object is automatically shared by clients that execute in the same context. This means that clients such as other beans that execute in the same context as a scoped object see the same instance of the object. But clients in a different context see a different instance.
The
@SessionScoped annotation specifies that the scope type for the Login bean is session scope. Objects that are not associated with any of the usual scopes, but instead exist for the exclusive benefit of an object that triggered their creation, are said to be dependents of their owner. The lifecycle of these dependent objects is tied to that of the owner. In particular, a dependent object is destroyed whenever the owner is destroyed.Beans typically acquire references to other beans through dependency injection. The dependency injection mechanism is completely type safe. CDI uses the annotations specified in JSR 330: Dependency Injection for Java for dependency injection.
One of those annotations,
In response, the container will inject the
One of those annotations,
@Inject, identifies a point at which a dependency on a Java class or interface can be injected. The container then provides the needed resource. In this example, the Login bean specifies two injection points. The first use of the @Inject annotation in the example injects a dependency on the Credentials bean. In response, the container will inject the
Credentials bean into any instance of Login created within this context. The second @Inject annotation injects a dependency on the JPA EntityManager. The container will inject the EntityManager to manage the persistence context. The
A qualifier identifies a specific implementation of a Java class or interface to be injected. In order to use a qualifier annotation, you first need to define its type as a qualifier. You use the
@Produces annotation identifies the getCurrentUser() method as a producer method. A producer method is called whenever another bean in the system needs an injected object of the specified type. In this case, the injected object is the currently logged-in user, which is injected by the qualifier annotation @LoggedIn. A qualifier identifies a specific implementation of a Java class or interface to be injected. In order to use a qualifier annotation, you first need to define its type as a qualifier. You use the
@Qualifier annotation, another JSR 330 annotation, to do that. For example:Let's return to the login prompt discussed earlier. When a user responds to the prompt and clicks the Submit button, CDI technology goes into action.
The Java EE container automatically instantiates a contextual instance of the
This instance continues to exist for and is available to other requests in the same HTTP session, and provides the
The Java EE container automatically instantiates a contextual instance of the
Credentials bean and the Login bean. An instance of a bean that is bound to a context is called a contextual instance. JSF assigns the user name and password the user entered to the Credentials bean contextual instance. Next, JSF calls the login() method in the Login bean contextual instance. This instance continues to exist for and is available to other requests in the same HTTP session, and provides the
User object that represents the current user to any other bean that requires it.This example demonstrates only some of the features in this powerful technology. Another feature enables beans to produce or consume events. Yet another lets you define interceptors that bind additional function across all bean types, or define decorators that apply the additional function to a specific bean type.
Source: java.sun.com - J2EE 6 Overview
Great overview. Thanks. Vlad
ReplyDelete