A JBoss Project
Red Hat
CDI tagcloud

Weld 3.0.0.Alpha8

2015-4-21: Jozef Hartinger

Weld 3.0.0.Alpha8 has been released. The main change is the enhanced API for using Weld in Java SE environment. In addition, this release comes with several weld-probe improvements.

Enhanced API for Weld SE

Weld has provided support for the Java SE environment for a long time with the weld-se module. The API provides an easy way for an application to initialize Weld and use it in a standalone mode. On initialization Weld SE scans the classpath for bean archives with the beans.xml file, similarly to how it’s done in the Java EE environment.

In this release we are extending the API further. This is partially inspired by the current discussion in the CDI expert group where a standardized CDI API for Java SE is being proposed as part of CDI-26.

The following code snippet shows the new API in action:

Weld builder = new Weld()
        .disableDiscovery()
        .packages(Main.class, Utils.class)
        .interceptors(TransactionalInterceptor.class)
        .property("org.jboss.weld.construction.relaxed", true);
    
    try (WeldContainer weld = builder.initialize()) {
        MyBean bean = weld.select(MyBean.class).get();
        System.out.println(bean.computeResult());
    }

There are several new things to notice:

  • the Weld class is used as a builder to configure Weld before it is initialized

  • automatic scanning can be disabled

  • instead of scanning, classes or packages can be selected explicitly. All classes in those packages will be managed by Weld

  • interceptors, decorators, extensions and Weld-specific configuration options can be specified using the builder

  • WeldContainer now implements AutoCloseable and can therefore be used in a try-with-resources block. At any time that execution gets outside of the code block, the Weld instance is shut down and all managed instances are safely destroyed.

It is also possible to start multiple independent Weld instances:

new Weld().disableDiscovery().containerId("one").beanClasses(MyBean.class).initialize();
    new Weld().disableDiscovery().containerId("two").beanClasses(OtherBean.class).initialize();
    
    MyBean bean = WeldContainer.instance("one").select(MyBean.class).get();
    System.out.println(bean.computeResult());
    
    WeldContainer.instance("one").shutdown();
    WeldContainer.instance("two").shutdown();

Here, two independent WeldContainer instances are initialized. Each of them is given a unique ID. The ID can subsequently be used to obtain a WeldContainer reference in a different place of the code. One possible use-case this enables is for a library or framework (e.g. a testing framework) to use an embedded instance of Weld internally for its own needs (dependency injection, events, extensibility). This instance would not interfere with the Weld instance used by the application.

Obviously, automatic classpath scanning can still be used as before:

try (WeldContainer weld = new Weld().enableDiscovery().initialize()) {
        MyBean bean = weld.select(MyBean.class).get();
        System.out.println(bean.computeResult());
    }

Update:

To play with the new API use the following dependency in you Maven project:

<dependency>
        <groupId>org.jboss.weld.se</groupId>
        <artifactId>weld-se-core</artifactId>
        <version>3.0.0.Alpha8</version>
    </dependency>

Aforementioned classes are from the org.jboss.weld.environment.se package.

Weld Probe Enhancements

Since the last Alpha releases there were several enhancements to Weld Probe. If you are not familiar with Weld Probe, check this introductory blog post first.

A new feature of Probe is that, when the development mode is enabled, it now embeds a tiny information bar directly into the application’s HTML output. That makes it easy to navigate to Probe directly from the application anytime. Furthermore, if invocation tracking is enabled, the information bar helps navigate directly to the invocation tree related to the request that rendered the output.

Weld Probe information bar embedded in application's HTML output


Additionally, the following Probe improvements were implemented:

  • tracked invocations are now grouped into a invocation tree instead of being tracked in isolation

  • a special type of edges is now used in the overview graph to represent a "declared by" relation (when a bean declares a producer method or field)

  • Instance<?> injection points are now treated specially - a resolved bean is show as injection point’s dependency

See this live demo and try Weld Probe yourself.

[ Experimental API documentation ] [ Release notes ] [ Distribution ] [ Patch for Wildfly (8.2, 9 Beta) ]

Weld 3.0.0.Alpha5

2015-2-25: Jozef Hartinger

Weld 3.0.0.Alpha5, the latest release in the series of CDI 2.0 prototypes, has been released. The highlights of the release include new Bean builder API and many improvements to Weld Probe.

