If you have worked with the Spring framework, many of you will know about the concept of Dependency Injection and how Spring uses this concept to implement its framework. Jakarta EE also defines a similar specification called Context Dependency Injection (CDI) to implement this Dependency Injection concept. Details about this specification you can see the latest here https://jakarta.ee/specifications/cdi/. Jakarta EE CDI also defines a container to contain dependent objects, when the dependent objects need to use these dependent objects, they only need to call from the CDI container. In this tutorial, I will introduce you to Context Dependency Injection in Jakarta EE with an official implementation of it, the Weld library.
First, I will create a new Maven project as an example:
Although the Weld library has an implementation for Jakarta EE CDI, it also has a version that supports Java SE. For simplicity, I will use this version that supports Java SE. I will declare the Weld dependency for Java SE as follows:
1 2 3 4 5 |
<dependency> <groupId>org.jboss.weld.se</groupId> <artifactId>weld-se-shaded</artifactId> <version>5.1.0.Final</version> </dependency> |
I will create a new class, simply print the words “Hello World”, to be able to create a new object of this class in the CDI container. The content of this class is as simple as this:
1 2 3 4 5 6 7 8 |
package com.huongdanjava.jakartaee.cdi; public class SayHello { public void say() { System.out.println("Hello World!"); } } |
Objects created in the Jakarta EE CDI container are also called beans and in Jakarta EE CDI, by default, we will use a file named beans.xml located in src/main/resources/META- INF to define how the Jakarta EE CDI will define beans from classes. The contents of the basic beans.xml file are as follows:
1 2 3 4 5 |
<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="annotated"> </beans> |
The most important property is bean-discovery-mode which defines how Jakarta EE CDI will create beans from Java classes. There are 3 values for this bean-discovery-mode property:
- annotated: only initialize Java classes that are annotated with Jakarta EE CDI annotations.
- all: initializes all Java classes in the CDI container.
- none: do nothing.
By default, if we do not declare the bean-discovery-mode property, the value of bean-discovery-mode is “annotated” from CDI 4.0 version guys!
The Jakarta EE CDI defined annotations include:
- Annotation @ApplicationScoped
- Annotation @RequestScoped
- Annotation @Interceptor
- All annotations are annotated with the @Stereotype annotation
- Annotation @Dependent
For simplicity, I will only mention and use the @ApplicationScoped annotation as an example for this tutorial.
In other words, the @ApplicationScoped annotation will specify that the bean created by the annotated class with this annotation will only be initialized once in the application. Like the class that implements the Singleton design pattern, guys!
I will annotate the SayHello class with the @ApplicationScoped annotation as follows:
1 2 3 4 5 6 7 8 9 10 11 |
package com.huongdanjava.jakartaee.cdi; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class SayHello { public void say() { System.out.println("Hello World!"); } } |
Now, we will use the Main class with the main() method, define the CDI container class to get the bean of the SayHello class to see how it goes!
Jakarta EE CDI defines the SeContainer interface as a CDI container and we use the SeContainerInitializer class to initialize this CDI container as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.huongdanjava.jakartaee.cdi; import jakarta.enterprise.inject.se.SeContainer; import jakarta.enterprise.inject.se.SeContainerInitializer; public class Main { public static void main(String[] args) { try (SeContainer container = SeContainerInitializer.newInstance().initialize()) { } } } |
The implementation of the Weld library for the SeContainer class is the WeldContainer class and the SeContainerInitializer class is the Weld class. The Weld class will read the contents of the beans.xml file in the src/main/resources/META-INF directory to configure the CDI container.
We will use the select() method of the SeContainer class to get the SayHello class bean in the CDI container and call the say() method of this SayHello class as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.huongdanjava.jakartaee.cdi; import jakarta.enterprise.inject.se.SeContainer; import jakarta.enterprise.inject.se.SeContainerInitializer; public class Main { public static void main(String[] args) { try (SeContainer container = SeContainerInitializer.newInstance().initialize()) { SayHello sayHello = container.select(SayHello.class).get(); sayHello.say(); } } } |
Result: