Context and Dependency Injection (CDI)

Contexts and Dependency Injection (CDI) is a framework that makes it easier to integrate Jakarta EE components of different types. CDI enables Java object dependencies to be automatically injected and helps manage the lifecycle of those dependencies.

CDI provides the following fundamental services:

  • Contexts, which help you bind the lifecycle and interactions of stateful components to well-defined, extensible contexts.

  • Dependency injection, which helps you inject components into an application in a type-safe way.

CDI is an essential element in MicroProfile, Java EE, and Jakarta EE. MicroProfile specifications take a CDI-first approach. They rely on the CDI extension mechanism, which implements more functions and enhances existing standards with new capabilities.

You can use CDI with your Open Liberty applications by enabling the Jakarta Contexts and Dependency Injection feature.

CDI beans

Beans are components that can be injected into each other with a dependency injection. Almost every Plain Old Java Object (POJO) with a constructor can be a bean. In CDI, a bean is a source of contextual objects that define application state and logic. The beans are managed by CDI containers by using bean-defining annotations. The container instantiates dependencies and controls when and how the components are instantiated and destroyed.

Annotations are metadata about code. You can use them to decorate a class, method, field, parameter, variable, constructor, or package. You can also use annotations to define the scope in which the bean is stored.

CDI scopes

Scopes define the state of a bean. The following CDI scope annotations control the lifecycle of the bean:

  • The @ApplicationScoped class-level annotation specifies that an instance is live when the application is active.

  • The @RequestScoped class-level annotation specifies that a new instance of the bean is created for every request, such as a servlet request.

  • The @Dependent class-level annotation specifies that the new instance belongs to another object. A dependent bean instance is never shared among different clients or different injection points. It is instantiated when the object it belongs to is created, and then destroyed when the object it belongs to is destroyed.

If no class-level annotation is defined, the @Dependent annotation is the default.

Annotations that define CDI beans must be discovered. You can enable CDI annotation scanning by using a beans.xml file in the META-INF folder of a .jar file, or in the WEB-INF folder of a .war file. This file can be empty, or it can contain code similar to the following example:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="https://jakarta.ee/xml/ns/jakartaee"
    xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd"
    version="4.0"
    bean-discovery-mode="annotated">
</beans>

In CDI 3.0 and earlier, the presence of an empty beans.xml file or a beans.xml file with the bean-discovery-mode="all" attribute makes all of the potential objects CDI beans. Otherwise, only objects with CDI bean-defining annotations are CDI beans.

In CDI 4.0 and later, the presence an empty beans.xml file causes an archive to be treated as an implicit bean archive, the equivalent of setting the bean-discovery-mode="annotated" attribute. Only objects with CDI bean-defining annotations are CDI beans. If necessary, you can set the cdiemptyBeansXmlCDI3Compatibility attribute to enable compatibility with previous versions. Setting this attribute to true in CDI 4.0 causes an empty beans.xml file to be treated as an explicit beans archive.

Also in CDI 4.0 and later, a non-empty beans.xml file that does not specify the bean-discovery-mode attribute defaults this value to annotated. Therefore, by default, only objects with CDI bean-defining annotations are discovered as CDI beans. However, always properly specify a version for all beans.xml files, as shown in the previous example.

CDI bean injection

CDI injects defined beans into other components through the @Inject annotation. For instance, the POJO in the following example is a CDI bean. Because the MyBean class has the @ApplicationScoped annotation, only one instance is created. You can use the same instance throughout the lifetime of the application.

@ApplicationScoped
public class MyBean {
    int i=0;
    public String sayHello() {
        return "MyBean hello " + i++;
    }
}

In the following example, the MyRestEndPoint class specifies the @RequestScoped annotation, which means an instance is created for each request. CDI injects the same MyBean instance into each request:

@RequestScoped
@Path("/hello")
public class MyRestEndPoint {
    @Inject MyBean bean;
    @GET
    @Produces (MediaType.TEXT_PLAIN)
    public String sayHello() {
        return bean.sayHello();
    }
}