News

Tour around Weld 3

2017-5-19   Matej Novotny

This post briefly describes all the main CDI 2.0 features and elaborates on Weld-specific features we added on top of that. It is not intended as a deep-dive but rather to give you the overall idea of what is going on and what can the new release offer. So, enough talk, let’s get the show on the road!

Async Events and Notification Options

Up until now, the only way to send events was to do so synchronously. That meant stopping the work of your current thread to instead occupy it with observer resolution and subsequent notification of observer methods. Once all that was done, the thread resumed it’s work.

With CDI 2.0 there are asynchronous events - a 'fire & forget' way of handling things. Here is how to fire such and event and how to observe it:

[ source, java ]

// nothing new here, plain old Event is used
    @Inject Event<Payload> event;
    
    public void sendAsyncEvent() {
        // we use a new fireAsync method for asynchronous events
        CompletionStage<Payload> eventResult = event.fireAsync(new Payload()).thenAccept(...);
    }
    
    public void asyncObserver (@ObservesAsync Payload payload){ … }

Few things to note here - first of all, the return value of fireAsync is CompletionStage allowing you to chain the work for when the event is done. You can follow-up with more tasks, react on exceptional return value and so on. Another noticeable detail is that observers which are to be notified have to have @ObservesAsync annotation. As you might have guessed, an observer can be notified of either synchronous (@Observes) or asynchronous (@ObservesAsync) events but never both!

Apart from this very basic usage, async events allow you to specify NotificationOptions - an option allowing you to tweak the way notification works. From CDI perspective, there is currently only one standardized option and that enables usage of custom executors which will be used for notifications. But the API was designed in a generic way so that implementation can enrich it with its own options. Weld currently offers two more options - timeout and parallel execution - both of which are well described in Weld docs. And here is a snippet showing it in action:

[ source, java ]

public void sendAsyncEventWithOptions() {
        // we use a secondary version of fireAsync method with NotificationOptions parameter
        event.fireAsync(new Payload(), NotificationOptions.of("weld.async.notification.timeout", 2000));
    }

Configurators API

Another of the key features are Configurators. They are here to ease our work when doing small tweaks in extensions. Here is a snippet showing how easy it can be to register a new bean in AfterBeanDiscovery using configurator. You don’t have to create a new class implementing Bean<X> anymore:

[ source, java ]

public void addABean(@Observes AfterBeanDiscovery event) {
        // get an instance of BeanConfigurator
        event.addBean()
          // set the desired data
          .types(Foo.class)
          .scope(RequestScoped.class)
          .addQualifier(Custom.CustomLiteral.INSTANCE);
          //finally, add a callback to tell CDI how to instantiate this bean
          .produceWith(obj -> new Foo());
    }

Following configurators were added:

  • AnnotatedTypeConfigurator

  • InjectionPointConfigurator

  • BeanAttributesConfigurator

  • BeanConfigurator

  • ObserverMethodConfigurator

  • ProducerConfigurator

On top of that, Weld adds one additional configurator - InterceptorConfigurator. This one allows you to observe WeldAfterBeanDiscovery and then use this configurator to create and register a custom interceptor from scratch.

SE Bootstrap API

A big change in CDI 2.0 is the SE support. Of course, Weld fans have had this for years now, but it has gone official, so that still counts, right?

The official CDI API is very similar to that of Weld, here is how it looks like:

[ source, java ]

public void bootBasicContainer() {
        SeContainerInitializer initializer = SeContainerInitializer.newInstance();
        try (SeContainer container = initializer.initialize()) {
            Assert.assertTrue(container.isRunning());
        }
    }

This is the very basic way; you can also opt to use synthetic bean archive where you cherry-pick all the beans/interceptors/…​ in your archive. CDI spec describes this fairly well, so how about we instead shift our attention to what Weld SE offers on top of that?

A small reminder of how to boot SE container using pure Weld API:

