Getting Started With Jakarta EE 10 - Jakarta CDI
Published on 04 Apr 2023
by Luqman SaeedJakarta EE 10, the first major release of the platform since it was transferred to the Eclipse Foundation, did come with a slew of changes and updates to many of its constituent specifications. One such specification that received updates is the Jakarta Contexts and Dependency Injection specification. The specification release version for Jakarta EE 10 is Jakarta CDI 4.0, which came with major changes.
Two of such major changes are the split of the specification into a Lite and Full profiles and the change in default behaviour for an empty beans.xml file. In this blog post, we take a quick look at getting started with Jakarta CDI, in my view, the single most influential specification on the Jakarta EE Platform.
Setup
As a coreJakarta EEspecification, there’s not much setup to be done in getting Jakarta CDI up and running. Your typical Jakarta EE application will already contain a dependency on the platform in your dependency file, almost certainly the Maven pom.xml file. If you are not sure where or how to get started, check outmy very opinionated guide to getting started with Jakarta EE 10.
With the platform dependency in place, we need to configure CDI. The sample beans.xml file below shows how to set the bean discovery mode to all.
<?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_0.xsd"
bean-discovery-mode="all">
</beans>
You might be asking what is the bean discovery mode in the first place? Think of it as a way to tell the dependency injection container which of your Java classes, or beans, it should “index” and make available on request. As Jakarta CDI is at its core a dependency injection implementation, you can determine explicitly which of your beans should be managed by the container. The bean discovery mode has three possible values, namely annotated, all and none.
Annotated means you want only beans that are explicitly annotated with Jakarta CDI annotations to be managed on your behalf. All means all Java beans in your application should be managed and none effectively disables CDI. In Jakarta CDI 4.0, shipped with Jakarta EE 10, an empty beans.xml file is now translated equivalent to setting a bean discovery mode of annotation. You should avoid setting it to none. I recommend using all at all times.
Features of Jakarta CDI
Jakarta CDI is a IoC inversion of control that not only helps you write powerful, loosely coupled code, but also has features that help manage application complexity in a much simplified way. These features together, allow you to break your applicaiton down into components that can be swapped out dynamically at runtime with minimal to no application rewrite or even redeployment. Five core features you get with Jakarta CDI are:
Typesafe Dependency Resolution Mechanism
CDI uses Java types to resolve dependencies. Unlike other dependency injection implementations that are string based, CDI uses Java types through a combination of metadata and Java beans to resolve dependencies that you declare. This is achieved through a sophisticated resolution mechanism that allows you to select dependencies at development or deployment time.
Well Defined Lifecycle Contexts
CDI allows you to bind stateful objects to a well defined, extensible lifecycle context. Each instance of a bean that you request from the runtime has a predictable lifecycle, complete with callbacks that you can hook into.
Integration With the Web Tier
Through integration with the Jakarta Unified Expression Language (EL), contextual objects like Jakarta Enterprise Beans can be accessed directly from a Jakarta Server Faces page.
Interceptors
Jakarta CDI interceptors allow you to associate interceptors with Java objects through typesafe interceptor bindings. You can use these interceptors to implement orthogonal services like logging in your applications.
Events
Jakarta CDI events are a powerful, typesafe, fully decoupled communication mechanism between different parts of your application. One component can fire an event, and any registered listeners of that event will be notified or called by the CDI runtime, passing in the requisite event payload automatically.
Beans And Scopes
A bean however, cannot be an inner or abstract class. A CDI bean isn’t very different from a JavaBean. In fact, any JavaBean is automatically a CDI bean. Technically, this kind of bean is called a managed bean. Managed in the sense that the creation and destruction of such bean instances are fully managed by the CDI container.
With your knowledge of what a bean is, you effectively know the core of CDI. It is a way to make beans available to dependents in an automatic, loosely coupled way. Take the following sample controller for instance.
@ApplicationScoped
public class DataController {
@Inject
private Datastore datastore;
}
The @Inject annotation signals to the CDI container to inject an instance of the annotated type, in this case DataStore into the declared field variable. Technically, the instance created by the CDI container and injected into the field is a contextual instance. But you will hardly need to know that technicality.
Even though the above sample class and its metadata look very underwhelming, there is a lot going on there. The DataController only declares its dependency on the Datastore and leaves the management of such dependency to the CDI container. It does not concern itself with the creation of its dependency. It delegates that to the container, which manages the DataController instance and its dependency. The Datastore could be in a different scope and that would still be managed on your behalf.
Producers
However, through the Jakarta CDI producer construct, we are able to transform the Datastore, a completely external class into a CDI managed bean. The code snippet below shows us “producing” Datastore instances using the CDI producer method.
@Produces
@ApplicationScoped
public Datastore generateDatastore() {
var datastore = Morphia.createDatastore(MongoClients.create(connectionString), databaseName);
datastore.getMapper().mapPackage(HelloEntity.class.getPackageName());
if (DeploymentStage.DEV.name().equalsIgnoreCase(deploymentStage)) {
datastore.getDatabase().drop();
}
datastore.ensureIndexes();
return datastore;
}
There is a lot more to the Jakarta CDI specification. As the Jakarta EE Platform keeps evolving, CDI will increasingly become the underlying “glue” that holds all the disparate parts of the platform into a cohesive whole. Take a look at the specification document here. Don’t worry, it’s an easy read at just about 200 pages. You can also check out this guide we have that goes a lot more into details about what CDI is and how to use it.
Related Posts
Nugget Friday - Preventing Memory Leaks with JDBC Connection Pool Management in Payara Server
Published on 15 Nov 2024
by Luqman Saeed
0 Comments
AI Tools for Jakarta EE at the upcoming Virtual Payara Conference
Published on 14 Nov 2024
by Dominika Tasarz
0 Comments
Virtual Payara Conference is coming next month and on Day 2 - Developer Insight - we will help you unlock the future of Jakarta EE development!
AI Tools for Jakarta EE - 12 December 2024, 3:40pm GMT - Register Here!
Join Gaurav Gupta, Senior ...