Bean Builder API

The common way for frameworks and libraries to expose their API to applications via CDI is by using producer methods. An alternative approach is a custom implementation of the javax.enterprise.inject.spi.Bean interface that is registered by a CDI portable extension. This latter approach gives the extension more control but is also less straightforward.

One of the goals of CDI 2.0 is to fill this gap and simplify extension development. This Weld release comes with a preview of the Bean builder API. The API is inspired by Bean builder API provided by DeltaSpike. In addition, Java 8 lambdas are used in the API to simplify the entire process even further.

Here’s an example of a simple extension that builds and registers a bean:

void register(@Observes ExperimentalAfterBeanDiscovery event) {
        event.addBean()
            .addType(Integer.class)
            .addQualifier(Random.LITERAL)
            .produceWith(() -> new java.util.Random().nextInt(1000));
    }

That’s it! Likewise, it is easy to can define a bean with custom disposal logic using a lambda expression:

void register(@Observes ExperimentalAfterBeanDiscovery event) {
        event.addBean()
            .addType(Connection.class)
            .produceWith(this::newConnection)
            .disposeWith(connection -> connection.close());
    }

See the BeanBuilder Javadoc for more information.

Event monitoring with Probe

We introduced Probe in the previous blog post. This release adds event monitoring view to Probe. In this view both system and application events are displayed. The events can be filtered by type and qualifiers. It is also possible to track which observer methods a particular event was delivered to.

Weld Probe event monitoring

Further improvements

In addition, there were a couple of minor improvements to Probe, namely:

  • better filtering of invocation trees - Probe now searches the whole tree, not just the entry points

  • the context view now displays the conversation context

  • Probe is now more careful and does not try to bind interceptors to classes that are not proxyable

  • all the configuration options for Probe are now documented

If you haven’t tried Probe yet check this demo running on OpenShift. The easiest way to get Probe to run locally is to patch WildFly with a Weld patch. If you’re not familiar with patching WildFly, check Markus’s tutorial.

Relaxed construction

CDI requires that beans that are normal-scoped, intercepted or decorated always define a no-argument constructor. This requirement applies even if the bean already defines an @Inject annotated constructor with parameters. This is purely a technical requirement implied by how Java allocates class instances.

Weld is however able to operate fine even if this requirement is not met. Weld uses special non-portable JVM APIs that allow it to allocate proxy instances without calling proxy’s constructor. This mode is non-portable and needs to be explicitly enabled using a configuration option.

This mode is not new but has been neglected in the past. For this release we added a bunch of tests for this mode, fixed a lot of bugs and enabled it by default in Weld-SE. Any feedback on this mode is appreciated.

Weld 3.0.0.Alpha4

2015-2-5: Jozef Hartinger

Here we are again with the next Alpha release of Weld 3. This time there are no additional CDI 2.0 previews. Instead, this release contains multiple performance improvements, enables @Asynchronous calls to be implemented simply with CDI interceptors and most importantly, it comes with weld-probe.

Weld Probe

Why isn’t my field injected? Why isn’t my interceptor triggered? What extensions do third-party libraries register?

Have you ever found yourself asking a similar question? Making Weld developer-friendly and helpful in troubleshooting is our priority. Yet, similar problems still occur sometimes.

But we can do event better! In Alpha4 of Weld 3 we are introducing a new tool called Weld Probe. Probe is a built-in tool that provides a detailed view into internals of a CDI application. Weld Probe has a web UI and is provided out-of-the-box.

Probe makes it easy to inspect:

  • beans, their properties such as qualifiers, stereotypes and name

  • a graph of bean dependencies

  • observers and producers declared by beans

  • interceptors and decorators bound to a bean

  • extensions

  • information about current contextual instances

  • tracking of invocations and invocation trees

Plus more addons are planned in future.

Weld Probe Screenshot

To try probe all that needs to be done is to upgrade to Alpha4, enable the development mode and point your browser to the URL of your CDI application plus /weld-probe suffix.

For more thorough overview of what Probe provides see Martin’s blog post or the reference documentation. You can play with Probe using this simple CDI application hosted on OpenShift. Just append /weld-probe to the URL.

Bear in mind that Probe is still work in progress and that this early preview may have defects here and there.

Implementing @Asynchronous using CDI interceptor