[ source, java ]

public void bootWeldSeContainer() {
        Weld weld = new Weld();
        try (WeldContainer container = weld.initialize()) {
            container.select(FooBean.class).get();
        }
    }

One of the things Weld makes easier, is when you want to create a quick extension, but don’t really want to write a whole new class which you then need to place in META-INF/services or register on bootstrap. You can easily create a 'synthetic extension' programatically:

[ source, java ]

Extension testExtension = ContainerLifecycleObserver.extensionBuilder()
        .add(afterBeanDiscovery((e) -> System.out.println("Bean discovery completed!")))
        .add(processAnnotatedType().notify((e) -> {
                if (e.getAnnotatedType().getJavaClass().getName().startsWith("com.foo")) {
                    e.veto();
                }
            })).build();
    
    try (WeldContainer container = new Weld().addExtension(testExtension).initialize()) {
        // Use the container...
    }

What we just did was to create an extension with two container lifecycle observer methods. It follows a familiar builder pattern and the body of the observer methods is specified as lambda expression. Before booting SE container, we register this extension as we would any other. For more information about this, don’t hesitate to check our older news post.

On-demand Request Context Activation

Especially in SE (although not only there) you might want to activate a RequestContext manually for certain period of time. There are two ways to achieve that, first of which is an interceptor - @ActivateRequestContext. You can use that on either a method or a type (enabling it for all methods). As you might expect, it will activate the context before executing your method and shut it down afterwards. The other way is through means of built-in bean named RequestContextController. This bean can be injected as any other CDI bean and offers to self-explanatory methods: activate and deactivate. The obvious advantage of this approach is that you can enable the context for an extended period of time.

Observer Method Ordering

A small but noteworthy improvement to observer methods. You can not leverage @Priority annotation in observer methods hence ordering them as you wish.

[ source, java ]

public void observeFirst (@Observes @Priority(1) EventPayload payload) {...}
    
    public void observeSecond (@Observes @Priority(2) EventPayload payload) {...}

Intercepting Produced Beans

Up until now, anything you created using producers could not be easily intercepted. CDI 2.0 allows this for @AroundInvoke interceptors in two ways. There is a new method on BeanManager named createInterceptionFactory but most of the time you will rather use a built-in bean InterceptionFactory which can be injected as a producer method parameter. Here is a snippet:

[ source, java ]

@Produces
    @Dependent
    public ProducedBean produceFoo(InterceptionFactory<ProducedBean> factory) {
        factory.configure().add(Counter.Literal.INSTANCE);
        return factory.createInterceptedInstance(new ProducedBean());
    }

To explain this a bit, we first inject the built-in bean with the type equal to the produced type we wish to intercept. Then we configure() it, which returns an AnnotatedTypeConfigurator allowing us to add interceptor binding. Finally, we invoke InterceptionFactory.createInterceptedInstance() which takes a the object we produce as a parameter.

You can read more about this in this CDI spec chapter.

Trimmed Bean Archives

Last but not least feature we will mention are so called 'trimmed' bean archives. You can mark an explicit bean archive as trimmed in beans.xml by adding the </trim> element. Such bean archive will perform an annotated type discovery as with bean-discovery-mode="all" but all types that don’t have a bean defining annotation or any scope annotation are then removed from the set of discovered types.

Even in this case, Weld allows you to go one step further and veto types based on regular expression. It works on a similar principle but affects your whole application - it processess all types from all bean archives. Your archives will be scanned as they would be with bean discovery mode all and ProcessAnnotatedType will be fired for all found annotated types. Then, based on the regular expression you provide, annotated types which do not have a bean defining annotation and match the regular expression will be vetoed.


Weld 3.0.0.Final - the first implementation of CDI 2.0!

2017-5-15   release   Martin Kouba

I am very pleased to announce the release of Weld 3.0.0.Final - the first implementation of CDI 2.0! I would like to thank not only to everyone involved in this particular release but also to the Weld community as a whole and also to all active CDI EG members who invested a lot of energy into the specification process!

[ source, java ]

/**
     * TODO: Continue to deliver bugfixes and improvements
     */
    public class WeldTeam extends OpenSourceCommunity {
    
      @Inject
      @AwesomeNews
      Event<String> event;
    
      public void release() {
        // Fire asynchronously so that we don't need to wait for observer notification before we start celebrating!
        event.fireAsync("CDI 1.2 is dead, long live CDI 2.0!");
        celebrate();
      }
    
    }
Note
Weld 3 is an IMPORTANT MILESTONE. Therefore, we’re preparing a special blogpost summarizing all the important stuff that was added. Expect the Tour around Weld 3 blogpost within a few days.

Let’s sum up the notable changes since 3.0.0.CR2:

  • Weld defines two non-portable notification options to configure the notification of asynchronous observer methods (see also Notification options for more info):

    • weld.async.notification.mode - the notification mode, possible values are: SERIAL (default) and PARALLEL

    • weld.async.notification.timeout - the notification timeout (in milliseconds) after which the returned completion stage must be completed.

      • If the time expires the stage is completed exceptionally with a CompletionException holding the java.util.concurrent.TimeoutException as its cause

      • The expiration does not abort the notification of the observers

  • Session replication - handle situation when HTTPSessionBean might not be serializable (WELD-2346)

  • Fire @Initialied(RequestScoped.class)/@Destroyed(RequestScoped.class) events for a @PostConstruct callback if the request context was activated for the specific callback

  • Weld SE

    • It’s possible to easily register a org.jboss.weld.bootstrap.api.Service during container bootstrap (WELD-2360)

    • Any javax.enterprise.inject.spi.CDI method can now be called during AfterDeploymentValidation (WELD-2371)

    • ContainerInitialized and ContainerShutdown now implement toString() (WELD-2354)

  • Weld Servlet

    • Fixed usage of Jandex on Tomcat when using unpackWars=false (WELD-2357)

  • Added option to disable Jandex in Weld SE and Weld Servlet (WELD-2374)

  • Development tools

    • If a deployment validation fails and the development mode is enabled a simple validation HTML report (which contains a lot of useful information) is generated

      • Users are encouraged to always attach this report when asking a question on the mailing list or any other communication channel

  • Updated documentation and migration notes for integrators

  • Examples cleanup (dropped GAE support, etc.)

WildFly Patch

As usual, a patch for WildFly is available. This time the target platforms are WildFly 10.1.0.Final and WildFly 11.0.0.Alpha1. If you’re not familiar with patching WildFly, check the FAQ.


Weld 2.4.3.Final

2017-4-7   release   Matej Novotny

Even as we get ever closer to CDI 2.0 final version, we shan’t forget about our stable 2.4 branch. Ladies and gentlemen, here comes the next-in-line 2.4 release - Weld 2.4.3.Final!

Notable fixes and improvements:

  • Weld now shares proxy classes for built-in beans of the same type (WELD-2344)

  • Fixed usage of Jandex on Tomcat when using unpackWars=false (WELD-2357)

  • Weld now supports wider variety of non-portable extension observer methods (WELD-2338)

  • There is now new debug level logging during bootstrap which allows to monitor name, start, end and duration of all bootstrap phases (WELD-2336)

  • Session replication

    • Built-in session and conversation scoped beans are not part of the bean identifier index anymore (WELD-2343)

    • Handle situation when HTTPSessionBean might not be serializable (WELD-2346)

  • Weld SE

    • You can now easily register new org.jboss.weld.bootstrap.api.Service during container bootstrap (WELD-2360)

    • Any javax.enterprise.inject.spi.CDI method can now be called during AfterDeploymentValidation (WELD-2371)

    • ContainerInitialized event is now correctly fired after registration of shutdown hook (WELD-2340)

    • ContainerInitialized and ContainerShutdown now implement toString() (WELD-2354)

  • Probe development tool

    • Allow monitoring of bean instance creation using AroundConstruct (WELD-2332)

    • Fixed a situation when bean was wrongly marked as unused when injected as parameter (WELD-2342)

