Building a CDI 2 standalone Java application

User Rating: 0 / 5

Star InactiveStar InactiveStar InactiveStar InactiveStar Inactive
 

In the second article about CDI 2 we will learn how to create a standalone J2SE application featuring CDI2. Let's get started!

Using Context Dependency Injection for J2SE application is something not totally new to developers. For example,before CDI 2 you could start-up the Weld CDI container using the specific classes provided by it. This needed to include at first the correct dependencies:

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

Then you could startup the container with like this:

public static void main(String[] args) throws IOException {
    Weld weld = new Weld();
    WeldContainer container = weld.initialize();
    Application application = container.instance().select(Application.class).get();
    application.run();
    weld.shutdown();
}

Although that does work, it was needed to have a standard way to boot your CDI containers, once that you have available in your classpath the right dependencies. As CDI 2 is progressing quickly (https://jcp.org/aboutJava/communityprocess/pr/jsr365/index.html) to the version 2.0 let's see how you can bootstrap the Weld container with a J2SE project.

The class we will use for this purpose is javax.enterprise.inject.se.SeContainerInitializer which is a CDI container initializer for Java SE. By using it, we will be able to create an instance of a javax.enterprise.inject.se.SeContainer which is your gate for accessing the container in Java SE.

Let's see an HelloWorld CDI 2 example:

package com.mastertheboss;

import javax.enterprise.inject.spi.*;
import javax.enterprise.inject.se.*;

public class CDI2Demo {
	public static void main(String... args) {
		SeContainerInitializer containerInit = SeContainerInitializer.newInstance();
		SeContainer container = containerInit.initialize();

		// Fire synchronous event that triggers the code in App class.
		container.getBeanManager().fireEvent(new SimpleEvent());

		container.close();
	}
}

So, once we have inited the SeContainer we fire a synchronous event that triggers the code in App class:

package com.mastertheboss;

import javax.enterprise.event.*;


public class App {
    public void onEvent(@Observes SimpleEvent ignored, SimpleService service) {
        service.greet();
    }
}

SimpleEvent is just a no-implementation Event:

package com.mastertheboss;

public class SimpleEvent {

}

The observed event will execute the greet() method in SimpleService:

package com.mastertheboss;

import javax.inject.*;

public class SimpleService {
    @Inject
    private Hello greeter;

    public void greet()
    {
        greeter.greet();
    }
}

Just to add a taste of CDI, we've injected the Hello Bean in it which will print the final "Hello World" message:

package com.mastertheboss;

public class Hello {
 
	    public void greet() {
	        System.out.println("Hello World!");
	    }
}

In order to compile and run the HelloWorld project you need mainly two dependencies in your pom.xml:

  • cdi-api 2.0
  • a CDI container implementation such as weld-se-core
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.mastertheboss</groupId>
   <artifactId>cdi-j2se</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>cdi-j2se</name>
   <url>http://maven.apache.org</url>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <weld.version>2.3.3.Final</weld.version>
   </properties>
   <dependencies>
      <dependency>
         <groupId>javax.enterprise</groupId>
         <artifactId>cdi-api</artifactId>
         <version>2.0-PFD</version>
      </dependency>
      <dependency>
         <groupId>org.jboss.weld.se</groupId>
         <artifactId>weld-se-core</artifactId>
         <version>3.0.0.CR1</version>
      </dependency>
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>3.8.1</version>
         <scope>test</scope>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.5.0</version>
            <executions>
               <execution>
                  <phase>test</phase>
                  <goals>
                     <goal>java</goal>
                  </goals>
                  <configuration>
                     <mainClass>com.mastertheboss.CDI2Demo</mainClass>
                  </configuration>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
</project>

Build and run the HelloWorld project with:

$ mvn clean install

And here's your first glorious CDI 2 standalone application:

CDI 2 standalone J2SE tutorial

Once more thing you could try is building an all-in-one archive with includes your application class and CDI implementations. This can be done by Eclipse by exporting your project as a fat JAR which includes all the required dependencies. The only workaround you have to include is excluding Weld's classes from being scanned otherwise you will get validation errors. You can do that by including in your beans.xml the following scan rule:

<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_1_1.xsd"
       version="1.1" bean-discovery-mode="all">
    <scan>
        <exclude name="org.jboss.weld.**" />
    </scan>
</beans>

Here's the full project ready for download: https://github.com/fmarchioni/mastertheboss/tree/master/cdi/cdi-j2se

Follow us on Twitter