It is possible to implement a substitute for EJB @Asynchronous method calls using CDI interceptors. Arjan Tijms recently blogged about his solution A similar one can be found in Weld’s testsuite. Long story short: This would not work smoothly until now because of a limitation in Weld. This limitation is now gone in Alpha4.

Performance

This release integrates various runtime performance improvements mainly around bean instance construction, producer and observer method invocation.

Next

Weld 3.0.0.Alpha5 is planned in 3 weeks time from now, with some more CDI 2.0 previews. We are going to continue releasing Alpha versions of Weld 3.0 roughly every 3 weeks until the early draft of CDI 2.0, which should happen sometime in March. At that point, we’ll move to Beta releases.

In the meantime, we’d like to hear your feedback on Probe or on Weld 3.0 Alpha releases in general. Feel free to use our forums or #weld-dev on freenode

An update on Weld 3

2014-12-10: Jozef Hartinger

Today we are releasing the third Alpha release of Weld 3. These Alpha releases serve as prototypes of changes currently being discussed by the CDI expert group for the upcoming CDI 2.0.

The Alpha releases are not suitable for production use as the new API and functionality are still subject to change. We are releasing them to allow the community to test-drive the changes early in the development cycle. We want to shorten the feedback loop and identify possible glitches as soon as possible.

Let’s just quickly review what has been available since Alpha1:

  • declarative ordering of observer methods using @Priority

  • ability for an extension to veto and modify an observer method

  • support for Java 8 repeatable annotations as qualifiers and interceptor bindings

  • enhanced AnnotatedType API

For more details and examples of these features see my previous blog post.

On top of this, we’re now adding the following new features and enhancements:

  • asynchronous events

  • simplified configuration of Weld-specific properties

  • Guava is no longer used internally

Asynchronous events

Since its first version CDI has provided events as a facility for component interaction. Events enable loose coupling while preserving type safety. So far, CDI has supported synchronous delivery of events - the calling thread blocks until invocations of all associated observer methods complete. An alternative to this are transactional observer methods which are called asynchronously at the end of a transaction.

For the upcoming CDI 2.0 specification one of the hot topics is enhancement of the events facility. The expert group is considering adding fully asynchronous event dispatching mechanism.

A working prototype of this is available in Weld 3.0.0.Alpha3. The current proposal adds a method called fireAsync to the existing Event interface.

@Inject
    private ExperimentalEvent<Configuration> event;
    …
    event.fireAsync(new Configuration());

The call to event.fireAsync() returns immediately. The event is delivered to corresponding observers in a dedicated thread pool that can be configured.

What about thread-safety?

There are two common usage pattens for events. In the first one an immutable event object is used. An alternative is to use mutable events. A mutable event allows observers to participate on the result which is later used by the component that fired the event. An example of this would be the ProcessAnnotatedType<T> event used by CDI extensions. When events are fired synchronously, both approaches work fine but how does this work when we switch to async?

Nothing changes actually. No matter if the event object is immutable or not, you do not have to worry about thread-safety of the event object. The current implementation comes with the guarantee that event object is safely published which means that an observer method observes the event in the state in which:

  • it was left by an observer executing before the given observer, or

  • the initial state of the event if the given observer is the first one

Furthermore, the state is consistent throughout the execution of an observer method which means that we guarantee safe publication and prevent races for you. The only thing that should be avoided is modifying the state of the event object outside of an observer method. This behavior matches the option 4.1.1.1 in the current spec proposal.

In addition, if observer methods are ordered (another new feature proposed for CDI 2.0) we preserve the ordering (as in such situation the observers are ordered for a reason!) and invoke observers in the given order.

Last but not least, if an observer is transactional, we again preserve this and invoke the observer method in the corresponding transaction phase.

How do I know when event delivery finishes and what about exceptions?

In the current prototype we’re reusing the CompletionStage API, introduced in Java 8, which allows actions (callbacks) to be bound to the completion of the asynchronous delivery process. This is what it looks like:

event.fireAsync(new Configuration()).thenAccept(config -> master.compute(config));

This piece of code starts with asynchronously firing a mutable configuration object allowing loosely-coupled observers to alter the configuration of a computation. Once all observers finish, computation is initiated based on the resulting configuration.

If an exception occurs this can be dealt with also, either by falling back to a default value

