Context and Dependency Injection beans

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 at run time, 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.

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:

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
            http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
      version="1.1" bean-discovery-mode="all">
  // enable interceptors; decorators; alternatives
</beans>

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.

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++;
    }
}

The MyRestEndPoint class has the @RequestScoped annotation in the following code, 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();
    }
}