CDI 2 brings some new nice features but one which is interesting is the programmatic observer registration. Until CDI 1.2 it was quite some work to create a custom observer, now it becomes trivial :).

An observer still needs to be registered in CDI "context" and it is naturally done thanks to AfterBeanDiscovery event (you can also add Beans with this event).

The API uses the new fluent builder API of CDI 2. You define what type/qualifiers you observe and how you observe it:

public class MyExtension implements Extension {
  void addObserver(@Observes final AfterBeanDiscovery afterBeanDiscovery) {
    afterBeanDiscovery.addObserverMethod()
      .observedType(MyEvent.class)
      .notifyWith(e -> /* ... */ });
  }
}

If you want to use the new asynchronous event support (will post more on it in future posts), you just flag your observer method as such:

afterBeanDiscovery.addObserverMethod()
  .observedType(MyEvent.class)

  .async(true)

  .notifyWith(e -> /* ... */ });

There are few more options on the builder:

  • force a bean class for the "enclosing" class of the method (default to the extension)
  • add qualifiers for the event
  • customize the reception
  • read the model from another ObserverMethod
  • set the priority

As a small bonus or thinking exercise, if you use the SE API of CDI 2 you can also create anonymous extensions and a tons of observers using this method which can be very fancy to validate the behavior of your event based runtime:

try (final SeContainer container = SeContainerInitializer.newInstance()
        .disableDiscovery()
        .addExtensions(new Extension() {
            void addABunchOfObserversAtLeastMoreThanThreads(@Observes final AfterBeanDiscovery afterBeanDiscovery) {
                IntStream.range(0, 100)
                        .forEach(i -> afterBeanDiscovery.addObserverMethod()
                                .observedType(MyEvent.class)
                                .notifyWith(e -> { /* do something  */ }));
            }
        })
        .addPackages(MyApp.class)
        .initialize()) {
    // fire some MyEvent and check it worked as expected
}

 

From the same author:

In the same category: