DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. An Overview of CDI Events

An Overview of CDI Events

Let's look into CDI events and how you can interact with them. We'll cover what they are, how to fire them, listen to them, and add qualifiers.

Pavel Pscheidl user avatar by
Pavel Pscheidl
CORE ·
May. 30, 17 · Tutorial
Like (22)
Save
Tweet
Share
45.08K Views

Join the DZone community and get the full member experience.

Join For Free

Java Enterprise Edition has many features that really stand out. One of the best is the event mechanism, which is part of the Contexts & Dependency Injection for Java specification. Events have been present in Java EE for a long time. The design of the events mechanism is extremely clean, and learning how to use events is therefore very simple. This overview is aimed at developers who are not familiar with the event mechanism and want to get to know the basics. Advanced features of CDI 2.0, like Asynchronous events, are not covered. You will learn to:

  • Fire specific events.
  • Use event qualifier.
  • Observe events fired during transactions.
  • Configure even observer bean instantiation.

At the end of this article, you will find instructions for a quick-to-run sample application available on GitHub, demonstrating capabilities of CDI events.

Simple Events

The goal is to fire an event in one component of the application and listen to it anywhere else. This allows the application components to be more loosely coupled. Whenever an event is fired, all the subscribers/listeners receive it. Java EE (CDI) internally manages a list of all listeners and decides which one to call when. Automatically, without any configuration.

Firing an Event

Firing an event is as simple as injecting a javax.enterprise.event.Event<T> into a bean and invoking its fire(T t) method.

@Named
public class EventSource {

    @Inject
    private Event<String> simpleMessageEvent;

    public void fireEvent(){
    simpleMessageEvent.fire("Hello");
    }

}


The class Event<T> from the javax.enterprise.event package is instantiated and managed automatically by CDI. As you have probably already noticed, there is one generic type T inside the Event<T> class. This is the type of message held inside each and every event fired. Only methods observing the same type will receive the event. The generic type can, of course, be any Java type.

Listening to an Event

In order to observe events application-wide, two steps are required:

  • Create a method accepting the desired type of event as an argument.
  • Annotate the method’s argument with the javax.enterprise.event.Observes annotation.
@Named
public class EventObserver {

    public void observeEvent(@Observes String message){
    System.out.println(message);
    }

}


The number of methods listening to a certain type of event, where the type is the generic parameter T defined inside the injected Event<T>, is not limited. Of course, the method must be present inside any kind of Java EE bean (CDI, EJB).

Event Qualifiers

A common use case is to categorize or in general differentiate events from each other. Event observers can then decide which events they want to listen to. This is done by means of a CDI Qualifier. A qualifier is, in fact, a fancy annotation.

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Important {
}


The resulting @Important annotation is recognized as a qualifier by placing the @Qualifier annotation on it. The name of the annotation is arbitrary. You can use just about anything that is allowed for Java annotations.

There is one strong reason annotations are used as qualifiers: CDI is well thought out and leverages type safety. Using built-in Java types instead of e.g. prehistoric Strings has many benefits for the programmer. One of the strongest reasons are compile-time checks — developers are no longer forced to waste time running the application with each change to check if everything is wired correctly. The compiler does the check naturally.

Firing an Event With a Qualifier

The mechanism of firing an event remains. Only the created qualifier @Important is used to annotate the injected Event<String>. Nothing more is required. The fire() method will automatically let the observers know the message is @Important. There is no work for the developer.

@Named
public class SelectedEventSource {

    @Inject
    @Important
    private Event<String> importantMessageEvent;

    public void fireEvent(){
    importantMessageEvent.fire("Hello");
    }

}


There is also an alternative way of firing an event with a qualifier demonstrated in the [sample application], using the select() method of an Event<T>.

Observing Only Selected Events

Using the @Important qualifier, the event is internally marked as @Important. But this does not stop general observers from receiving the event. Event qualifiers are instead used to limit the mass of the set of event types an observer receives. This limitation is done by simply using the qualifier @Important together with the @Observes annotation.

@Named
public class ImportantEventObserver {

    public void observeImportantMessage(@Observes @Important String message){
    System.out.println(message);
    }

}


This method will receive only events marked as @Important with type String and no other events.

Transactions and Events

Java EE has also had the concept of tranasctions for a long time. Transactions may fail and be rolled backed or may be completed successfully. During transactions, events may be fired. But what if the event observers wants to receive the event only if the transaction ended up in a certain state — for example, successful completion ?

This is very easy to achieve with CDI. The @Observes annotation has a field named during. This field accepts values from the javax.enterprise.event.TransactionPhase enumeration.

@Named
public class TransactionEventObserver {

    public void observeImportantMessage(@Observes(during = TransactionPhase.AFTER_SUCCESS) String message){
    System.out.println(message);
    }

}


This way, the observer will be notified only after the transaction ends successfully. There are five possible states defined by TransactionPhase. The default value is TransactionPhase.IN_PROGRESS — the event is delivered immediately after it was fired.

public enum TransactionPhase {
    IN_PROGRESS,
    BEFORE_COMPLETION,
    AFTER_COMPLETION,
    AFTER_FAILURE,
    AFTER_SUCCESS
}


Event Reception

In a situation when an event is fired, but the observer resides in a bean with no living instance, there are two scenarios possible.

  1. CDI creates the instance and delivers the event to the observer (Reception.ALWAYS)
  2. The event is not delivered (Reception.IF_EXISTS)

This is configured easily per each observer by means of a notifyObserver attribute of the @Observes annotation. The attribute accepts values from the javax.enterprise.event.Reception enumeration. There are only two possible values, Reception.ALWAYS and Reception.IF_EXISTS. By default, when the bean instance is not created, CDI will create it and deliver the event. This corresponds to the first option. The Reception.ALWAYS is used as a default value and can be omitted. In the following example, only the @Observes annotation could be used.

@Named
public class EventObserver {
// Explicit declaration of the default value - can be omitted
    public void observeEvent(@Observes(notifyObserver = Reception.ALWAYS) String message){
    System.out.println(message);
    }

}


If the value is changed to Reception.IF_EXISTS, CDI will deliver the event only to the currently instantiated beans.

@Named
public class EventObserver {
// If there is no bean instantiated, create one
    public void observeEvent(@Observes(notifyObserver = Reception.IF_EXISTS) String message){
    System.out.println(message);
    }

}

Sample Project

There is a sample application on GitHub created to demonstrate the capabilities of CDI events. Starting the application is easy, and no configuration or manual downloads are required, only Maven’s presence is needed.

The simplest and fastest way to do it is to execute maven goal wildfly-swarm:run. On the first run, the WildFly Swarm microcontainer will be downloaded. The application will be scanned, and only the parts required to run the application will be downloaded automatically — a few megabates. In the end, Java EE is about choice, so feel free to choose whichever way of running the Java EE sample application fits you the best.

The application also has clickable GUI to play with.

Event CDI

Published at DZone with permission of Pavel Pscheidl. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • 2023 Software Testing Trends: A Look Ahead at the Industry's Future
  • Why Open Source Is Much More Than Just a Free Tier
  • Better Performance and Security by Monitoring Logs, Metrics, and More
  • Top Five Tools for AI-based Test Automation

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: