JBoss.orgCommunity Documentation

Chapter 4. Errai CDI

4.1. Features and Limitations
4.1.1. Other features
4.2. Events
4.2.1. Conversational events
4.2.2. Client-Server Event Example
4.3. Producers
4.4. safe dynamic lookup
4.5. Deploying Errai CDI
4.5.1. Deployment in Development Mode
4.5.2. Deployment to a Servlet Engine
4.5.3. Deployment to an Application Server

CDI (Contexts and Dependency Injection) is the Jave EE standard (JSR-299) for handling dependency injection. In addition to dependency injection, the standard encompasses component lifecycle, application configuration, call-interception and a decoupled, type-safe eventing specification.

The Errai CDI extension implements a subset of the specification for use inside of client-side applications within Errai, as well as additional capabilities such as distributed eventing.

Errai CDI does not currently implement all life cycles specified in JSR-299 or interceptors. These deficiencies may be addressed in future versions.

Important

Errai CDI is implemented as an extension on top of the Errai IOC Framework (see Chapter 3, Dependency Injection ), which itself implements JSR-330. Inclusion of the CDI module your GWT project will result in the extensions automatically being loaded and made available to your application.

Classpath Scanning and ErraiApp.properties

Errai CDI only scans the contents of classpath locations (JARs and directories) that have a file called ErraiApp.properties at their root. If CDI features such as dependency injection, event observation, and @PostConstruct are not working for your classes, double-check that you have an ErraiApp.properties at the root of every JAR and directory tree that contains classes Errai should know about.

Beans that are deployed to a CDI container will automatically be registered with Errai and exposed to your GWT client application. So, you can use Errai to communicate between your GWT client components and your CDI backend beans.

Errai CDI based applications use the same annotation-driven programming model as server-side CDI components, with some notable limitations. Many of these limitations will be addressed in future releases.

The CDI container in Errai is built around the Errai IOC module , and thus is a superset of the existing functionality in Errai IOC. Thus, all features and APIs documented in Errai IOC are accessible and usable with this Errai CDI programming model.

Any CDI managed component may produce and consume events . This allows beans to interact in a completely decoupled fashion. Beans consume events by registering for a particular event type and optional qualifiers. The Errai CDI extension simply extends this concept into the client tier. A GWT client application can simply register an Observer for a particular event type and thus receive events that are produced on the server-side. Likewise and using the same API, GWT clients can produce events that are consumed by a server-side observer.

Let's take a look at an example.


Two things are noteworthy in this example:

  1. Injection of an Event dispatcher proxy

  2. Creation of an Observer method for a particular event type

The event dispatcher is responsible for sending events created on the client-side to the server-side event subsystem (CDI container). This means any event that is fired through a dispatcher will eventually be consumed by a CDI managed bean, if there is an corresponding Observer registered for it on the server side.

In order to consume events that are created on the server-side you need to declare an client-side observer method for a particular event type. In case an event is fired on the server this method will be invoked with an event instance of type you declared.

To complete the example, let's look at the corresponding server-side CDI bean:


A key feature of the Errai CDI framework is the ability to federate the CDI eventing bus between the client and the server. This permits the observation of server produced events on the client, and vice-versa.

Example server code:


Domain-model:



Client application logic:


Producer methods and fields act as sources of objects to be injected. They are useful when additional control over object creation is needed before injections can take place e.g. when you need to make a decision at runtime before an object can be created and injected.



Producers can also be scoped themselves. By default, producer methods are dependent-scoped, meaning they get called every time an injection for their provided type is requested. If a producer method is scoped @Singleton for instance, the method will only be called once, and the bean manager will inject the instance from the first invokation of the producer into every matching injection point.


For more information on CDI producers, see the CDI specification and the WELD reference documentation .

As an alternative to using the bean manager to dynamically create beans, this can be accomplished in a type-safe way by injecting a javax.enterprise.inject.Instance<T> .

For instance, assume you have a dependent-scoped bean Bar and consider the following:

In this example, calling barInstance.get() returns a new instance of the dependent-scoped bean Bar .

If you do not care about the deployment details for now and just want to get started take a look at the Quickstart Guide .

The CDI integration is a plugin to the Errai core framework and represents a CDI portable extension. Which means it is discovered automatically by both Errai and the CDI container. In order to use it, you first need to understand the different runtime models involved when working GWT, Errai and CDI.

Typically a GWT application lifecycle begins in Development Mode and finally a web application containing the GWT client code will be deployed to a target container (Servlet Engine, Application Server). This is no way different when working with CDI components to back your application.

What's different however is availability of the CDI container across the different runtimes. In GWT development mode and in a pure servlet environment you need to provide and bootstrap the CDI environment on your own. While any Java EE 6 Application Server already provides a preconfigured CDI container. To accomodate these differences, we need to do a little trickery when executing the GWT Development Mode and packaging our application for deployment.

In development mode we need to bootstrap the CDI environment on our own and make both Errai and CDI available through JNDI (common denominator across all runtimes). Since GWT uses Jetty, that only supports read only JNDI, we need to replace the default Jetty launcher with a custom one that will setup the JNDI bindings:

JettyLauncher uses different class loaders to load classes that belongs to the web application, the Jetty server, and the Java standard library itself. In the majority of cases, you can simply put all dependencies into your web application's WEB-INF/lib folder. However, there are cases where putting a dependency in WEB-INF/lib will cause troubles such as ClassCastException when same class is also loaded by a different classloader. To mitigate this problem, JettyLauncher can be instructed that certain classes (or packages) shall be loaded only by the system class loader. To do so, set the Java system property jetty.custom.sys.classes when launching Dev Mode.

For example, when using gwt-maven-plugin:

Once this is set up correctly, we can bootstrap the CDI container through a servlet listener:

We provide integration with the JBoss Application Server , but the requirements are basically the same for other vendors. When running a GWT client app that leverages CDI beans on a Java EE 6 application server, CDI is already part of the container and accessible through JNDI ( java:/BeanManager ).