event.fireAsync(new Configuration())
        .exceptionally(throwable -> DEFAULT_CONFIGURATION)
        .thenAccept((config) -> master.compute(config));

or by executing arbitrary code:

event.fireAsync(new Configuration()).whenComplete((config, throwable) -> {
        if (throwable != null) {
            System.err.println("Oops. Failed because of " + throwable.getMessage());
        } else {
            master.compute(config);
        }
    });

CompletionStage allows much more. If you are unfamiliar with the API see the Javadoc page for more information.

How do I try this myself?

It’s easy and multiple options are available. First of them is to use Weld in a standalone application.

  1. Create a new Java SE application.

  2. Add dependency on Weld

    <dependency>
            <groupId>org.jboss.weld.se</groupId>
            <artifactId>weld-se-core</artifactId>
            <version>3.0.0.Alpha3</version>
        </dependency>
  3. Create an empty beans.xml file, e.g.

    mkdir src/main/resources/META-INF
        touch src/main/resources/META-INF/beans.xml
  4. Launch Weld and fire an event asynchronously

    public static void main(String[] args) {
            WeldContainer weld = new Weld().initialize();
            Event<String> evnt = weld.event().select(String.class);
            ExperimentalEvent<String> event = (ExperimentalEvent<String>) evnt;
        
            event.fireAsync("message");
        }

WildFly

Alternatively, a patch is available for WildFly that upgrades Weld within an existing WildFly instance. See the download page for more details.

Note that these new prototyped APIs are not part of the CDI API yet. Instead, they are currently located in Weld API in a package named org.jboss.weld.experimental

All these altered APIs have the Experimental prefix (that’s why we are using ExperimentalEvent in the examples)

We would appreciate your feedback! Feel free to use Weld forums or the cdi-dev mailing list for this purpose.

What’s next?

We are going to continue releasing early prototypes of features currently proposed for CDI 2.0. The plan is to release a new Alpha version every 3 weeks. There are several areas we want to focus on:

  • simplifying how extensions register beans and observers

  • monitoring and debugging of CDI applications

  • experimenting with full interception (intercepting even calls within a given component)

  • splitting the codebase into a “light” and “full” version (to support proposed CDI light version)

  • bootstrap API for SE environment

Weld 3.0.0.Alpha1 released!

2014-10-2: Jozef Hartinger

Today we are releasing Weld 3.0.0.Alpha1. This release serves as an early proof of concept of some of the ideas that are being discussed by the CDI Expert Group for the upcoming CDI 2.0 specification. Furthermore, this is a great opportunity for the community to test-drive some of the proposed improvements and provide us with feedback. Be warned though that this released does not come with any guarantee of stability and that binary and functional compatibility is likely to be broken in the following releases.

Ordering of observer methods

The first of the new features are ordered observer methods. This requirement came up a long ago and several approaches were proposed in the meantime, as documented by CDI-4.The Alpha1 release employs the general-purpose @Priority annotation to determine the order in which observer methods are to be notified.

There are many open questions about this feature. Here are some of the rules we set for the purpose of this experimental implementation. These are by no means set in stone but instead we encourage you to give us feedback on these:

  • Each observer method has a certain priority value. An observer method that does not define a priority explicitly is given the default priority which is 2500 (in the middle of the Interceptor.Priority.APPLICATION range)

  • The priority of an observer method determines the order. An observer method with lower value is called before an observer method with higher value

  • If multiple observer methods define the same priority value, the order is undefined

  • Observer methods priorities should match existing priority range convention

  • The ordering applies to both transactional and non-transactional observer methods

  • The priority annotation is applied on the event parameter (not the observer method)

Here’s an example:

public void sendWelcome(@Observes @Priority(APPLICATION + 800) @Registered User user) {
        // ...
    }

Note that javax.annotation.Priority can currently only be applied to types. Therefore, we temporarily created a substitute called org.jboss.weld.experimental.Priority which is identical to the original except that it can also be applied on parameters (of observer methods). The plan is to propagate this change back to javax.annotation.Priority. In the meantime, Weld’s twin gets the job done.

In addition to the @Priority annotation, the SPI was also enhanced to expose the priority of an observer method. We are not touching javax.enterprise interfaces just yet. Instead, the org.jboss.weld.experimental package contains proposals for how the new SPI should look like. As the package name suggests, this SPI is good for a test-drive but do not expect it to be stable. To use the experimental SPIs, you’ll need to add a dependency on weld-api.

