9 Using Contexts and Dependency Injection for the Jakarta EE Platform
About CDI for the Jakarta EE Platform
CDI for the Jakarta EE Platform specification was formerly called Web Beans. CDI injection simplifies the use of managed beans with JSF technology in Web applications.
WebLogic Server 26.1 implements Jakarta Contexts and Dependency Injection 4.1 for Jakarta EE 11. CDI integrates with Jakarta Dependency Injection 2.0, Jakarta Interceptors 2.2, Jakarta Annotations 3.0 and the applicable Jakarta EE component specifications. CDI managed beans are defined by CDI; they are distinct from the former Jakarta Managed Beans specification. Jakarta Contexts and Dependency Injection 4.1 Jakarta Dependency Injection 2.0 Jakarta Interceptors 2.2 Jakarta Annotations 3.0
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 Jakarta EE, namely:
-
Servlets
-
Jakarta Server Pages (JSP)
-
Jakarta Server Faces (JSF)
-
Jakarta Enterprise Beans (EJB)
-
Jakarta EE Connector architecture (JCA)
-
Web services
Such integration enables standard Jakarta 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.
Some links in this chapter provide historical Java EE 8 tutorial background. For this release, use the jakarta.* APIs and CDI 4.1 discovery and configuration rules described here; consult the Jakarta CDI 4.1 specification for the current contract. Jakarta CDI 4.1 specification
See Introduction to Contexts and Dependency Injection for the Java EE Platform in the Java EE 8 Tutorial.
CDI 2.0 Examples
The optional WebLogic Server examples include demonstrations of asynchronous events, observer ordering and InterceptionFactory, features introduced in CDI 2.0. The sample directories retain their historical javaee8 names; the current source uses Jakarta APIs.
-
Asynchronous Events – Demonstrates how to produce async events and how singleton EJBs can consume these events.
-
Observer Ordering – Demonstrates how singleton EJBs can consume events according to the priority.
-
Interception Factory – Demonstrates how to produce a class instance with adding the specified annotation dynamically by InterceptionFactory.
For more information, see the CDI 2.0 examples in the WebLogic Server distribution kit: ORACLE_HOME\wlserver\samples\server\examples\src\examples\javaee8\cdi where ORACLE_HOME represents the directory in which you installed WebLogic Server. See Sample Applications and Code Examples in Understanding Oracle WebLogic Server.
CDI 1.1 Example
A sample originating with Java EE 7 demonstrates CDI features in the historically named javaee7 directory. Installed sample location:ORACLE_HOME\wlserver\samples\server\examples\src\examples\javaee7\cdi where ORACLE_HOME represents the directory in which you installed WebLogic Server. See Sample Applications and Code Examples in Understanding Oracle WebLogic Server.
These paths are present when the samples component is installed; see Sample Applications and Code Examples for installation and execution instructions.
Defining a Managed Bean
A managed bean is the basic component in a CDI application and defines the beans that CDI can create and manage.
A bean is a source of the objects that CDI can create and manage. See About Beans in The Java EE 8 Tutorial .
A CDI managed-bean class must satisfy the CDI 4.1 managed-bean requirements, including the constructor, nesting and class-kind restrictions. It may have a no-argument constructor or an appropriate @Inject constructor. See Which Java Classes Are Managed Beans? in the CDI 4.1 specification. Which Java Classes Are Managed Beans?
Note:
Eligibility and discovery are separate. With annotated discovery, give the class a bean-defining annotation, such as @Dependent or a normal scope. @Named, @Alternative and a custom qualifier by themselves are not bean-defining annotations. An explicit bean archive with bean-discovery-mode=all can discover eligible classes without such annotations.Injecting a Bean
To use the beans that you define, inject them into another bean that an application such as a Jakarta Server Faces can use.
See Injecting Beans in The Java EE 8 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 the resource injection that was introduced in the Java EE 5 specification, which selects the resource to inject from the string name of the resource. For example, a data source that is injected with the jakarta.annotation.Resource annotation is identified by its string name.
Create an injection point by annotating an instance field, a bean constructor, or an initializer method with jakarta.inject.Inject. Constructor and initializer-method parameters receive their dependencies because their enclosing constructor or method is annotated; annotate the parameters with qualifiers when selection requires them.
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 jakarta.inject.Inject;
...
public class Printer {
@Inject Greeting greeting;
...
}Defining the Scope of a Bean
A scope determines the lifecycle of a bean’s contextual instances and how references resolve to those instances. Choose it for the state and lifetime required by the application; using injection does not itself require conversational state.
To define the scope of a bean, annotate the class declaration of the bean with the scope. The jakarta.enterprise.context package defines the following scopes:
-
@RequestScoped -
@SessionScoped -
@ApplicationScoped -
@ConversationScoped -
@Dependent
For information about these scopes, see Using Scopes in The Java EE 8 Tutorial .
If no explicit scope or stereotype-supplied default scope applies, the bean’s default scope is @Dependent. A dependent instance injected into another contextual instance is normally destroyed with its owning instance. The other listed scopes are normal scopes, generally accessed through client proxies that resolve the instance for the active context. A session-scoped instance, for example, belongs to an HTTP session.
For a normal-scoped bean, obtaining an injected reference need not immediately create its contextual instance; the proxy obtains the instance when used in the active context.
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 jakarta.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. See Using Qualifiers in The Java EE 8 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 when the application needs to distinguish beans or injection requirements. Qualifiers can be used with alternatives and may be shared by several beans. Every bean has @Any. A bean also has @Default when it declares no qualifier other than @Named and/or @Any.
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:
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 jakarta.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 jakarta.inject.Qualifier;
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface PeopleManager {}Applying Qualifiers to a Bean
Apply qualifiers to a bean class or producer to declare its selection metadata. An injection point without an explicit qualifier requires @Default; its Inject annotation is not a qualifier.
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.
For each injection point, CDI finds available enabled beans assignable to the required type and matching all required qualifiers, then applies the alternative/priority ambiguity-resolution rules. An unsatisfied dependency or an ambiguity that those rules cannot resolve is a deployment problem. Selecting an alternative does not globally disable every other bean of that Java type; another qualifier can still select a different bean.
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:
-
Accountant, which is shown in Example 9-5 -
Boss, which is shown in Example 9-6
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 jakarta.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. By providing alternative implementations of a bean type, you can modify an application at deployment time to meet such differing requirements.
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.
CDI enables you to select from any number of alternative bean type implementations for injection instead of a corresponding primary implementation. See Using Alternatives in CDI Applications in The Java EE 8 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:
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 jakarta.enterprise.inject.Alternative;
@Alternative
public class MockOrderImpl implements Order {
...
}Selecting an Alternative Implementation of a Bean Type for an Application
An @Alternative bean is disabled unless selected. Listing an alternative class in a bean archive’s beans.xml selects it for that bean archive. For application-wide selection, an alternative can instead use jakarta.annotation.Priority according to the CDI rules. The alternative must match the required types and qualifiers.
To select an alternative for a bean archive:
- Add a
classelement for the alternative to thealternativeselement in thebeans.xmlfile. - In the
classelement, provide the fully qualified class name of the alternative.
For more information about the beans.xml file, see Configuring a CDI Application.
Example 9-10 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>
...This descriptor-based example intentionally demonstrates archive-local selection; do not also enable it through priority merely to repeat this example.
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:
-
jakarta.ejb.Singleton, which denotes a singleton session bean -
jakarta.ejb.Stateful, which denotes a stateful session bean -
jakarta.ejb.Stateless, which denotes a stateless session bean
-
-
The bean is listed in the
ejb-jar.xmldeployment-descriptor file.
For more information about session beans, see:
Developing Enterprise JavaBeans Using Deployment Descriptors for Oracle WebLogic Server
See the following sections:
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:
|
|
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.
See Jakarta Contexts and Dependency Injection: Advanced Topics in the Jakarta EE 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 jakarta.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
A disposer method performs cleanup for objects produced by producer methods or producer fields declared by the same bean class. Mark exactly one disposed parameter with jakarta.enterprise.inject.Disposes. CDI resolves a disposer using the disposed parameter’s required type and qualifiers and the CDI assignability rules. A disposer can match several producers in that class; a producer must not resolve to more than one disposer. Other disposer parameters are injection points.
Example 9-11 shows how to use the @Produces annotation to define a producer method and the @Disposes annotation to define a disposer method.
Configure a JDBC data source bound as jdbc/CustomerDB before deploying this example. CDI discovers SomeClass through @Dependent. On the first use requiring a contextual Connection during a request, connect obtains a connection from that configured data source. The connection is request-scoped; its matching disposer closes it when that contextual instance is destroyed. The data source itself remains container-managed. This example does not define application authentication or transaction boundaries.
Example 9-11 Defining a Producer Method and Disposer Method
package com.example.resources;
import jakarta.annotation.Resource;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.context.RequestScoped;
import jakarta.enterprise.inject.Disposes;
import jakarta.enterprise.inject.Produces;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
@Dependent
public class SomeClass {
@Resource(lookup = "jdbc/CustomerDB")
private DataSource dataSource;
@Produces @RequestScoped
public Connection connect() throws SQLException {
return dataSource.getConnection();
}
public void close(@Disposes Connection connection) throws SQLException {
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 jakarta.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 can have matching disposer methods under the same resolution rules.
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 Jakarta Annotations 3.0: Common Annotations for the Java Platform. For more information, see Using Jakarta 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:
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 Jakarta 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.
See Using Jakarta EE Interceptors in the Jakarta EE 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.
com.example.billpayment.interceptor.Transactional is an application-defined binding used only to illustrate binding resolution. It is different from jakarta.transaction.Transactional and does not itself supply transaction semantics.
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:
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 jakarta.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:
Example 9-13 shows how to define an interceptor class.
This pass-through example continues the invocation and returns its result. Use the applicable Jakarta Transactions/EJB facilities when actual transaction boundaries are required.
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 jakarta.interceptor.AroundInvoke;
import jakarta.interceptor.Interceptor;
import jakarta.interceptor.InvocationContext;
@Transactional
@Interceptor
public class TransactionInterceptor {
@AroundInvoke
public Object manageTransaction(InvocationContext context) throws Exception {
return context.proceed();
}
}
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. Interception applies to eligible container invocations and supported lifecycle callbacks under the CDI and Interceptors rules; it does not intercept arbitrary direct Java calls or every private/static/final method.
Note:
For interceptor-binding resolution, place the binding on the interceptor class and on the target class or eligible target method. The interceptor method is identified by @AroundInvoke or the applicable lifecycle annotation; it does not need the binding annotation. Alternatively, @Interceptors names interceptor classes directly on the supported target class or method. Bindings provide the indirect association illustrated here.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.
The following procedure enables this class for a bean archive using beans.xml. Alternatively, @Priority enables it for the application and determines its priority ordering under the CDI rules.
To enable an interceptor:
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>
...Applying an Interceptor on a Producer
In CDI 1.x, the interceptor is not bound to a producer bean. CDI 2.0 introduces the interface jakarta.enterprise.inject.spi.InterceptionFactory<T>, which allows to apply interceptors programmatically to the return value of a producer method.
The InterceptionFactory interface allows to create a wrapper instance whose method invocations are intercepted by method interceptors and forwarded to a provided instance.
API outline; package jakarta.enterprise.inject.spi
public interface InterceptionFactory<T> {
InterceptionFactory<T> ignoreFinalMethods();
AnnotatedTypeConfigurator<T> configure();
T createInterceptedInstance(T instance);
}A producer method can receive InterceptionFactory<T> as an injected parameter, as below. Programmatic callers use BeanManager.createInterceptionFactory(CreationalContext<T>, Class<T>). An injected InterceptionFactory parameter is supported on a producer method, not an arbitrary bean field.
Producer fragment: Product and ActionBinding.Literal are application-defined collaborators. Supply their definitions and interceptor enablement before using this fragment; it is not a standalone compilation unit.
@Produces
@RequestScoped
public Product createInterceptedProduct(InterceptionFactory<Product> interceptionFactory) {
interceptionFactory.configure().add(ActionBinding.Literal.INSTANCE);
return interceptionFactory.createInterceptedInstance(new Product());
}See Using Interceptors in CDI Applications in Java EE 8 Tutorial for more information about using 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.
A decorator decorates eligible bean types exposed through its decorated interfaces. The bean must match the delegate injection point’s required type and qualifiers and satisfy the CDI decoration restrictions.
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.
See Using Decorators in The Java EE 8 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:
-
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.
-
Annotate the class declaration of the decorator class with the
jakarta.decorator.Decoratorannotation. -
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.
-
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 represents the next element in the decorator chain or the underlying bean, 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.
-
Declare an injection point of the decorated interface type.
-
Annotate the injection point with the
jakarta.decorator.Delegateannotation. -
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 jakarta.decorator.*;
import jakarta.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.
The following procedure enables this class for a bean archive using beans.xml. Alternatively, @Priority enables it for the application and determines its priority ordering under the CDI rules.
To enable a decorator class:
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 Jakarta Server Faces (JSF) pages and Jakarta Server Pages (JSP) pages. 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. See Giving Beans EL Names in The Java EE 8 Tutorial .
To assign an EL name to a CDI bean class, annotate the class declaration of the bean class with the jakarta.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:
A bean can obtain its name from @Named on the class or from a stereotype that supplies @Named. A bean without either naming mechanism has no EL name. Producer methods and fields can also define named beans.The following example shows how to use the @Named annotation to assign an EL name to a CDI bean class. This example assigns the EL name cart to the ShoppingCart class.
ShoppingCart.java: the returned number is a display-only demonstration value.
package com.example.cart;
import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Named;
import java.io.Serializable;
@SessionScoped
@Named("cart")
public class ShoppingCart implements Serializable {
private static final long serialVersionUID = 1L;
public String getTotal() {
return "0.00";
}
}
Session scope is passivating: bean state, interceptors, decorators and injected dependencies must satisfy the CDI passivation rules. This simple bean has no injected dependencies.
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.
The following example 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-19 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.
...
<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.
Apply the stereotype to reuse its supported metadata and default scope/name rules. An explicit scope or supported naming declaration can override the corresponding default under the CDI rules.
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:
The following example shows the definition of a stereotype.
Example 9-20 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
@Namedannotation. -
The interceptor bindings
@Secureand@Transactionalare applied to the bean. The definition of these interceptor bindings is beyond the scope of this example.
import jakarta.enterprise.inject.Stereotype;
import jakarta.inject.Named;
import jakarta.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-21 shows how to apply stereotypes to a bean.
Example 9-21 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-20. 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
CDI events decouple the bean that fires an event from the beans that observe it. Senders and observers still share the event payload types and qualifiers available to the CDI application. This is in-container event delivery; communication between processes or servers requires an appropriate messaging or remote transport.
At run time, application operations may generate information or state changes that other beans in the CDI application need to observe.
See Using Events in the historical tutorial for background; use the shared payload and in-container delivery contract described above.
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:
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:
Example 9-22 shows how to send an event.
Example 9-22 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 jakarta.enterprise.event.Event;
import jakarta.enterprise.context.SessionScoped;
import jakarta.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:
Example 9-23 shows how to declare an observer method for receiving qualified events of a particular type. Example 9-24 shows how to declare an observer method for receiving all events of a particular type.
Example 9-23 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 jakarta.enterprise.event.Observes;
public void afterLogin(@Observes @LoggedIn User user) {
...
}Example 9-24 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 jakarta.enterprise.event.Observes;
public void afterLogin(@Observes User user) {
...
}An observer’s qualifiers must be a subset of the event’s qualifiers. An observer without an explicit qualifier can receive qualified events of a matching type.
The examples below are schematic observer-method fragments; supply the event type, qualifier and enclosing bean.
Injecting a Predefined Bean
The scope and qualifiers of each built-in bean are defined by its integrating specification; do not infer them from resource-injection annotations.
CDI provides predefined beans that implement the following interfaces:
-
jakarta.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.
-
jakarta.validation.Validator -
Validator for bean instances.
The bean that implements this interface enables a
Validatorobject for the default bean validationValidatorFactoryobject to be injected. -
jakarta.validation.ValidatorFactory -
Factory class for returning initialized
Validatorinstances.The bean that implements this interface enables the default bean validation
ValidatorFactoryobject to be injected.
Inject a built-in CDI bean with jakarta.inject.Inject and the required Java type and qualifiers. In Jakarta EE, supported built-in integrations include UserTransaction, Principal and Jakarta Validation’s Validator/ValidatorFactory; their availability and use are subject to the applicable component specification. Principal is an interface; use it to access the current caller identity rather than caching a caller name for later requests.
The scope and qualifiers of each built-in bean are defined by its integrating specification; do not infer them from resource-injection annotations.
For more information about injecting resources, see Resource Injection in The Java EE 8 Tutorial .
The following complete servlet demonstrates CDI field injection of a built-in UserTransaction.
Example 9-25 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 jakarta.transaction.UserTransaction interface.
package com.example.web;
import jakarta.inject.Inject;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.transaction.UserTransaction;
@WebServlet("/transaction")
public class TransactionServlet extends HttpServlet {
@Inject
private UserTransaction transaction;
}
@Resource remains a separate Jakarta EE resource-injection mechanism; its plural @Resources form groups class-level declarations and is not used on this field.
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.
A CDI bean can use Jakarta EE resource injection, and producer fields can expose those resource references through type-safe CDI qualifiers. Centralizing declarations is an optional design choice; applications can declare resource injection where appropriate.
-
Optionally centralize related resource declarations in a resource-holder bean.
-
Use producer fields to translate the injected resource type into a CDI bean.
You can then 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.
import javax.sql.DataSource;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.annotation.Resource;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.PersistenceUnit;
import jakarta.ejb.EJB;
import jakarta.xml.ws.WebServiceRef;
...
public class SomeClass {
@WebServiceRef(lookup="java:app/service/PaymentService")
PaymentWebService paymentWebService;
@EJB(beanName="../payment.jar#PaymentService")
PaymentBusiness paymentBean;
@Resource(lookup="java:global/env/jdbc/CustomerDatasource")
DataSource customerDatabase;
@PersistenceContext(unitName="CustomerDatabase")
EntityManager customerDatabasePersistenceContext;
@PersistenceUnit(unitName="CustomerDatabase")
EntityManagerFactory customerDatabasePersistenceUnit;
...
}The following example shows how to inject the same set of resources by combining Java EE 5 resource injection with CDI producer fields.
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.sql.DataSource;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import com.example.resources.CustomerDatabase;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import jakarta.annotation.Resource;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.PersistenceUnit;
import jakarta.ejb.EJB;
import jakarta.xml.ws.WebServiceRef;
...
@ApplicationScoped
public class SomeClass {
@Produces
@WebServiceRef(lookup="java:app/service/PaymentService")
PaymentWebService paymentWebService;
@Produces
@EJB(beanName="../payment.jar#PaymentService")
PaymentBusiness paymentBean;
@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 Jakarta EE resources in CDI applications in a way that is consistent with CDI. To use Jakarta EE resources in this way, inject the resources as CDI beans into other beans.
The following example shows how to inject a Jakarta EE resource as a CDI bean into another bean.
import jakarta.persistence.EntityManagerFactory;
import com.example.resources.CustomerDatabase;
import jakarta.enterprise.context.RequestScoped;
import jakarta.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:
-
Constructing the instance of
SomeOtherClass -
Injecting the reference to the entity manager factory by using the producer field.
-
Saving the new instance of
SomeOtherClassin 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 ends, CDI destroys SomeOtherClass and releases its dependent contextual references. This does not close or destroy the container-managed EntityManagerFactory or its persistence unit. Do not add a disposer that calls close on these container-managed persistence resources.
Resource-declaration fragments: supply the named EJB module/business interface, generated PaymentWebService client type, persistence unit CustomerDatabase and configured JDBC/service resources before deployment. These fragments are not a standalone application. The payment types are intentionally distinct; no extra qualifier is needed for those types.
CustomerDatabase.java qualifier shared by the producer and consumer fragments:
package com.example.resources;
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 jakarta.inject.Qualifier;
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface CustomerDatabase {}
Using CDI With JCA Technology
WebLogic Server supports CDI in embedded resource adapters and global resource adapters. Package a RAR bean archive with META-INF/beans.xml and an explicit discovery mode appropriate to the archive. With annotated discovery, eligible helper bean classes need bean-defining annotations; use all only when full eligible-type discovery is intended.
For more information about the beans.xml file, see Configuring a CDI Application.
Jakarta Connectors component classes can receive the supported injection services, but they are not thereby CDI managed beans. Eligible adapter helper classes can be discovered as CDI beans subject to the archive’s discovery mode. The following adapter component types are not CDI managed beans:
-
Resource adapter beans. These beans are classes that are annotated with the
jakarta.resource.spi.Connectorannotation or are declared as corresponding elements in the resource adapter deployment descriptorra.xml. -
Managed connection factory beans. These beans are classes that are annotated with the
jakarta.resource.spi.ConnectionDefinitionannotation or thejakarta.resource.spi.ConnectionDefinitionsannotation, or are declared as corresponding elements inra.xml. -
Activation specification beans. These beans are classes that are annotated with the
jakarta.resource.spi.Activationannotation or are declared as corresponding elements inra.xml. -
Administered object beans. These beans are classes that are annotated with the
jakarta.resource.spi.AdministeredObjectannotation or are declared as corresponding elements inra.xml.
Configuring a CDI Application
Package eligible classes in a bean archive and choose the discovery mode described below. CDI does not define a separate module packaging format.
CDI Full supports explicit and implicit bean archives. A beans.xml descriptor is not universally required: eligible classes with bean-defining annotations can be discovered in an implicit archive when discovery is enabled. A nonempty current descriptor uses the Jakarta namespace and explicitly states bean-discovery-mode. Use annotated to discover eligible classes with bean-defining annotations, all for full eligible-type discovery in CDI Full, or none to exclude a bean archive. An empty descriptor defaults to annotated, subject to the separately documented WebLogic legacy option.
For migration, AppDeploymentMBean.LegacyEmptyBeansXmlDiscovery defaults to false. When true for an application, qualifying empty beans.xml descriptors, including valid descriptors that omit bean-discovery-mode, use all rather than annotated. An explicit bean-discovery-mode always takes precedence. The option applies when the application is deployed or redeployed; it is separate from ImplicitBeanDiscoveryEnabled and is not a general switch to scan every archive. RAR discovery does not use this compatibility override.
If your CDI application uses alternatives, interceptors, or decorators, enable these items through the applicable beans.xml declaration or supported priority mechanism in the beans.xml file. For more information, see:
The required location of the beans.xml file depends on the type of the application:
-
WAR: WEB-INF/beans.xml or WEB-INF/classes/META-INF/beans.xml; use only one for the same archive. EJB/library/application-client JAR or RAR: META-INF/beans.xml.
Shared bean-archive JARs can be placed in an EAR’s library directory, normally lib. Each JAR is discovered/configured according to its own archive metadata and applicable visibility rules.
Example 9-26 shows a beans.xml file for configuring a CDI application.
Example 9-26 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="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_1.xsd"
version="4.1" bean-discovery-mode="all">
<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>
Enabling and Disabling CDI
CDI for a domain is enabled by default. However, even when an application does not use CDI, there is some CDI initialization that occurs when you deploy an application in WebLogic Server. To maximize deployment performance for applications that do not use CDI, you can disable CDI.
CdiContainerMBean.Policy supplies the domain default, Enabled or Disabled. An explicit weblogic-application.xml cdi-descriptor policy for an EAR, or a supported module descriptor policy for a standalone deployment, takes precedence; otherwise the domain default is used. Disabling CDI prevents CDI processing for the affected deployment. Domain-level changes are broad defaults, so assess applications that depend on CDI before changing them.
The application cdi-descriptor elements are policy and implicit-bean-discovery-enabled. See the application/web descriptor references for supported scope and precedence.
Enabling and Disabling CDI for a Domain
Configure the domain CDI default while preserving the existing domain configuration.
Configuration fragment for an existing domain’s cdi-container element; this is not a complete config.xml. Prefer the WLST procedures below, which preserve the domain configuration. Do not add a duplicate domain or cdi-container element. If editing the file manually, stop the domain first and preserve the rest of its configuration.
<cdi-container>
<policy>Disabled</policy>
</cdi-container>
You can use the WLST scripting tool to enable or disable CDI for a domain. The following examples demonstrate how to use WLST to enable and disable CDI for a domain whether you are online or offline.
Example 9-27 Enabling CDI While Online
WLST online configuration edit. Supply the user-config file and protected matching user-key file previously created for the administrative user, and the configured AdminServer URL. Call the function with those three values. Run with no unrelated pending edit; changing these defaults does not reconstruct already-running CDI contexts.
To disable, use Disabled or False as applicable. These examples were checked statically/procedurally, not run against your domain; inspect the printed singleton bean name.
def configure_cdi_online(user_config_file, user_key_file, admin_url):
connect(userConfigFile=user_config_file, userKeyFile=user_key_file,
url=admin_url)
edit()
startEdit()
cd('/')
cdi_container = cmo.getCdiContainer()
print('CDI configuration bean: ' + cdi_container.getName())
cdi_container.setPolicy('Enabled')
validate()
save()
activate(block='true')
disconnect()
Example 9-28 Enabling CDI While Offline
WLST offline existing-domain edit. Stop the domain before editing it offline. Pass the actual domain directory to the function; it reads and preserves that configuration. It lists the CDI bean names and creates the bean only when absent. Inspect the printed path. Use the online procedure when configuring a running domain.
Use Enabled/Disabled or True/False as applicable to select the intended default.
def configure_cdi_offline(domain_directory):
readDomain(domain_directory)
cd('/')
domain_name = get('Name')
cd('CdiContainer')
bean_names = ls(returnType='c', returnMap='true')
if not bean_names:
cd('/')
create(domain_name, 'CdiContainer')
cd('CdiContainer')
bean_names = ls(returnType='c', returnMap='true')
if len(bean_names) != 1:
raise Exception('Expected one CDI configuration bean')
cd(list(bean_names.keys())[0])
print(pwd())
set('Policy', 'Enabled')
updateDomain()
closeDomain()
Implicit Bean Discovery
An implicit bean archive is discovered under the CDI Full rules, for example from eligible classes with bean-defining annotations or from an empty/annotated beans.xml descriptor. An arbitrary archive without beans.xml is not automatically a bean archive. Archive visibility and extension-specific rules also apply.
Disabling implicit discovery and selecting legacy empty-descriptor discovery solve different migration needs. Prefer explicit discovery metadata for predictable new applications; use the compatibility setting when retaining the older descriptor behavior is intentional.
ImplicitBeanDiscoveryEnabled is a boolean, true by default. An explicit application cdi-descriptor value (EAR descriptor, or supported standalone module descriptor) takes precedence over an explicit domain value. Setting false suppresses implicit discovery for affected archives; it does not mean all descriptor-declared CDI archives are disabled. The domain examples below modify the default; use the EAR descriptor or supported standalone module descriptor for narrower configuration.
The application cdi-descriptor elements are policy and implicit-bean-discovery-enabled. See the application/web descriptor references for supported scope and precedence.
weblogic-application.xml Deployment Descriptor Elements
weblogic.xml descriptor reference
Implicit bean archives were introduced in CDI 1.1 / Java EE 7; this is historical context. Use the current annotated/all/none rules and independent switches described in Configuring a CDI Application.
Enabling and Disabling Implicit Bean Discovery for a Domain
Configuration fragment for an existing domain’s cdi-container element; this is not a complete config.xml. Prefer the WLST procedures below, which preserve the domain configuration. Do not add a duplicate domain or cdi-container element. If editing the file manually, stop the domain first and preserve the rest of its configuration.
<cdi-container>
<implicit-bean-discovery-enabled>false</implicit-bean-discovery-enabled>
</cdi-container>
You can use WLST scripting too to enable or disable this feature. The following examples demonstrate how to use WLST to enable and disable implicit bean discovery for a domain whether you are online or offline.
Example 9-29 Enabling Implicit Bean Discovery Using WLST Online
WLST online configuration edit. Supply the user-config file and protected matching user-key file previously created for the administrative user, and the configured AdminServer URL. Call the function with those three values. Run with no unrelated pending edit; changing these defaults does not reconstruct already-running CDI contexts.
To disable, use Disabled or False as applicable. These examples were checked statically/procedurally, not run against your domain; inspect the printed singleton bean name.
def configure_implicit_discovery_online(user_config_file, user_key_file, admin_url):
connect(userConfigFile=user_config_file, userKeyFile=user_key_file,
url=admin_url)
edit()
startEdit()
cd('/')
cdi_container = cmo.getCdiContainer()
print('CDI configuration bean: ' + cdi_container.getName())
cdi_container.setImplicitBeanDiscoveryEnabled(True)
validate()
save()
activate(block='true')
disconnect()
Example 9-30 Enabling Implicit Bean Discovery Using WLST Offline
WLST offline existing-domain edit. Stop the domain before editing it offline. Pass the actual domain directory to the function; it reads and preserves that configuration. It lists the CDI bean names and creates the bean only when absent. Inspect the printed path. Use the online procedure when configuring a running domain.
Use Enabled/Disabled or True/False as applicable to select the intended default.
def configure_implicit_discovery_offline(domain_directory):
readDomain(domain_directory)
cd('/')
domain_name = get('Name')
cd('CdiContainer')
bean_names = ls(returnType='c', returnMap='true')
if not bean_names:
cd('/')
create(domain_name, 'CdiContainer')
cd('CdiContainer')
bean_names = ls(returnType='c', returnMap='true')
if len(bean_names) != 1:
raise Exception('Expected one CDI configuration bean')
cd(list(bean_names.keys())[0])
print(pwd())
set('ImplicitBeanDiscoveryEnabled', True)
updateDomain()
closeDomain()
Supporting Third-Party Portable Extensions
CDI is intended to be a foundation for frameworks, extensions, and integration with other technologies.
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 jakarta.enterprise.inject.spi package.
Code in CDI extensions can handle events that are sent by the CDI framework.
Portable extensions implement jakarta.enterprise.inject.spi.Extension and are registered through META-INF/services/jakarta.enterprise.inject.spi.Extension. They observe the supported container lifecycle events and run during CDI bootstrap; they are not ordinary application bean observers. CDI also defines build-compatible extensions through jakarta.enterprise.inject.build.compatible.spi, a separate model. See Portable Extensions and Build Compatible Extensions in Jakarta CDI 4.1. Portable Extensions and Build Compatible Extensions in CDI 4.1
Using the Built-in Annotation Literals
CDI provides built-in annotation Literal classes for constructing supported annotation instances. The following table lists selected built-in literals in this release.
Syntax
Table 9-2 Built-in Annotation Literals
| Classes | Package |
|---|---|
Any |
jakarta.enterprise.inject |
Default |
jakarta.enterprise.inject |
| Specializes | jakarta.enterprise.inject |
| Vetoed | jakarta.enterprise.inject |
Alternative |
jakarta.enterprise.inject |
Typed |
jakarta.enterprise.inject |
Nonbinding |
jakarta.enterprise.util |
Initialized |
jakarta.enterprise.context |
|
BeforeDestroyed |
jakarta.enterprise.context |
Destroyed |
jakarta.enterprise.context |
RequestScoped |
jakarta.enterprise.context |
SessionScoped |
jakarta.enterprise.context |
ApplicationScoped |
jakarta.enterprise.context |
Dependent |
jakarta.enterprise.context |
ConversationScoped |
jakarta.enterprise.context |
Example 9-31 Built-in Annotation Literals
Default defaultLiteral = new Default.Literal();Using the Configurator Interfaces
CDI 2.0 introduced some new configurator interfaces which can be used for dynamically defining or modifying CDI objects.
The configurator interfaces introduced in CDI 2.0 include:
AnnotatedTypeConfiguratorInjectionPointConfiguratorBeanAttributesConfiguratorBeanConfiguratorObserverMethodConfiguratorProducerConfigurator
See Using the Configurators Interfaces in Java EE 8 Tutorial for more information.
The shared package is jakarta.enterprise.inject.spi.configurator; use these interfaces in their supported bootstrap-extension context.
Bootstrapping a CDI Container
For a standalone Java SE application using a CDI implementation, bootstrap through jakarta.enterprise.inject.se.SeContainerInitializer.newInstance(), configure the initializer as needed, then call initialize() to obtain a SeContainer. Close that container when the application finishes, for example with try-with-resources. WebLogic Server initializes CDI for deployed Jakarta EE applications; do not add this standalone bootstrap step inside those applications.
The standard standalone Java SE bootstrap API was introduced in CDI 2.0. The following Java EE 8 tutorial link is historical background.
See Configuring the CDI Container in Java EE 8 Tutorial for more information.