Resource and Dependency Injection in Java EE 7

1. Overview

Contexts and Dependency Injection (CDI) is a feature of Java EE that helps meld the web tier and transactional tier of its platform that is included in Java EE 6 and higher. From a technical perspective, what this means is that CDI offers a dependency injection framework and also manages the dependencies’ lifecycle.

In this tutorial today, we will be covering CDI for Java EE 7.

1.1 Contexts and Dependency Injection Specification

As mentioned on Oracle’s Java EE 7 website, Java EE 7 uses CDI 1.1, which is outlined in JSR 346.

CDI 1.1 brought many major changes, as mentioned in this blog post by the CDI lead Pete Muir, such as:

  • Global enablement of interceptors, global enablement of decorators, and alternatives using the @Priority annotation
  • Support for @AroundConstruct lifecycle callback for constructors
  • EventMetadata to allow inspection of event metadata
  • Allowing binding interceptors to constructors

As mentioned, other significant changes are mentioned in the blog post, and it is encouraged that they are all reviewed.

2. Comparing Dependency Injection and Resource Injection

Injection Type Can Inject JNDI Resources Directly Can Inject Regular Classes Directly Resolves By Typesafe
Resource Injection True False Resource name No
Dependency Injection False True Type Yes

2.1 Dependency Injection

Dependency injection allows us to turn regular Java classes into managed objects and to inject those managed objects into other managed objects. The hurdle is ensuring we are providing the correct managed object at the right time.

Here we have an @Inject annotation that denotes that we will be providing – also known as injecting – a dependency to this constructor:

@Inject
	public MaskingDataProcessor(MaskingData maskingData) {
		this.maskingData = maskingData;

	}

So, where does this dependency come from?

We have two classes in this example: SSNDataMasker and BirthdayMasker, and they both implement the same interface.

SSNDataMasker is annotated to be the default and therefore will be chosen by default if available:

@Default
public class SSNMasker implements MaskingData {

	...
}

BirthdayMasker is annotated to be the alternative dependency and therefore will be chosen if SSNDataMasker is unavailable:

@Alternative
public class BirthdayMasker implements MaskingData {

	...
}

2.2 Resource Injection

Resource injection allows us to inject any resource available in the JNDI namespace into any object managed by the container. For instance, we can use resource injection to inject connectors, data sources, or any other resources available in the JNDI namespace.

In the code below, we inject a data source object into a field and this kind of resource injection is appropriately called field-based injection:

public class MyClass {
	 @Resource(name="java:comp/SomeDataSource")
	private DataSource myDataBase;
	...
}


Another way of injecting resources is method-based injection. In method-based injection, the parameter that is passed is injected with the resource:

public class MyClass {
	
	private DataSource myDataBase;
        ...

	@Resource(name="java:comp/SomeDataSource")
	public void setMyDataSource(DataSource dataSource) {
		myDataBase = dataSource;
	}
}


3. What’s the Difference Between EJB and CDI?

As this article on the Oracle website states, the “C” in CDI is the main difference between EJB beans and CDI beans. EJB components might be stateful, but are not inherently contextual. When we reference a stateful component instance, it must be explicitly passed between clients and destroyed by the application.  CDI improves the EJB component model with contextual lifecycle management. However, there are times when we want to use one over another.

3.1 When to Use EJB

There are several useful container services that are available only if we make our CDI bean also an EJB by adding @Stateful, @Stateless, or @Singleton.

Examples include:

  • When we are exposing a JAX-WS @WebService, making it an EJB allows us to not have to list it and map it as a servlet in the xml file. This is available to @Stateless and @Singleton.
  • When we are exposing a JAX-RS resource via @Path. When the RESTful service is an EJB, we get automatic discovery and don’t need to add it to a JAX-RS Application subclass or elsewhere. This is available to @Stateless and @Singleton.
  • When we are working in parallel, the @Asynchronous method invocation is useful. As we know, having too many thread can degrade performance. The @Asynchronous annotation allows us to parallelize things we do using the container’s thread pool. This is available to @Stateful, @Stateless and @Singleton.

3.2 When to Use CDI

Simply put, we should use CDI when we benefit from its use. When we need injection, events, interceptors, decorators, lifecycle tracking, and other features that CDI offers.

4. Conclusion

To quickly test the concepts we reviewed regarding CDI, let’s add Weld to a Maven project:

<dependency>
    <groupId>org.jboss.weld.se</groupId>
    <artifactId>weld-se-core</artifactId>
    <version>2.4.1.Final</version>
</dependency>

Assuming we already have code to test – such as the code previously mentioned in the blog post – we just need to execute Weld, like:

public static void main(String[] args) {
		
    Weld weld = new Weld();
    WeldContainer container = weld.initialize();
    MaskingDataProcessor maskingDataProcessor = container.select(MaskingDataProcessor.class).get();
    container.shutdown();
	}