74

A gentle introduction to CDI 2.0 in Java SE

 7 years ago
source link: https://aboullaite.me/cdi-20-java-se/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Whenever we mention Context and Dependency Injection, we
automatically think about Java EE (Since CDI 1.0 focused strongly on Java EE). But, as you probably know, you don't necessarily need a Java EE (EE4J) application server to enjoy CDI magic. CDI 2.0 allows developers to use the same wiring model in both Java SE and Java EE and introduces new features to make CDI in Java SE more useful.

This blog post shows how to bootstrap CDI 2.0 in Java SE using Weld.

Why adding Java SE support

From the spec we can highlight 3 main reasons:

  • Align with many other Java EE spec (JPA, JAX-RS ...) which support Java SE bootstrapping
  • Boost CDI adoption for Spec and Frameworks
  • Provide a mean of building new stacks out of Java EE

Before CDI 2.0

Using Context Dependency Injection on Java SE applications is something not totally new. Here is how thing could be done using Weld.

First add weld dependency to your pom.xml:

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

To activate CDI we need to create a beans archive and include beans.xml file in the META-INF directory of the classpath. We add an empty beans.xml file:

<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd" >
</beans>

Then we 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();
}
1234567

Although that does work, isn't it more accurate to have a standard way to boot CDI containers ?! That's what CDI 2.0 is about.

Bootstrap a CDI 2.0 container

CDI 2.0 introduced SeContainerInitializer, which is a new api to configure and bootstrap a CDI container under Java SE, it returns a SeContainer that implements Instance<Object> allowing programmatic lookup.

 SeContainerInitializer initializer = SeContainerInitializer.newInstance();
        /** disable discovery and register bean classes manually */
        try (SeContainer container = initializer.disableDiscovery().addBeanClasses(MyService.class).initialize()) {
            container.select(MyService.class);
        }
12345

Notice that we called disableDiscovery() and manually pre-configures all CDI beans to start the CDI environment without the beans.xml file.

Also, 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();
}
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253

To get started, check out this complete example on github, using CDI 2.0. Please feel free to comment below for suggestions and remark.


Recommend

  • 65

    Sometimes data does not make sense until you can look at in a visual form, such as with charts and plots. Being able to quickly visualize your data samples for yourself and others is an important skill both in ap...

  • 39
    • www.tuicool.com 6 years ago
    • Cache

    A gentle introduction to Go Modules

    Go 1.11 introduced a new concept of Modules which brings first class support for managing dependency versions and enabling reproducible builds....

  • 29

    Go 1.11 introduced a new concept of Modules which brings first class support for managing dependency versions and enabling reproducible builds. Go previously had no notion of dependency versions, and it has been a long and arduous road to get wh...

  • 58

    Applying probabilistic models to data usually involves integrating a complex, multi-dimensional probability distribution. For example, calculating the expectation/mean of a model distribution involves such an integration. Man...

  • 54

    I have some grim news for the programmers in the audience. This news comes with a silver lining of course. If you are a web developer (or are thinking about teaching yourself web programming), you probably don't...

  • 49
    • www.tuicool.com 6 years ago
    • Cache

    A Gentle Introduction to Multithreading

    Modern computers have the ability to perform multiple operations at the same time. Supported by hardware advancements and smarter operating systems, this feature makes your programs run faster, both in terms of speed of e...

  • 33
    • www.tuicool.com 6 years ago
    • Cache

    A gentle introduction to SHAP values in R

    Hi there! During the first meetup of argentinaR.org -an R user group-

  • 26

    In this article we’ll cover the basic idea behind symbolic execution, a powerful yet underutilized technique for static program analysis. Using this technique, we can prove that our code obeys certain properties...

  • 62

    Photo by Markus Spiske “Life is a school of probability~Walter B...

  • 12

    Observable Event example with CDI 2.0 (Java EE 8) Code source: GitHub With Java EE 8 CDI will receive a maj...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK