Fusion Middleware Documentation
Advanced Search


Developing Applications for Oracle WebLogic Server
Close Window

Table of Contents

Show All | Collapse

9 Using Contexts and Dependency Injection for the Java EE Platform

WebLogic Server provides an implementation of the Contexts and Dependency Injection (CDI) specification. The CDI specification defines a set of services for using injection to specify dependencies in an application. CDI provides contextual life cycle management of beans, type-safe injection points, a loosely coupled event framework, loosely coupled interceptors and decorators, alternative implementations of beans, bean navigation through the Unified Expression Language (EL), and a service provider interface (SPI) that enables CDI extensions to support third-party frameworks or future Java EE components.

The following sections explain how to use CDI for the Java EE platform in your applications:

About CDI for the Java EE Platform

CDI is specified by Java Specification Request (JSR) 299: Contexts and Dependency Injection for the Java EE platform. This specification was formerly called Web Beans. CDI uses the following related specifications:

CDI provides the following features:

  • Contexts. This feature enables you to bind the life cycle and interactions of stateful components to well-defined but extensible life cycle contexts.

  • Dependency injection. This feature enables you to inject components into an application in a type-safe way and to choose at deployment time which implementation of a particular interface to inject.

CDI is integrated with the major component technologies in Java EE, namely:

  • Servlets

  • JavaServer Pages (JSP)

  • JavaServer Faces (JSF)

  • Enterprise JavaBeans (EJB)

  • Java EE Connector architecture (JCA)

  • Web services

Such integration enables standard Java EE objects, such as Servlets and EJB components, to use CDI injection for dependencies. CDI injection simplifies, for example, the use of managed beans with JSF technology in Web applications.

For more information, see Introduction to Contexts and Dependency Injection for the Java EE Platform in the Java EE 6 Tutorial.

A complete example that shows how to use CDI is provided in the cdi sample application, which is installed in EXAMPLES_HOME\wl_server\examples\src\examples\javaee6\cdi, where EXAMPLES_HOME represents the directory in which the WebLogic Server code examples are configured. For more information about the WebLogic Server code examples, see "Sample Applications and Code Examples" in Understanding Oracle WebLogic Server.

Defining a Managed Bean

A bean is a source of the objects that CDI can create and manage. For more information, see About Beans in The Java EE 6 Tutorial.

A managed bean is the basic component in a CDI application and defines the beans that CDI can create and manage. To define a managed bean, define a top-level plain old Java object (POJO) class that meets either of the following conditions:

  • The class is defined to be a managed bean by any other Java EE specification.

  • The class meets all of the conditions that are required by JSR 299 as listed in About Managed Beans in The Java EE 6 Tutorial.

Note:

No special declaration, such as an annotation, is required to define a managed bean. To make the managed beans of an application available for injection, you must configure the application as explained in Configuring a CDI Application.

Injecting a Bean

To use the beans that you define, inject them into another bean that an application such as a JavaServer Faces application can use. For more information, see Injecting Beans in The Java EE 6 Tutorial.

CDI ensures type-safe injection of beans by selecting the bean class on the basis of the Java type that is specified in the injection point, not the bean name. CDI also determines where to inject a bean from the Java type in the injection point.

In this respect, CDI bean injection is different than Java EE 5 resource injection. Java EE 5 resource injection selects the resource to inject from the string name of the resource. For example, a data source that is injected with the javax.annotation.Resource annotation is identified by its string name.

To inject a bean, obtain an instance of the bean by creating an injection point in the class that is to use the injected bean. Create the injection point by annotating one of the following program elements with the javax.inject.Inject annotation:

  • An instance class field

  • An initializer method parameter

  • A bean constructor parameter

Example 9-1 shows how to use the @Inject annotation to inject a bean into another bean.

Example 9-1 Injecting a Bean into Another Bean

This example annotates an instance class field to inject an instance of the bean class Greeting into the class Printer.

import javax.inject.Inject;
...
public class Printer {
    @Inject Greeting greeting;
    ...
}

Defining the Scope of a Bean

The scope of a bean defines the duration of a user's interaction with an application that uses the bean. To enable a Web application to use a bean that injects another bean class, the bean must be able to hold state over the duration of the user's interaction with the application.

To define the scope of a bean, annotate the class declaration of the bean with the scope. The javax.enterprise.context package defines the following scopes:

  • @RequestScoped

  • @SessionScoped

  • @ApplicationScoped

  • @ConversationScoped

  • @Dependent

For information about these scopes, see Using Scopes in The Java EE 6 Tutorial.

If you do not define the scope of a bean, the scope of the bean is @Dependent by default. The @Dependent scope specifies that the bean's life cycle is the life cycle of the object into which the bean is injected.

The predefined scopes except @Dependent are contextual scopes. CDI places beans of contextual scope in the context whose life cycle is defined by the Java EE specifications. For example, a session context and its beans exist during the lifetime of an HTTP session. Injected references to the beans are contextually aware. The references always apply to the bean that is associated with the context for the thread that is making the reference. The CDI container ensures that the objects are created and injected at the correct time as determined by the scope that is specified for these objects.

Example 9-2 shows how to define the scope of a bean.

Example 9-2 Defining the Scope of a Bean

This example defines the scope of the Accountant bean class to be @RequestScoped.

The Accountant class in this example is qualified by the @BeanCounter qualifier. For more information, see Using Qualifiers.

package com.example.managers;

import javax.enterprise.context.RequestScoped;

@RequestScoped
@BeanCounter
public class Accountant implements Manager
{
 ...
}

Overriding the Scope of a Bean at the Point of Injection

Overriding the scope of a bean at the point of injection enables an application to request a new instance of the bean with the default scope @Dependent. The @Dependent scope specifies that the bean's life cycle is the life cycle of the object into which the bean is injected. The CDI container provides no other life cycle management for the instance. For more information about scopes, see Defining the Scope of a Bean.

Note:

The effects of overriding the scope of a bean may be unpredictable and undesirable, particularly if the overridden scope is @Request or @Session.

