Understanding Jarkarta EE 8 - C.D.I. (Part 1)
Tags: java, jakartaee, programming, tutorial
Published: 2020-07-15 05:23:20

The fundamental purpose of a software developer is to write code that are:
 - Easily maintainable and testable.
 - Loosely Coupled
 - Easily extensible.

Building a distributed Java enterprise application required huge understanding in wiring various mainstream technologies across various application tiers, tying web controllers to database backend through a series of application and business services. This made it difficult to achieve the points highlighted above, making it a huge learning curve for developers to do what they do best: to write code.

**C**ontext and **D**ependency **I**njection (C.D.I) is one such technology that was introduced in Java EE 6 ([JSR 299](https://jcp.org/en/jsr/detail?id=299)), with the goal to help knit the web tier with the transactional tier.

The Jakarta EE 8 CDI specification version is [CDI 2.0](https://jakarta.ee/specifications/cdi/2.0/cdi-spec-2.0.html), which is an update to [CDI 1.2 (JSR 346)](https://jcp.org/en/jsr/detail?id=346).

## Dependency Injection
According to [Wikipedia](https://en.wikipedia.org/wiki/Dependency_injection):

> In software engineering, dependency injection is a technique in which
> an object receives other objects that it depends on. These other
> objects are called dependencies. In the typical "using" relationship
> the receiving object is called a client and the passed (that is,
> "injected") object is called a service.

Dependency injection helps eliminate the need of hard-coding dependencies (object creation and instantiation) thus making our application loosely coupled, maintanable, extendable and easier to test. With CDI, dependency resolution is done on runtime. The DI container (the injector) is responsible for injecting dependent beans.

## So, what is C.D.I.?
CDI is a typesafe approach to [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection). Among various services and features, it provides lifecycle management of stateful beans **bound** to well defined *contexts*. This allows developers a great deal of flexibility to integrate various kinds of components in a loosely coupled and typesafe way.

This article discusses dependency injection in a tutorial format. It covers some of the features of CDI such as type safe annotations configuration, alternatives and more. 

## Dependency Injection with CDI
To use CDI to manage bean injection, we will need to do the following:

### Setting up Bean archive.
Bean classes must exists in a bean archive in order to be discoverable by the CDI container.

To enable bean archive, `beans.xml` must exist in the following folder, with `bean-discovery-mode` set to `all` or `annotated`. If the bean discovery mode is set to `none` it's no longer a bean archive file.

> An example of beans.xml file, version 2.0

```xml
    <?xml version="1.0" encoding="UTF-8"?>
    <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_2_0.xsd "
    	version="2.0" bean-discovery-mode="all">
    	
    </beans>
```

 - In a WAR file, place your `beans.xml` inside `WEB-INF` folder.
 - In a JAR file, place your `beans.xml` inside the `META-INF` folder. In a Mavenized project, this file must exist inside `src/main/resources/META-INF` directory.

The default bean discovery mode is `annotated`, if version number is specified (`1.1` or later), else `all` otherwise. This mean that all bean classes must be annotated with [Bean defining annotations](https://jakarta.ee/specifications/cdi/2.0/cdi-spec-2.0.html#bean_defining_annotations) in order to be qualified for bean discovey.

*Note*: The `beans.xml` file can be an empty file.

Now, let's look at various examples on how we can create bean qualified for injection. This tutorial covers the basis of dependency injection, `@Inject`, `@Produces` and `@Qualifiers`. 

## CDI in action
In order to understand CDI we'll have to [bootstrap CDI in Java SE](https://jakarta.ee/specifications/cdi/2.0/cdi-spec-2.0.html#se_bootstrap).  Even though JSR 299 provides a requirements to implement our own CDI container, we will use existing JSR 299 Reference Implementation (RI). In this example we use JBoss Weld, a JSR 299 CDI RI.

We include `weld-se-core` dependency to your Maven project.

```xml
			<dependency>
			    <groupId>org.jboss.weld.se</groupId>
			    <artifactId>weld-se-core</artifactId>
			    <version>${org.jboss.weld.se.core.version}</version>
			</dependency>
```

Where `org.jboss.weld.se.core.version` is `3.1.4.Final` at the time of writing.

We, also, don't want Weld specific beans to be discovered by the container, so we add the following exclusion on `beans.xml`:

```xml	
	<scan>
        <exclude name="org.jboss.weld.**" />
    </scan>
```

## Example of basic Dependency Injection in CDI
In this example, we will introduce basic injection by just injecting with `@Inject` a basic bean.

> DefaultService.java
```java
    public class DefaultService {
    
    	public void doWork() {
    		System.out.println("Default Service work.");
    	}
    }
```

> MainController.java
```java
    public class MainController {
    
    	@Inject
    	private DefaultService service;
    	
    	public void execute() {
    		service.doWork();
    	}
    }
```

> Main.java
```java
    public class Main {
    
    	public static void main(String[] args) {
    		SeContainer container = null;
    		
    		try {
    			SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
    			container = containerInitializer.initialize();
    			
    			//Get bean via CDI
    			MainController controller = container.select(MainController.class).get();
    			controller.execute();
    		} finally {
    			if (container != null) {
    				container.close();
    			}
    		}
    	}
    }
```

By selecting the `MainController` from the `container` the CDI container resolve the bean in a typesafe way at runtime and inject it.

You'll notice that `DefaultService` and the `MainController` has not been annotated by any qualified Bean annotation, so the bean is qualified as the `@Default` qualifier. Also, if no qualifier is passed to `SeContainer.select()` method, the `@Default` qualifier is assumed.

When we run the `Main` program, Weld will boostrap to the `SeContainer` and Weld becomes the CDI container to do the injection.

Output:

> Jul 15, 2020 5:33:51 AM org.jboss.weld.bootstrap.WeldStartup \<clinit\>
> INFO: WELD-000900: 3.1.4 (Final)
> WARNING: An illegal reflective access operation has occurred
> WARNING: Illegal reflective access by org.jboss.weld.util.bytecode.ClassFileUtils$1 (file:/C:/Users/buhake.sindi/.m2/repository/org/jboss/weld/weld-core-impl/3.1.4.Final/weld-core-impl-3.1.4.Final.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int)
> WARNING: Please consider reporting this to the maintainers of org.jboss.weld.util.bytecode.ClassFileUtils$1
> WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
> WARNING: All illegal access operations will be denied in a future release
Jul 15, 2020 5:33:52 AM org.jboss.weld.bootstrap.WeldStartup startContainer
> INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
Jul 15, 2020 5:33:53 AM org.jboss.weld.environment.se.WeldContainer fireContainerInitializedEvent
> INFO: WELD-ENV-002003: Weld SE container 0b2888f8-0582-4b76-a2db-2c04514757a4 initialized
> **Default Service work.**
Jul 15, 2020 5:33:53 AM org.jboss.weld.environment.se.WeldContainer shutdown
> INFO: WELD-ENV-002001: Weld SE container 0b2888f8-0582-4b76-a2db-2c04514757a4 shut down

We can see that `Default Service work.` is outputted on the console.

The full source code of this example can be found on the [GitHub source tree](https://github.com/TheEliteGentleman/jakartaee8-tuts-cdi/tree/master/src/main/java/za/co/sindi/tuts/jakartaee/cdi/example01).

Let's pause for a moment. We will carry on with other various ways of DI injection provided by the CDI framework as well as other features present in the specs (such as `events`, `interceptors`, etc.).