Bootstrap a CDI 2.0 container in Java SE

Bootstrap a CDI 2.0 container in Java SE

When I think of CDI (Contexts and Dependency Injection), I always have Java EE in mind. But you don’t need a JEE application server to use CDI. CDI 2.0 includes a new API to bootstrap a CDI container in Java SE. This blog post shows how to bootstrap CDI 2.0 in JavaSE with Gradle and Weld.


How to bootstrap the CDI container

First you have to setup the 2 gradle dependencies for the CDI 2.0 API and weld-se-shaded in your build.gradle.

dependencies {
    compile "javax.enterprise:cdi-api:2.0"
    runtime "org.jboss.weld.se:weld-se-shaded:3.0.1.Final"
}

Add the CDI 2.0 beans.xml to your META-INF folder.

<?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"
    bean-discovery-mode="all" version="2.0">
</beans>

To bootstrap your CDI container just call:

SeContainerInitializer initializer = SeContainerInitializer.newInstance();

/** container.close() in AutoCloseable, The application context is started automatically by the container on start up. */
try (SeContainer container = initializer.initialize()) {
    /** do some stuff :) */
    MyBean myBean = container.select(MyBean.class).get();
    ...
}

With the above setup the container is running in a bean auto discovery mode. In this mode you project needs a beans.xml. Without that file you get an error!

Disabled discovery mode

To start your CDI environment without the beans.xml, you have to call disableDiscovery() and manually preconfigure all CDI beans.

SeContainerInitializer initializer = SeContainerInitializer.newInstance();

/** disable discovery and register bean classes manually */
try (SeContainer container = initializer.disableDiscovery().addBeanClasses(MyBean.class).initialize()) {
    /** do some stuff :) */
    MyBean myBean = container.select(MyBean.class).get();
    ...
}

SeContainerInitializer class

The SeContainerInitializer class has a lot of methods to preconfigure you CDI container.

public abstract class SeContainerInitializer {

    /** Returns an instance of {@link SeContainerInitializer}. Each call returns a new instance */
    public static SeContainerInitializer newInstance() {...}

    /** Add provided bean classes to the synthetic bean archive. */
    public abstract SeContainerInitializer addBeanClasses(Class<?>... classes);

    /** All classes from the packages of the specified classes will be added to the set of bean classes for the synthetic bean archive. */
    public abstract SeContainerInitializer addPackages(Class<?>... packageClasses);

    /** Packages of the specified classes will be scanned and found classes will be added to the set of bean classes for the synthetic bean archive. */
    public abstract SeContainerInitializer addPackages(boolean scanRecursively, Class<?>... packageClasses);

    /** All classes from the specified packages will be added to the set of bean classes for the synthetic bean archive. */
    public abstract SeContainerInitializer addPackages(Package... packages);

    /** All classes from the specified packages will be added to the set of bean classes for the synthetic bean archive. */
    public abstract SeContainerInitializer addPackages(boolean scanRecursively, Package... packages);

    /** Add extensions to the set of extensions. */
    public abstract SeContainerInitializer addExtensions(Extension... extensions);

    /** Add extensions to the set of extensions. */
    public abstract SeContainerInitializer addExtensions(Class<? extends Extension>... extensions);

    /** Add interceptor classes to the list of enabled interceptors for the synthetic bean archive. */
    public abstract SeContainerInitializer enableInterceptors(Class<?>... interceptorClasses);

    /** Add decorator classes to the list of enabled decorators for the synthetic bean archive. */
    public abstract SeContainerInitializer enableDecorators(Class<?>... decoratorClasses);

    /** Add alternatives classes to the list of selected alternatives for the synthetic bean archive. */
    public abstract SeContainerInitializer selectAlternatives(Class<?>... alternativeClasses);

    /** Add alternative stereotype classes to the list of selected alternative stereotypes for the synthetic bean archive. */
    public abstract SeContainerInitializer selectAlternativeStereotypes(Class<? extends Annotation>... alternativeStereotypeClasses);

    /** Add a configuration property to the container */
    public abstract SeContainerInitializer addProperty(String key, Object value);

    /** Set all the configuration properties. */
    public abstract SeContainerInitializer setProperties(Map<String, Object> properties);

    /** By default, the discovery is enabled. However, it's possible to disable the discovery completely so that only the "synthetic" bean archive is considered. */
    public abstract SeContainerInitializer disableDiscovery();

    /** Set a {@link ClassLoader}. The given {@link ClassLoader} will be scanned automatically for bean archives if scanning is enabled. */
    public abstract SeContainerInitializer setClassLoader(ClassLoader classLoader);

    /** Initializes a CDI SeContainerInitializer. (Cannot be called within an application server). */
    public abstract SeContainer initialize();
}

The complete gradle project is here on github.com/elmolm


Florian Schmidt

Senior Java EE Software Engineer, Swift Enthusiast, Techie, Managing Partner Sneed IT UG, Founder Smipty