To override the scope of a bean at the point of injection, inject the bean by using the javax.enterprise.inject.New annotation instead of the @Inject annotation. For more information about the @Inject annotation, see Injecting a Bean.

Using Qualifiers

Qualifiers enable you to provide more than one implementation of a particular bean type. When you use qualifiers, you select between implementations at development time. For more information, see Using Qualifiers in The Java EE 6 Tutorial.

Note:

To select between alternative implementations at deployment time, use alternatives as explained in Providing Alternative Implementations of a Bean Type.

Using qualifiers involves the tasks that are explained in the following sections:

Defining Qualifiers for Implementations of a Bean Type

A qualifier is an application-defined annotation that enables you to identify an implementation of a bean type. Define a qualifier for each implementation of a bean type that you are providing.

Define qualifiers only if you are providing multiple implementations of a bean type and if you are not using alternatives. If no qualifiers are defend for a bean type, CDI applies the predefined qualifier @Default when a bean of the type is injected.

Note:

CDI does not require a qualifier to be unique to a particular bean. You can define a qualifier to use for more than one bean type.

To define a qualifier:

  1. Define a Java annotation type to represent the qualifier.

  2. Annotate the declaration of the annotation type with the javax.inject.Qualifier annotation.

  3. Specify that the qualifier is to be retained by the virtual machine at run time.

    Use the java.lang.annotation.Retention(RUNTIME) meta-annotation for this purpose.

  4. Specify that the qualifier may be applied to the program elements METHOD, FIELD, PARAMETER, and TYPE.

    Use the java.lang.annotation.Target({METHOD, FIELD, PARAMETER, TYPE}) meta-annotation for this purpose.

The following examples show how to define qualifiers @BeanCounter and @PeopleManager for different implementations of the same bean type.

Example 9-3 Defining the @BeanCounter Qualifier

This example defines the @BeanCounter qualifier.

package com.example.managers;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface BeanCounter {}

Example 9-4 Defining the @PeopleManager Qualifier

This example defines the @PeopleManager qualifier.

package com.example.managers;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface PeopleManager {}

Applying Qualifiers to a Bean

Applying qualifiers to a bean identifies the implementation of the bean type. You can apply any number of qualifiers or no qualifiers to a bean. If you do not apply any qualifiers to a bean, CDI implicitly applies the predefined qualifier @Default to the bean.

Note:

CDI does not require a qualifier to be unique to a particular bean. You can apply the same qualifier to different types of beans in the set of beans that are available in the application.

To apply qualifiers to a bean, annotate the class declaration of the bean with each qualifier to apply. Any qualifier that you apply to a bean must be defined as explained in Defining Qualifiers for Implementations of a Bean Type.

The following examples show how to apply the qualifiers @BeanCounter and @PeopleManager to different implementations of the Manager bean type.

Example 9-5 Applying the @BeanCounter Qualifier to a Bean

This example applies the @BeanCounter qualifier to the Accountant class. The Accountant class is an implementation of the Manager bean type. The @BeanCounter qualifier is defined in Example 9-3.

package com.example.managers;
...
@BeanCounter
public class Accountant implements Manager
{...}

Example 9-6 Applying the@ PeopleManager Qualifier to a Bean

This example applies the @PeopleManager qualifier to the Boss class. The Boss class is an implementation of the Manager bean type. The @PeopleManager qualifier is defined in Example 9-4.

package com.example.managers;
...
@PeopleManager
public class Boss implements Manager
{...}

Injecting a Qualified Bean

To inject a qualified bean, create an injection point and annotate the injection point with the bean's qualifiers. The qualifiers at the injection point define the overall requirements of the injection target. The CDI application must contain a CDI managed bean that matches the type of the injection point and the qualifiers with which the injection point is annotated. Otherwise, a deployment error occurs. For more information about how to create an injection point, see Injecting a Bean.

If you do not annotate the injection point, the predefined qualifier @Default is applied to the injection point by default.

CDI resolves the injection point by first matching the bean type and then matching implementations of that type with the qualifiers in the injection point.

Only one active bean class may match the bean type and qualifiers in the injection point. Otherwise, an error occurs.

A bean class is active in one of the following situations:

  • The bean class is an alternative that is enabled.

  • The bean class is not an alternative and no alternatives for its bean type are enabled.

For information about alternatives, see Providing Alternative Implementations of a Bean Type.

Example 9-7 shows how to inject a qualified bean.

Example 9-7 Injecting a Qualified Bean

This example injects the @BeanCounter implementation of the Manager bean type. The Manager bean type is implemented by the following classes:

In this example, the Accountant class is injected because the bean type and qualifier of this class match the bean type and qualifier in the injection point.

package com.example.managers;
...
import javax.inject.Inject;
...
public class PennyPincher { 
   @Inject @BeanCounter Manager accountant;
   ...
}

Providing Alternative Implementations of a Bean Type

The environments for the development, testing, and production deployment of an enterprise application may be very different. Differences in configuration, resource availability, and performance requirements may cause bean classes that are appropriate to one environment to be unsuitable in another environment.

Different deployment scenarios may also require different business logic in the same application. For example, country-specific sales tax laws may require country-specific sales tax business logic in an order-processing application.

By providing alternative implementations of a bean type, you can modify an application at deployment time to meet such differing requirements. CDI enables you to select from any number of alternative bean type implementations for injection instead of a corresponding primary implementation. For more information, see Using Alternatives in The Java EE 6 Tutorial.

Note:

To select between alternative implementations at development time, use qualifiers as explained in Using Qualifiers.

Providing alternative implementations of a bean type involves the tasks that are explained in the following sections:

Defining an Alternative Implementation of a Bean Type

To define an alternative implementation of a bean type:

  1. Write a bean class of the same bean type as primary implementation of the bean type.

    To ensure that any alternative can be injected into an application, you must ensure that all alternatives and the primary implementation are all of the same bean type. For information about how to inject a bean, see Injecting a Bean.

  2. Annotate the class declaration of the implementation with the javax.enterprise.inject.Alternative annotation.

    Note:

    To ensure that the primary implementation is selected by default, do not annotate the class declaration of the primary implementation with @Alternative.