Here’s an example of reading the observer method priority using the SPI in an Extension. ExperimentalProcessObserverMethod and ExperimentalObserverMethod interfaces come from the org.jboss.weld.experimental package.

public class SimpleExtension implements Extension {
    
        void observe(@Observes ExperimentalProcessObserverMethod<User, ?> event) {
            ExperimentalObserverMethod<User> observerMethod = event.getObserverMethod();
            this.priority = observerMethod.getPriority();
        }
    }

Use the corresponding CDI ticket for any feedback on these features.

Vetoing and modifying observer methods

We’ll stay with observer methods for a few more paragraphs. A request was raised in the CDI issue tracker for making it possible to disable an observer method using the ProcessObserverMethod SPI.

This Alpha1 release introduces the veto() methods (aligned with ProcessAnnotatedType.veto()) for this:

void disableDebuggingObservers(@Observes ExperimentalProcessObserverMethod<?, Debug> event) {
        if (projectStage != ProjectStage.Development) {
            event.veto();
        }
    }

In addition, the observer method metadata may be altered by an extension. This is done similarly to how InjectionTarget, InjectionPoint or BeanAttribute metadata are modified which is most often by wrapping the original object (decorator design pattern). Any piece of metadata (including aforementioned priority) can be altered. For example, the transaction phase:

void alterObserver(@Observes ExperimentalProcessObserverMethod<User, ?> event) {
        event.setObserverMethod(new ForwardingExperimentalObserverMethod<User>(event.getObserverMethod()) {
            @Override
            public TransactionPhase getTransactionPhase() {
                return TransactionPhase.AFTER_SUCCESS;
            }
        });
    }

Repeatable qualifiers and interceptor bindings

This release serves as a proof of concept for supporting repeating qualifiers and interceptor bindings. You can now fully utilize Java 8 features and use multiple qualifiers or interceptor bindings of the same type in the same location, for example:

public class School {
    
        @Produces
        @Speaks("English")
        @Speaks("French")
        public Student graduate() {
            // ...
        }
    }

Repeating qualifiers can be used for both bean and event resolution. See the Java documentation for how to define a repeating annotation.

Interceptor bindings in invocation context

This is an often recurring scenario. An interceptor binding defines several @NonBinding members which serve as configuration for the interceptor. How does an interceptor get hold of these values? This is not easy as the interceptor binding may often appear on the intercepted method, the class that defined it or may be inherited from another interceptor binding or stereotype (even transitively!). This problem gave birth to utilities such as this one. Still, even after all this effort the result is not entirely correct as it was obtained using Java reflection ignoring the fact that the interceptor binding may have been modified (e.g. using ProcessAnnotatedType).

This problem is being addressed as CDI-468. The Alpha1 release of Weld implements this feature and exposes new methods for obtaining interceptor bindings that are in effect for the interception. This is done using ExperimentalInvocationContext.getInterceptorBindings() or ExperimentalInvocationContext.getInterceptorBindingsByType().

Again, ExperimentalInvocationContext can be found in the org.jboss.weld.experimental package and depicts how the future version of javax.interceptor.InvocationContext could look like.

@Interceptor
    @Secure
    public class SecurityInterceptor {
    
        @Inject
        private User user;
    
        @AroundInvoke
        public Object intercept(ExperimentalInvocationContext ctx) throws Exception {
            Secure binding = ctx.getInterceptorBindingsByType(Secure.class).iterator().next();
            if (!user.getRoles().contains(binding.requireRole())) {
                throw new SecurityException();
            }
            return ctx.proceed();
        }
    }

Again, your feedback is welcome at CDI-468.

Changes in the Annotated layer

CDI provides an abstraction over the Reflection API - AnnotatedType and friends - which mostly allows extensions to alter the set of annotations present on a type, field, method, etc.

The Alpha1 release contains two minor additions to this API. Firstly, the API now supports Java 8 repeating annotations with a new method ExperimentalAnnotated.getAnnotationsByType(Class<T> annotationClass)

Secondly, it is now possible to access the java.lang.reflect.Parameter instance that is wrapped by AnnotatedParameter using ExperimentalAnnotatedParameter.getJavaParameter();

See CDI-471 and CDI-481 for details.