See also the release details. Thanks to everyone involved in this release!

WildFly Patch

As usual, a patch for WildFly is available. This time the target platform is WildFly 10.1.0.Final. If you’re not familiar with patching WildFly, check the FAQ.


Weld 3.0.0.CR2

2017-3-3   release   Martin Kouba

I am very pleased to announce the release of Weld 3.0.0.CR2 (CDI 2.0-PFD). The intention is to provide the latest updates so that early adopters and reviewers can work with up-to-date reference implementation during the JCP review process.

Notable fixes and improvements:

  • InterceptionFactory handles interface correctly (WELD-2335)

  • Enable to obtain InjectionPoint metadata from within BeanConfigurator#produceWith() (WELD-2333)

  • ObserverMethodConfigurator.beanClass() should be preset to the extension class (WELD-2324)

  • Performance improvements in javax.enterprise.inject.Instance implementation (WELD-2322 and WELD-2323)

  • Don’t include built-in session and conversation scoped beans in the bean identifier index (WELD-2343)

  • Support InjectionPoint metadata injected into dependent singleton session bean (WELD-2341)

  • Logging

    • Log DEBUG info about important phases during bootstrap (WELD-2336)

    • Fix the error message when an extension observer method is static (WELD-2331)

    • Improved transactional observer methods logging in case of failure (WELD-2330)

  • Weld SE - ContainerInitialized should be fired after the container is initialized and shutdown hook is registered (WELD-2340)

  • Probe development tool

    • Extended bean archive info

    • Monitor bean instance creation

    • Do not mark a bean as unused if only injected into an observer method or disposer method

    • org.jboss.weld.probe package is vetoed

See also the release details. Thanks to everyone involved in this release!

WildFly Patch

As usual, a patch for WildFly is available. This time the target platform is WildFly 10.1.0.Final. If you’re not familiar with patching WildFly, check the FAQ.


Weld 2.4.2.Final

2017-2-2   release   Martin Kouba

As you may know, CDI 2 (JSR 365) is in Public Review phase. That’s great news for early adopters. But for now, I am very pleased to announce another production-ready version of Weld 2.4 (CDI 1.2). See also the release details. Thanks to everyone involved in this release!

Warning
There is a regression in Weld 2.4.2.Final. The problem only occurs if a Security Manager is used. However, users are encouraged to upgrade to 2.4.2.SP1 which contains a fix for the issue.

Notable fixes and improvements:

  • Added trimmed bean archives support (CDI 2.0, WELD-2314)

  • Fixed Weld SE and Weld Servlet cooperation (WELD-2260 and WELD-2262)

  • Fixed ActivateRequestContextInterceptor - align the priority with CDI 2.0, fire @Initialized and @Destroyed events (CDI 2.0, WELD-2281)

  • Fixed JDK9 build problems (WELD-2303 and WELD-2301)

  • Validation - allow to use CDI 2 rules when validating selected alternatives in bean.xml (WELD-2313)

  • Performance improvements in javax.enterprise.inject.Instance implementation (CDI 2.0, WELD-2323)

  • Illegal bean types ignored for a session bean (WELD-2315)

  • Dependency upgrade - jboss-classfilewriter to 1.2.1.Final (enables interception of default methods, see also WELD-2093)

  • Weld SE - addded useful methods from SeContainerInitializer (CDI 2.0, WELD-2316)

  • Probe development tool - extended bean archive info

WildFly Patch

As usual, a patch for WildFly is available. This time the target platform is WildFly 10.1.0.Final. If you’re not familiar with patching WildFly, check the FAQ.