The following examples show the declaration of the primary implementation and an alternative implementation of a bean type. The alternative implementation is a mock implementation that is intended for use in testing.

Example 9-8 Declaring a Primary Implementation of a Bean Type

This example declares the primary implementation OrderImpl of the bean type Order.

package com.example.orderprocessor;
...
public class OrderImpl implements Order {
 ...
}

Example 9-9 Declaring an Alternative Implementation of a Bean Type

This example declares the alternative implementation MockOrderImpl of the bean type Order. The declaration of the primary implementation of this bean type is shown in Example 9-8.

package com.example.orderprocessor;
...
import javax.enterprise.inject.Alternative;

@Alternative
public class MockOrderImpl implements Order {
 ...
}

Selecting an Alternative Implementation of a Bean Type for an Application

By default, CDI selects the primary implementation of a bean type for injection into an application. If you require an alternative implementation to be injected, you must select the alternative explicitly.

To select an alternative implementation for an application:

  1. Add a class element for the alternative to the alternatives element in the beans.xml file.

  2. In the class element, provide the fully qualified class name of the alternative.

For more information about the beans.xml file, see Configuring a CDI Application.

Example 9-16 shows a class element in the beans.xml file for selecting an alternative implementation of a bean type.

Example 9-10 Selecting an Alternative Implementation of a Bean Type

This example selects the alternative implementation com.example.orderprocessor.MockOrderImpl.

...
<alternatives>
    <class>com.example.orderprocessor.MockOrderImpl</class>
</alternatives>
...

Applying a Scope and Qualifiers to a Session Bean

CDI enables you to apply a scope and qualifiers to a session bean. A session bean is an EJB component that meets either of the following requirements:

  • The class that implements the bean is annotated with one of the following annotations:

  • The bean is listed in the ejb-jar.xml deployment-descriptor file.

For more information about session beans, see the following documents:

Applying a Scope to a Session Bean

The scopes that CDI allows you to apply to a session bean depend on the type of the session bean as shown in Table 9-1.

Table 9-1 Allowed CDI Scopes for Session Beans

Session Bean Type Allowed Scopes

Singleton

Either of the following scopes:

  • Dependent

  • Application

Stateful

Any

Stateless

Dependent


For more information about scopes in CDI, see Defining the Scope of a Bean.

When CDI injects a reference to a stateful session bean, CDI creates the bean, injects the bean's fields, and manages the stateful session bean according to its scope. When the context is destroyed, CDI calls the stateful session bean's remove method to remove the bean.

Applying Qualifiers to a Session Bean

CDI allows you to apply any qualifier to a session bean. CDI does not restrict the type of qualifier that you can apply to a session bean. For more information about qualifiers in CDI, see Using Qualifiers.

Using Producer Methods, Disposer Methods, and Producer Fields

A producer method is a method that generates an object that can then be injected.

A disposer method enables an application to perform customized cleanup of an object that a producer method returns.

A producer field is a field of a bean that generates an object. A producer field is a simpler alternative to a producer method.

For more information, see Using Producer Methods and Fields in The Java EE 6 Tutorial.

Defining a Producer Method

A producer method enables an application to customize how CDI managed beans are created. This customization involves overriding the process that CDI normally uses to resolve beans. A producer method enables you to inject an object that is not an instance of a CDI bean class.

A producer method must be a method of a CDI bean class or session bean class. However, a producer method may return objects that are not instances of CDI bean classes. In this situation, the producer method must return an object that matches a bean type.

A producer method can have any number of parameters. If necessary, you can apply qualifiers to these parameters. All parameters of a producer method are injection points. Therefore, the parameters of a producer method do not require the @Inject annotation.

To define a producer method, annotate the declaration of the method with the javax.enterprise.inject.Produces annotation.

If the producer method sometimes returns null, set the scope of the method to dependent.

Note:

Calling a producer method directly in application code does not invoke CDI.

For an example of the definition of a producer method, see Example 9-11.

Defining a Disposer Method

If you require customized cleanup of an object that a producer method returns, define a disposer method in the class that declares the producer method.

To define a disposer method, annotate the disposed parameter in the declaration of the method with the javax.enterprise.inject.Disposes annotation. The type of the disposed parameter must be the same as the return type of the producer method.

A disposer method matches a producer method when the disposed object's injection point matches both the type and qualifiers of the producer method. You can define one disposer method to match to several producer methods in the class.

Example 9-11 shows how to use the @Produces annotation to define a producer method and the @Disposes annotation to define a disposer method.

Example 9-11 Defining a Producer Method and Disposer Method

This example defines the producer method connect and the disposer method close.

The producer method connect returns an object of type Connection. In the disposer method close, the parameter connection is the disposed parameter. This parameter is of type Connection to match the return type of the producer method.

At run time, the CDI framework creates an instance of SomeClass and then calls the producer method. Therefore, the CDI framework is responsible for injecting the parameters that are passed to the producer method.

The scope of the producer method is @RequestScoped. When the request context is destroyed, if the Connection object is in the request context, CDI calls the disposer method for this object. In the call to the disposer method, CDI passes the Connection object as a parameter.

import javax.enterprise.inject.Produces;
import javax.enterprise.inject.Disposes;

import javax.enterprise.context.RequestScoped;

public class SomeClass {
    @Produces @RequestScoped
    public Connection connect(User user) {
        return createConnection(user.getId(),
                user.getPassword());
    }
   
    private Connection createConnection(
            String id, String password) {...}
   
    public void close(@Disposes Connection connection) {
        connection.close();
    }
}

Defining a Producer Field

A producer field is a simpler alternative to a producer method. A producer field must be a field of a managed bean class or session bean class. A producer field may be either static or nonstatic, subject to the following constraints:

  • In a session bean class, the producer field must be a static field.

  • In a managed bean class, the producer field can be either static or nonstatic.

To define a producer field, annotate the declaration of the field with the javax.enterprise.inject.Produces annotation.

If the producer field may contain a null when accessed, set the scope of the field to dependent.

Note:

Using a producer field directly in application code does not invoke CDI.

Producer fields do not have disposers.

Initializing and Preparing for the Destruction of a Managed Bean

CDI managed bean classes and their superclasses support the annotations for initializing and preparing for the destruction of a managed bean. These annotations are defined in JSR 250: Common Annotations for the Java Platform. For more information, see Chapter 8, "Using Java EE Annotations and Dependency Injection".

Initializing a Managed Bean

Initializing a managed bean specifies the life cycle callback method that the CDI framework should call after dependency injection but before the class is put into service.

To initialize a managed bean:

  1. In the managed bean class or any of its superclasses, define a method that performs the initialization that you require.

  2. Annotate the declaration of the method with the javax.annotation.PostConstruct annotation.

    When the managed bean is injected into a component, CDI calls the method after all injection has occurred and after all initializers have been called.

    Note:

    As mandated by JSR 250, if the annotated method is declared in a superclass, the method is called unless a subclass of the declaring class overrides the method.

Preparing for the Destruction of a Managed Bean

Preparing for the destruction of a managed bean specifies the life cycle callback method that signals that an application component is about to be destroyed by the container.

To prepare for the destruction of a managed bean:

  1. In the managed bean class or any of its superclasses, define a method that prepares for the destruction of the managed bean.

    In this method, perform any cleanup that is required before the bean is destroyed, such a releasing resources that the bean has been holding.

  2. Annotate the declaration of the method with the javax.annotation.PreDestroy annotation.

    CDI calls the method before starting the logic for destroying the bean.

    Note:

    As mandated by JSR 250, if the annotated method is declared in a superclass, the method is called unless a subclass of the declaring class overrides the method.

Intercepting Method Invocations and Life Cycle Events of Bean Classes

Intercepting a method invocation or a life cycle event of a bean class interposes an interceptor class in the invocation or event. When an interceptor class is interposed, additional actions that are defined in the interceptor class are performed. An interceptor class simplifies the maintenance of code for tasks that are frequently performed and are separate from the business logic of the application. Examples of such tasks are logging and auditing.

Note:

The programming model for interceptor classes is optimized for operations that are separate from the business logic of the application. To intercept methods that perform operations with business semantics, use a decorator class as explained in Decorating a Managed Bean Class.

The interceptors that were introduced in the Java EE 5 specification are specific to EJB components. For more information about Java EE 5 interceptors, see "Specifying Interceptors for Business Methods or Life Cycle Callback Events" in Developing Enterprise JavaBeans for Oracle WebLogic Server.

CDI enables you to use interceptors with the following types of Java EE managed objects:

  • CDI managed beans

  • EJB session beans

  • EJB message-driven beans

Note:

You cannot use interceptors with EJB entity beans because CDI does not support EJB entity beans.

For more information, see Using Interceptors in The Java EE 6 Tutorial.

Intercepting method invocations and life cycle events of bean classes involves the tasks that are explained in the following sections:

Defining an Interceptor Binding Type

An interceptor binding type is an application-defined annotation that associates an interceptor class with an intercepted bean. Define an interceptor binding type for each type of interceptor that you require.

Note:

CDI does not require an interceptor binding type to be unique to a particular interceptor class. You can define an interceptor binding type to use for more than one interceptor class.

To define an interceptor binding type:

  1. Define a Java annotation type to represent the interceptor binding type.

  2. Annotate the declaration of the annotation type with the javax.interceptor.InterceptorBinding annotation.

  3. Specify that the interceptor binding type is to be retained by the virtual machine at run time.

    Use the java.lang.annotation.Retention(RUNTIME) meta-annotation for this purpose.

  4. Specify that the interceptor binding type may be applied to the program elements METHOD and TYPE.

    Use the java.lang.annotation.Target({METHOD, TYPE}) meta-annotation for this purpose.

Example 9-12 Defining An Interceptor Binding Type

This example defines the @Transactional interceptor binding type.

package com.example.billpayment.interceptor;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.interceptor.InterceptorBinding;

@InterceptorBinding
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface Transactional {}

Defining an Interceptor Class

An interceptor class is used to interpose in method invocations or life cycle events that occur in an associated target bean class. In an interceptor class, provide the code for tasks that are frequently performed and are separate from the business logic of the application, such as logging and auditing.

To define an interceptor class:

  1. Define a Java class to represent the interceptor.

  2. Annotate the declaration of the class with the following annotations:

    • javax.interceptor.Interceptor

    • The interceptor binding types that are defined for the class

      You can apply any number of interceptor binding types to an interceptor class.

      Note:

      CDI does not require an interceptor binding type to be unique to a particular interceptor class. You can apply the same interceptor binding type to multiple interceptor classes.

  3. Implement the interceptor methods in the class.

    CDI does not require the signature of an interceptor method to match the signature of the intercepted method.

  4. Identify the interceptor methods in the class.

    An interceptor method is the method that is invoked when a method invocation or a life cycle event of a bean class is intercepted.

    To identify an interceptor method, annotate the declaration of the method with the appropriate annotation for the type of the interceptor method.

    Interceptor Method Type Annotation

    Method invocation

    javax.interceptor.AroundInvoke

    EJB timeout

    javax.interceptor.AroundTimeout

    Initialization of a managed bean or EJB component

    javax.annotation.PostConstruct

    Destruction of a managed bean or EJB component

    javax.annotation.PreDestroy

    Activation of a stateful session bean

    javax.ejb.PostActivate

    Passivation of a stateful session bean

    javax.ejb.PrePassivate


    Note:

    An interceptor class can have multiple interceptor methods. However, an interceptor class can have no more than one interceptor method of a given type.

Example 9-13 shows how to define an interceptor class.

Example 9-13 Defining an Interceptor Class

This example defines the interceptor class for which the @Transactional interceptor binding type is defined. The manageTransaction method of this class is an interceptor method. The @Transactional interceptor binding is defined in Example 9-12.

package com.example.billpayment.interceptor;

