Oct 26, 2018

How to Enable CDI For Your Java SE or Servlet-only Environment

A CDI implementation provides the CDI essentials, managing dependency injection and contextual lifecycles. JBoss Weld and Apache OpenWebBeans (OWB) are two widely used CDI implementations. Dependent on the Java environment you choose, some setup may be necessary as detailed here.

CDI is part of Java EE6 and later so CDI implementations are included as standard in Java EE6+ compliant environments. There is no additional CDI configuration needed besides including the CDI-obligatory beans.xml file in your project.

Java SE6+

CDI is not part of Java SE but it can still be used. JBoss Weld and Apache OpenWebBeans implementations can be used to act as dependency injection bean managers but the respective containers must be booted manually.
DeltaSpike provides a dedicated Container Control module to enable applications deployed in Java SE environments to boot a CDI container. The Container Control module consists of the API component and components specific to the JBoss Weld, Apache OpenWebBeans and Apache OpenEJB CDI containers. The DeltaSpike module provides a layer of abstraction from the specific CDI containers, enabling you to write container-independent code in your project.
Instructions are provided here for adding the required resources to both Maven-based and Maven-independent projects and subsequently booting the CDI container from your project source code.

Declare CDI Dependencies

Dependencies for Maven-based Projects

For Maven-based projects, the Container Control module is available in Maven Central together with the other DeltaSpike modules. You must configure your project to use the DeltaSpike Container Control API and one of the CDI container-specific modules.
  1. Open the project pom.xml file for editing
  2. Add the DeltaSpike Container Control API to the list of dependencies
    <dependency>
        <groupId>org.apache.deltaspike.cdictrl</groupId>
        <artifactId>deltaspike-cdictrl-api</artifactId>
        <version>${deltaspike.version}</version>
        <scope>compile</scope>
    </dependency>
  3. Add CDI container dependencies for one of the container options listed here
    For JBoss Weld
    1. Add the JBoss Weld version to the list of properties, replacing the version as desired
      <properties>
          <weld.version>1.1.9.Final</weld.version>
      </properties>
    2. Add the JBoss Weld dependency to the list of dependencies
      <dependency>
          <groupId>org.jboss.weld.se</groupId>
          <artifactId>weld-se</artifactId>
          <version>${weld.version}</version>
          <scope>runtime</scope>
      </dependency>
    3. Add the DeltaSpike Weld-specific Container Control module to the list of dependencies
      <dependency>
          <groupId>org.apache.deltaspike.cdictrl</groupId>
          <artifactId>deltaspike-cdictrl-weld</artifactId>
          <version>${deltaspike.version}</version>
          <scope>runtime</scope>
      </dependency>
    For Apache OpenWebBeans
    1. Add the Apache OpenWebBeans version to the list of properties, replacing the version as desired
      <properties>
          <owb.version>1.2.0</owb.version>
      </properties>
    2. Add the Apache OpenWebBeans dependencies to the list of dependencies
      <dependency>
          <groupId>org.apache.openwebbeans</groupId>
          <artifactId>openwebbeans-impl</artifactId>
          <version>${owb.version}</version>
          <scope>runtime</scope>
      </dependency>
      
      <dependency>
          <groupId>org.apache.openwebbeans</groupId>
          <artifactId>openwebbeans-spi</artifactId>
          <version>${owb.version}</version>
          <scope>compile</scope>
      </dependency>
    3. Add the DeltaSpike Apache OpenWebBeans-specific Container Control module to the list of dependencies
      <dependency>
          <groupId>org.apache.deltaspike.cdictrl</groupId>
          <artifactId>deltaspike-cdictrl-owb</artifactId>
          <version>${deltaspike.version}</version>
          <scope>runtime</scope>
      </dependency>
  4. Save the pom.xml file changes
  5. Download all required dependencies
    mvn clean install

Dependencies for Maven-independent Projects

For Maven-independent projects, the Container Control module is distributed together with the other DeltaSpike modules in distribution-fill-<version>.zip. You must add two of the files from the cdictrl directory to your project, namely deltaspike-cdictrl-api.jar and the .jar file that corresponds to the CDI container you have chosen. Add these files to the project WEB-INF/lib or EAR/lib directory for .war and .ear projects respectively.

Start the CDI Container from Your Project

To start a CDI container in your application, you must instantiate a CdiContainer object and call the #bootmethod. When #boot is called, the CdiContainer scans CDI-enabled archives for beans and CDI extensions. Before the application exits, #shutdown must be called to correctly destroy all beans. An example is given in the code snippet here.
import org.apache.deltaspike.cdise.api.CdiContainer;
import org.apache.deltaspike.cdise.api.CdiContainerLoader;

public class MainApp {
    public static void main(String[] args) {

        CdiContainer cdiContainer = CdiContainerLoader.getCdiContainer();
        cdiContainer.boot();

        // You can use CDI here

        cdiContainer.shutdown();
    }
}
Starting the container does not automatically start all CDI Contexts. Contexts must be started independently using the provided ContextControl class. An example of starting the Context for @ApplicationScoped beans is added to the code snippet here.
import org.apache.deltaspike.cdise.api.CdiContainer;
import org.apache.deltaspike.cdise.api.CdiContainerLoader;
import org.apache.deltaspike.cdise.api.ContextControl;
import javax.enterprise.context.ApplicationScoped;

public class MainApp {
    public static void main(String[] args) {

        CdiContainer cdiContainer = CdiContainerLoader.getCdiContainer();
        cdiContainer.boot();

        // Starting the application-context enables use of @ApplicationScoped beans
        ContextControl contextControl = cdiContainer.getContextControl();
        contextControl.startContext(ApplicationScoped.class);

        // You can use CDI here

        cdiContainer.shutdown();
    }
}
To resolve project beans, you can use the DeltaSpike BeanProvider class. Whether EchoService is a concrete implementation or just an interface depends on the application. In the case that it is an interface, the corresponding implementation is resolved. The resolved bean is a standard CDI bean and it can be used for all CDI concepts, such as @Inject, in the class without further uses of BeanProvider. An example of resolving the bean without qualifiers is given in the code snippet here.
EchoService echoService = BeanProvider.getContextualReference(EchoService.class, false);

CdiContainer

The CdiContainer interface provides booting and shutdown of the CDI containers from deployed applications, withCdiContainerLoader a simple factory providing access to the underlying CdiContainer implementation.
This is useful to Java SE6+ applications in which a standalone CDI implementation must be provided and booted and shutdown by the application. Booting and shutdown of the CDI container for Java EE and servlet containers is managed by the servlet container integration.