import javax.annotation.Resource;
import javax.interceptor.*;
...
@Transactional @Interceptor
public class TransactionInterceptor {
    @Resource UserTransaction transaction;
    @AroundInvoke
    public Object manageTransaction(InvocationContext ctx)
            throws Exception {
        ...
    }
}

Identifying Methods for Interception

Identifying methods for interception associates the methods with the interceptor that is invoked when the methods are invoked. CDI enables you to identify all methods of a bean class or only individual methods of a bean class for interception.

  • To identify all methods of a bean class for interception, annotate the declaration of the bean class with the appropriate interceptor binding type.

  • To identify an individual method of a bean class for interception, annotate the declaration of the method with the appropriate interceptor binding type.

CDI does not require the signature of an intercepted method to match the signature of the interceptor method. To determine the arguments and return type of an intercepted method, an interceptor must query an interceptor context. Therefore, you can intercept any method or life cycle event in a bean class without any knowledge at compilation time of the interfaces of bean class.

Note:

An implementation of a Java EE 5 interceptor must be declared in the annotation on the method that is to be intercepted. A CDI interceptor uses an interceptor binding to identify an interceptor method and to relate an intercepted method to its interceptor method. Both the intercepted method and the interceptor method must be annotated with the binding. In this way, the intercepted method and the interceptor are related to each other only through the interceptor binding.

Example 9-14 Identifying All Methods of a Bean Class for Interception

This example identifies all methods of the ShoppingCart class for interception by the @Transactional interceptor.

package com.example.billpayment.interceptor;

@Transactional
public class ShoppingCart {
    ...
}

Example 9-15 Identifying an Individual Method of a Class for Interception

This example identifies only the checkout method of the ShoppingCart class for interception by the @Transactional interceptor.

package com.example.billpayment.interceptor;

public class ShoppingCart {
    ...
    @Transactional public void checkout() {
    ...
    }
}

Enabling an Interceptor

By default, an interceptor is disabled. If you require an interceptor to be interposed in method invocations and events, you must enable the interceptor explicitly.

To enable an interceptor:

  1. Add a class element for the interceptor to the interceptors element in the beans.xml file.

  2. In the class element, provide the fully qualified class name of the interceptor.

    Ensure that the order of t he class elements in the beans.xml file matches the order in which the interceptors are to be invoked.

    CDI interceptors are invoked in the order in which they are declared in the beans.xml file. Interceptors that are defined in the ejb-jar.xml file or by the javax.interceptor.Interceptors annotation are called before the CDI interceptors. Interceptors are called before CDI decorators.

    Note:

    Java EE 5 interceptors are invoked in the order in which they are annotated on an intercepted method.

For more information about the beans.xml file, see Configuring a CDI Application.

Example 9-16 shows a class element in the beans.xml file for enabling an interceptor class.

Example 9-16 Enabling an Interceptor Class

This example enables the interceptor class com.example.billpayment.interceptor.TransactionInterceptor. The interceptor class is defined in Example 9-13.

...
<interceptors>
    <class>com.example.billpayment.interceptor.TransactionInterceptor</class>
</interceptors>
...

Decorating a Managed Bean Class

Decorating a managed bean class enables you to intercept invocations of methods in the decorated class that perform operations with business semantics. You can decorate any managed bean class.

Note:

The programming model for decorator classes is optimized for operations that perform the business logic of the application. To intercept methods that are separate from the business logic of an application, use an interceptor class as explained in Intercepting Method Invocations and Life Cycle Events of Bean Classes.

For more information, see Using Decorators in The Java EE 6 Tutorial.

Decorating a managed bean class involves the tasks that are explained in the following sections:

Defining a Decorator Class

A decorator class intercepts invocations of methods in the decorated class that perform operations with business semantics. A decorator class and an interceptor class are similar because both classes provide an around-method interception. However, a method in a decorator class has the same signature as the intercepted method in the decorated bean class.

To define a decorator class:

  1. Write a Java class that implements the same interface as the bean class that you are decorating.

    If you want to intercept only some methods of the decorated class, declare the decorator class as an abstract class. If you declare the class as abstract, you are not required to implement all the methods of the bean class that you are decorating.

  2. Annotate the class declaration of the decorator class with the javax.decorator.Decorator annotation.

  3. Implement the methods of the decorated bean class that you want to intercept.

    If the decorator class is a concrete class, you must implement all the methods of the bean class that you are decorating.

    You must ensure that the intercepting method in a decorator class has the same signature as the intercepted method in the decorated bean class.

  4. Add a delegate injection point to the decorator class.

    A decorator class must contain exactly one delegate injection point. A delegate injection point injects a delegate object, which is an instance of the decorated class, into the decorator object.

    You can customize how any method in the decorator object handles the implementation of the decorated method. CDI allows but does not require the decorator object to invoke the corresponding delegate object. Therefore, you are free to choose whether the decorator object invokes the corresponding delegate object.

    1. In the decorator class, inject an instance of the bean class that you are decorating.

    2. Annotate the injection point with the javax.decorator.Delegate annotation.

    3. Apply qualifiers that you require to the injection point, if any.

      If you apply qualifiers to the injection point, the decorator applies only to beans whose bean class matches the qualifiers of the injection point.

Note:

No special declaration, such as an annotation, is required to define a decorated bean class. An enabled decorator class applies to any bean class or session bean that matches the bean type and qualifiers of the delegate injection point.

Example 9-17 shows the definition of a decorator class.

Example 9-17 Defining a Decorator Class

This example defines the decorator class DataAccessAuthDecorator. This class decorates any bean of type DataAccess.

Because only some methods of the decorated class are to be intercepted, the class is declared as an abstract class. This class injects a delegate instance delegate of the decorated implementation of the DataAcess bean type.

import javax.decorator.*;
import javax.inject.Inject;
import java.lang.Override;
...
@Decorator
public abstract class DataAccessAuthDecorator
        implements DataAccess {
       
    @Inject @Delegate DataAccess delegate;
 
    @Override
    public void delete(Object object) {
        authorize(SecureAction.DELETE, object);
        delegate.delete(object);
    }
 
    private void authorize(SecureAction action, Object object) {
        ...
    }
}

Enabling a Decorator Class

By default, a decorator class is disabled. If you require a decorator class to be invoked in a CDI application, you must enable the decorator class explicitly.

To enable an decorator class:

  1. Add a class element for the decorator class to the decorators element in the beans.xml file.

  2. In the class element, provide the fully qualified class name of the decorator class.

    Ensure that the order of the class elements in the beans.xml file matches the order in which the decorator classes are to be invoked.

Note:

Any interceptor classes that are defined for an application are invoked before the application's decorator classes.

For more information about the beans.xml file, see Configuring a CDI Application.

Example 9-18 shows a class element in the beans.xml file for enabling a decorator class.

Example 9-18 Enabling a Decorator Class

This example enables the decorator class com.example.billpayment.decorator.DataAccessAuthDecorator.

...
<decorators>
     <class>com.example.billpayment.decorator.DataAccessAuthDecorator</class>
</decorators>
...

Assigning an EL Name to a CDI Bean Class

EL enables components in the presentation layer to communicate with managed beans that implement application logic. Components in the presentation layer are typically JavaServer Faces (JSF) pages and JavaServer Pages (JSP) pages. For more information, see "JSP Expression Language" in Developing Web Applications, Servlets, and JSPs for Oracle WebLogic Server.

In the scripting languages in JSP pages and JSF pages, the syntax of an injected variable is identical to the syntax of a built-in variable of these languages. Any CDI bean that is injected into a JSP page or JSF page must be accessible through an EL name. For more information, see Giving Beans EL Names in The Java EE 6 Tutorial.

To assign an EL name to a CDI bean class, annotate the class declaration of the bean class with the javax.inject.Named annotation.

If you do not specify a name, the EL name is the unqualified class name with the first character in lower case. For example, if the unqualified class name is ShoppingCart, the EL name is shoppingCart.

To specify a name, set the value element of the @Named annotation to the name that you require.

Note:

To assign an EL name to a CDI bean class, you must annotate the bean class declaration with the @Named annotation. If the class is not annotated with @Named, the CDI bean class does not have an EL name.

Example 9-19 shows how to use the @Named annotation to assign an EL name to a CDI bean class.

Example 9-19 Assigning an EL Name to a Bean Class

This example assigns the EL name cart to the ShoppingCart class.

import javax.enterprise.context.SessionScoped;


@SessionScoped
@Named("cart")
public class ShoppingCart {
    public String getTotal() {
       ...
    }
   
    ...
}

Any bean that a JSP page or JSF page accesses must conform to the JavaBeans standard. To access a CDI managed bean from a JSP page or JSF page through the bean's EL name, use a syntax that is similar to the syntax for JavaBeans components.

Example 9-20 shows how an instance of the ShoppingCart class is accessed in a JSF page through the EL name that is assigned to the class.

Example 9-20 Accessing a Bean Through its EL Name

This example accesses an instance of the ShoppingCart class to display the value of its total property in a JSF page.

This property is returned by the getTotal getter method of the ShoppingCart class as shown in Example 9-19.

...
<h:outputText value="#{cart.total}"/>
...

Defining and Applying Stereotypes

In a large application in which several beans perform similar functions, you may require the same set of annotations to be applied to several bean classes. Defining a stereotype requires you to define the set of annotations only once. You can then use the stereotype to guarantee that the same set of annotations is applied to all bean classes that require the annotations. For more information, see Using Stereotypes in The Java EE 6 Tutorial.

Defining and applying stereotypes involves the tasks that are explained in the following sections:

Defining a Stereotype

A stereotype is an application-defined annotation type that incorporates other annotation types.

To define a stereotype:

  1. Define a Java annotation type to represent the stereotype.

  2. Annotate the declaration of the annotation type with the following annotations:

  3. Specify that the stereotype is to be retained by the virtual machine at run time.

    Use the java.lang.annotation.Retention(RUNTIME) meta-annotation for this purpose.

  4. Specify that the stereotype may be applied to the program element TYPE.

    Use the java.lang.annotation.Target(TYPE) meta-annotation for this purpose.

The following example shows the definition of a stereotype.

Example 9-21 Defining a Stereotype

This example defines the stereotype @Action, which specifies the following for each bean that the stereotype annotates:

  • The default scope is request scope unless the scope is overridden with a scope annotation.

  • The default EL name is assigned to the bean unless the name is overridden with the @Named annotation.

  • The interceptor bindings @Secure and @Transactional are applied to the bean. The definition of these interceptor bindings is beyond the scope of this example.

import javax.enterprise.inject.Stereotype;
import javax.inject.Named;
import javax.enterprise.context.RequestScoped; 
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@RequestScoped
@Secure
@Transactional
@Named
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface Action {}

Applying Stereotypes to a Bean

To apply stereotypes to a bean, annotate the class declaration of the bean with each stereotype to apply. You can apply any number of stereotypes to a bean. Any stereotype that you apply to a bean must be defined as explained in Defining a Stereotype.

Example 9-22 shows how to apply stereotypes to a bean.

Example 9-22 Applying Stereotypes to a Bean

This example applies the stereotypes @Action and @Mock to the bean class MockLoginAction. The definition of the @Action stereotype is shown in Example 9-21. The definition of the @Mock stereotype is beyond the scope of this example.

@Action
@Mock
public class MockLoginAction extends LoginAction {
 ... 
}

Using Events for Communications Between Beans

At run time, your application may perform operations that generate information or cause state changes that must be communicated between beans. For example, an application may require stateful beans in one architectural tier of the application to synchronize their internal state with state changes that occur in a different tier.

Events enable beans to communicate this information without any compilation-time dependency. One bean can define an event, another bean can send the event, and yet another bean can handle the event. The beans can be in separate packages and even in separate tiers of the application. For more information, see Using Events in The Java EE 6 Tutorial.

Using events for communications between beans involves the tasks that are explained in the following sections:

Defining an Event Type

An event type is a Java class that represents the information that you want to communicate between beans. For example, an event type may represent the state information that a stateful bean must synchronize with state changes in a different tier of an application.

Define an event type for each set of changes that you want to communicate between beans.

To define an event type:

  1. Define a Java class to represent the event type.

    Ensure that the class meets these requirements:

    • The class is declared as a concrete Java class.

    • The class has no type variables.

      The event types of the event include all superclasses and interfaces of the run time class of the event object. An event type must not contain a type variable. Any Java type can be an observed event type.

  2. If necessary, define any qualifiers to further distinguish events of this type. For more information, see Defining Qualifiers for Implementations of a Bean Type.

  3. Provide code in the class to populate the event payload of event objects that are instantiated from the class.

    The event payload is the information that you want the event to contain. You can use a JavaBeans property with getter and setter methods to represent an item of information in the event payload.

Sending an Event

To communicate a change that occurs in response to an operation, your application must send an event of the correct type when performing the operation. CDI provides a predefined event dispatcher object that enables application code to send an event and select the associated qualifiers at run time.

To send an event:

  1. Obtain an instance of the event type to send.

  2. Call methods of the event instance to populate the event payload of the event object that you are sending.

  3. Inject an instance of the parameterized javax.enterprise.event.Event interface.

    If you are sending a qualified event, annotate the injection point with the event qualifier.

  4. Call the fire method of the injected Event instance.

    In the call to the fire method, pass as a parameter the event instance that you are sending.

Example 9-23 shows how to send an event.

Example 9-23 Sending an Event

This example injects an instance of the event of type User with the qualifier @LoggedIn. The fire method sends only User events to which the @LoggedIn qualifier is applied.

import javax.enterprise.event.Event;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import java.io.Serializable;

@SessionScoped
public class Login implements Serializable {
 
    @Inject @LoggedIn Event<User> userLoggedInEvent;
    private User user;
   
    public void login(Credentials credentials) {
   
        //... use credentials to find user
       
        if (user != null) {
            userLoggedInEvent.fire(user);
        }
    }
    ...
}

Handling an Event

Any CDI managed bean class can handle events.

To handle an event:

  1. In your bean class, define a method to handle the event.

    Note:

    If qualifiers are applied to an event type, define one method for each qualified type.

  2. In the signature of the method, define a parameter for passing the event to the method.

    Ensure that the type of the parameter is the same as the Java type of the event.

  3. Annotate the parameter in the method signature with the javax.enterprise.event.Observes annotation.

    If necessary, set elements of the @Observes annotation to specify whether the method is conditional or transactional. For more information, see Using Observer Methods to Handle Events in The Java EE 6 Tutorial.

  4. If the event type is qualified, apply the qualifier to the annotated parameter.

  5. In the method body, provide code for handling the event payload of the event object.

Example 9-24 shows how to declare an observer method for receiving qualified events of a particular type. Example 9-25 shows how to declare an observer method for receiving all events of a particular type.

Example 9-24 Handling a Qualified Event of a Particular Type

This example declares the afterLogin method in which the parameter user is annotated with the @Observes annotation and the @LoggedIn qualifier. This method is called when an event of type User with the qualifier @LoggedIn is sent.

import javax.enterprise.event.Observes;

    public void afterLogin(@Observes @LoggedIn User user) {
        ...
    }

Example 9-25 Handling Any Event of a Particular Type

This example declares the afterLogin method in which the parameter user is annotated with the @Observes annotation. This method is called when any event of type User is sent.

import javax.enterprise.event.Observes;

    public void afterLogin(@Observes User user) {
        ...
    }

Injecting a Predefined Bean

CDI provides predefined beans that implement the following interfaces:

javax.transaction.UserTransaction

Java Transaction API (JTA) user transaction.

java.security.Principal

The abstract notion of a principal, which represents any entity, such as an individual, a corporation, and a login ID.

The principal represents the identity of the current caller. Whenever the injected principal is accessed, it always represents the identity of the current caller.

For example, a principal is injected into a field at initialization. Later, a method that uses the injected principal is called on the object into which the principal was injected. In this situation, the injected principal represents the identity of the current caller when the method is run.

javax.validation.Validator

Validator for bean instances.

The bean that implements this interface enables a Validator object for the default bean validation ValidatorFactory object to be injected.

javax.validation.ValidatorFactory

Factory class for returning initialized Validator instances.

The bean that implements this interface enables the default bean validation ValidatorFactory object to be injected.

To inject a predefined bean, create an injection point by using the javax.annotation.Resource annotation to obtain an instance of the bean. For the bean type, specify the class name of the interface that the bean implements.

Predefined beans are injected with dependent scope and the predefined default qualifier @Default.

For more information about injecting resources, see Resource Injection in The Java EE 6 Tutorial.

Example 9-26 shows how to use the @Resource annotation to inject a predefined bean.

Example 9-26 Injecting a Predefined Bean

This example injects a user transaction into the servlet class TransactionServlet. The user transaction is an instance of the predefined bean that implements the javax.transaction.UserTransaction interface.

import javax.annotation.Resource;
import javax.servlet.http.*;
...
public class TransactionServlet extends HttpServlet {
    @Resource UserTransaction transaction;
        ...
}

Injecting and Qualifying Resources

Java EE 5 resource injection relies on strings for configuration. Typically, these strings are JNDI names that are resolved when an object is created. CDI ensures type-safe injection of beans by selecting the bean class on the basis of the Java type that is specified in the injection point.

Even in a CDI bean class, Java EE 5 resource injection is required to access real resources such as data sources, Java Message Service (JMS) resources, and Web service references. Because CDI bean classes can use Java EE 5 resource injection, you can use producer fields to minimize the reliance on Java EE 5 resource injection. In this way, CDI simplifies how to encapsulate the configuration that is required to access the correct resource.

To minimize the reliance on Java EE 5 resource injection:

  1. Use Java EE 5 resource injection in only one place in the application.

  2. Use producer fields to translate the injected resource type into a CDI bean.

    You can the inject this CDI bean into the application in the same way as any other CDI bean.

    For more information about producer fields, see Defining a Producer Field.

Example 9-27 shows how to use Java EE 5 annotations to inject resources. Example 9-28 shows how to inject the same set of resources by combining Java EE 5 resource injection with CDI producer fields.

Example 9-27 Using Java EE 5 Annotations to Inject Resources

import javax.annotation.Resource;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;
import javax.ejb.EJB;
import javax.xml.ws.WebServiceRef;
...
public class SomeClass {
 
    @WebServiceRef(lookup="java:app/service/PaymentService")
    PaymentService paymentService;
   
    @EJB(ejbLink="../payment.jar#PaymentService")
    PaymentService paymentService;
   
    @Resource(lookup="java:global/env/jdbc/CustomerDatasource")
    Datasource customerDatabase;
   
    @PersistenceContext(unitName="CustomerDatabase")
    EntityManager customerDatabasePersistenceContext;
   
    @PersistenceUnit(unitName="CustomerDatabase")
    EntityManagerFactory customerDatabasePersistenceUnit;
   
    ...
}

Example 9-28 Combining Java EE 5 Resource Injection With Producer Fields

The declaration of the SomeClass class is annotated with @ApplicationScoped to set the scope of this bean to application. The @Dependent scope is implicitly applied to the producer fields.

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.annotation.Resource;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;
import javax.ejb.EJB;
javax.xml.ws.WebServiceRef;
...
@ApplicationScoped
public class SomeClass {
 
    @Produces
    @WebServiceRef(lookup="java:app/service/PaymentService")
    PaymentService paymentService;
   
    @Produces
    @EJB(ejbLink="../their.jar#PaymentService")
    PaymentService paymentService;
   
    @Produces @CustomerDatabase
    @Resource(lookup="java:global/env/jdbc/CustomerDatasource")
    Datasource customerDatabase;
   
    @Produces @CustomerDatabase
    @PersistenceContext(unitName="CustomerDatabase")
    EntityManager customerDatabasePersistenceContext;
   
    @Produces @CustomerDatabase
    @PersistenceUnit(unitName="CustomerDatabase")
    EntityManagerFactory customerDatabasePersistenceUnit;
    ...
}

CDI enables you to use Java EE resources in CDI applications in a way that is consistent with CDI. To use Java EE resources in this way, inject the resources as CDI beans into other beans.

Example 9-29 shows how to inject a Java EE resource as a CDI bean into another bean.

Example 9-29 injecting a Java EE Resource as a CDI Bean Into Another Bean

This example injects a persistence unit resource into a request-scoped bean.

import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Inject;

@RequestScoped
public class SomeOtherClass { 
    ...
    @Inject @CustomerDatabase
    private EntityManagerFactory emf;
    ...
}

Another class, for example YetAnotherClass, could inject a field of type SomeOtherClass. If an instance of SomeOtherClass does not already exist in the current request context, CDI performs the following sequence of operations:

  1. Constructing the instance of SomeOtherClass

  2. Injecting the reference to the entity manager factory by using the producer field from Example 9-28

  3. Saving the new instance of SomeOtherClass in the current request context

In every case, CDI injects the reference to this instance of SomeOtherClass into the field in YetAnotherClass. When the request context is destroyed, the instance of SomeOtherClass and its reference to the entity manager factory are destroyed.

Using CDI With JCA Technology

WebLogic Server supports CDI in embedded resource adapters and global resource adapters. To enable a resource adapter for CDI, provide a beans.xml file in the META-INF directory of the packaged archive of the resource adapter. For more information about the beans.xml file, see Configuring a CDI Application.

All classes in the resource adapter are available for injection. All classes in the resource adapter can be CDI managed beans except for the following classes:

Configuring a CDI Application

Configuring a CDI application enables CDI services for the application.You must configure a CDI application to identify the application as a CDI application. No special declaration, such as an annotation, is required to define a CDI managed bean. And no module type is defined specifically for packaging CDI applications.

To configure a CDI application, provide a file that is named beans.xml in the packaged archive of the application. The beans.xml file must be an instance of the extensible markup language (XML) schema beans_1_0.xsd.

If your application does not use any alternatives, interceptors, or decorators, the beans.xml file can be empty. However, you must provide the beans.xml file even if the file is empty.

If your CDI application uses alternatives, interceptors, or decorators, you must enable these items by declaring them in the beans.xml file. For more information, see:

The required location of the beans.xml file depends on the type of the application:

  • For a Web application, the beans.xml file must be in the WEB-INF directory.

  • For an EJB module, resource archive (RAR) file, application client JAR file, or library JAR file, the beans.xml file must be in the META-INF directory.

You can provide CDI bean archives in the lib directory of an EJB module. You must provide a beans.xml file in the META-INF directory of each CDI bean archive the lib directory of an EJB module.

Example 9-30 shows a beans.xml file for configuring a CDI application.

Example 9-30 beans.xml File for Configuring a CDI Application

This example configures a CDI application by enabling the following classes:

  • The alternative implementation com.example.orderprocessor.MockOrderImpl

  • The interceptor class com.example.billpayment.interceptor.TransactionInterceptor

  • The decorator class com.example.billpayment.decorator.DataAccessAuthDecorator

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
      http://java.sun.com/xml/ns/javaee 
      http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<alternatives>
    <class>com.example.orderprocessor.MockOrderImpl</class>
</alternatives>
<interceptors>
    <class>com.example.billpayment.interceptor.TransactionInterceptor</class>
</interceptors>
<decorators>
    <class>com.example.billpayment.decorator.DataAccessAuthDecorator</class>
</decorators>
</beans>

Supporting Third-Party Portable Extensions

CDI is intended to be a foundation for frameworks, extensions, and integration with other technologies. Therefore, CDI exposes SPIs that enable the development of portable extensions to CDI, such as:

  • Integration with business process management engines

  • Integration with third-party frameworks such as Spring, Seam, GWT or Wicket

  • New technology that is based upon the CDI programming model

The SPIs that enable the development of portable extensions to CDI are provided in the javax.enterprise.inject.spi package.

Code in CDI extensions can handle events that are sent by the CDI framework.

For more information, see "Portable extensions" in JSR 299: Contexts and Dependency Injection for the Java EE platform.