News

Weld 2.4.1.Final

2016-11-18   release   Martin Kouba

The development of Weld 3 (CDI 2) is underway. However, we don’t forget about the maintenance of the stable branch of Weld! So I am very pleased to announce the first bugfix version of Weld 2.4 (CDI 1.2). See also the release details. Thanks to everyone involved in this release!

Notable fixes and improvements:

  • removed false positive warning about Jandex version used (WELD-2231)

  • fixed Groovy support - only filter out relevant methods from Groovy objects when generating bean proxies (WELD-2255)

  • optimized proxy class generation for "large classes" (WELD-2244)

  • improved the way Weld configuration info is logged (WELD-2238)

  • Weld SE

    • added support for nested directories in uber jars, e.g. Spring Boot jar (WELD-2254)

    • allow to use CDI.getBeanManager() after BeforeBeanDiscovery is fired (WELD-2256)

    • don’t abort container initialization if JandexClassFileServices is unable to load an annotation (WELD-2232)

  • Weld Servlet - document the usage of org.jboss.weld.environment.container.class init param (WELD-2236)

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 Markus’s tutorial.


Weld Tip 3 - Boost performance of Weld apps

2016-10-25   tips   Martin Kouba

In this article we’re going to dive into various performance aspects of CDI applications. As you’ve probably noticed performance testing is sometimes tricky. First of all, it’s difficult to create a meaningful benchmark. One should understand the JVM specifics (the need for warmup, garbage collection, JVM settings, etc.) and also use appropriate tools (e.g. JMH for microbenchmarks) accordingly. But even that usually proves to be unsufficient. One should also run the test in a relevant context (data, load, etc.). Performance specialists also say that’s it’s good to avoid premature optimizations but keep performance aspects in mind when tuning the "final" code. But all these considerations are out of scope of this article. Let’s go through several areas where CDI affects the performance of your application and discuss the possibilities.

Bootstrap

During bootstrap the overhead of a framework should be minimal so that it does not slow down the application startup and also does not eat all the memory available. However, CDI needs to do all that magic behind the scenes - read annotations, build and validate metadata, etc. The following sections describe what could be done to minimize the impact.

Discovery mode

In CDI 1.0 there was only one "discovery mode". How does it work? Simply put: find all bean archives (containing beans.xml), discover and process all the found classes (identify beans, etc.). Needless to say, this might be a performance problem for large applications with thousands of classes. In CDI 1.1+ we call this mode all and a bean archive with this mode is called EXPLICIT. Since CDI 1.1+ a new discovery mode - annotated - can be used. The difference is that if this mode is used only classes with a bean defining annotation are considered. In other words, a component must be explicitly designated. A bean archive with this mode is called IMPLICIT. To make things a little bit more complicated, an implicit bean archive does not have to contain a beans.xml file at all. One class with a bean defining annotation or a session bean is enough.

Implicit bean archive has pros and cons:

  • saves a lot of memory if an archive contains a lot of classes which should NOT become beans (the container does not have to store the metadata)

  • speeds up the bootstrap (the container does not have to process all the types, fire events like ProcessBean, etc.)

  • does not fire ProcessAnnotatedType for all types from the bean archive; this breaks some extensions (e.g. MessageBundleExtension from DeltaSpike)

  • does not pick up @javax.inject.Singleton beans (it’s not a bean defining annotation)

CONCLUSION: If possible, use the annotated discovery mode.

Most Weld-based runtimes allow to suppress implicit bean archives without beans.xml, i.e. to require the beans.xml file in bean archives so that it’s not necessary to scan all the parts of the application. See also FAQ.
If it’s not possible to use annotated mode, you can try a Weld-specific feature to conserve memory used: Veto types without bean defining annotation. A similar solution is going to be standardized in CDI 2.0 (see also CDI-420).

Extensions

CDI portable extensions are essential integration points. And users love integrated technologies. However, the more extensions the more work must be done during bootstrap. For example, there is a ProcessAnnotatedType container lifecycle event. This event is fired:

  • for every type in an EXPLICIT bean archive,

  • for every session bean and every type with a bean defining annotation in an IMPLICIT bean archive.

The delivery might be restricted by means of type arguments, e.g. for observer void observeNumbers(@Observes ProcessAnnotatedType<? extends Number> event) an extension will be notified for every class assignable to Number. However, if you do <T> void observe(@Observes ProcessAnnotatedType<T> event) your extension will be notified for every class that is discovered. Now if we have an application with one EXPLICIT bean archive with 2000 classes, then a specific observer method on such extesion will be called 2000x. And if there are three similar extensions, the CDI container will have to create 2000 events and notify 6000 observers. This should be ok unless the observer logic is overly complex.

CONCLUSION: Pay attention to extensions used in your application. If you wonder what extensions are in service, use for example Weld Probe observers view or fired events view together with org.jboss.weld.probe.eventMonitor.containerLifecycleEvents enabled.

If possible, don’t use the extensions which observe all the annotated types from your application, i.e. which defined something like void observe(@Observes ProcessAnnotatedType<?> event). Since CDI 1.1 @WithAnnotations should be used to restrict the set of types an extension is going to process. Weld Probe warns you about these extensions.

Jandex

In some environments (WildFly, Weld SE, and more) Weld can leverage an "offline reflection library", such as Jandex, to speed up the scanning process. These libraries allow to effectively filter classes which are not beans and vetoed classes. It works like this: Jandex generates an index (scans the bytecode) and Weld is using this index to filter out useless classes. As a result Weld does not even have to _load the classes or use reflection API to detect types which should be ignored.

In Weld SE and Servlet it’s also possible to generate the Jandex index beforehand, e.g. using the Ant task.

Runtime

In runtime the overhead of a framework should be minimal so that it’s not an application bottleneck. However, CDI needs to do all that magic behind the scenes - create bean instances, manage contexts, intercept and decorate invocations, etc. The following sections describe what could be done to minimize the impact.

Identify problematic components easily

Before you start a profiler or a similar tool, it’s a good idea to identify all the CDI components involved in a problematic "request". This means all the beans, observer methods, interceptors and decorators. The good start might be the Weld Probe invocation trees view. An invocation tree shows all the business method invocations (including producers, disposers and observer methods). Once you spot a problematic component, you can check the business logic and associated interceptors and decorators. Sometimes profilers are just an overkill.

Lazy initialization of bean instances

Weld initializes bean instances of normal scoped beans lazily. In other words, when injecting a normal scoped bean (@RequestScoped, @ApplicationScoped, etc.) a new instance is not created until actually used. Instead, a shared client proxy is injected. This proxy invokes a method upon the correct bean instance (created if necessary).

Having many injection points resolving to normal scoped beans does not necessarily mean additional overhead associated with bean instance creation.

In the following example, an OrderProcessor instance is not created until its OrderProcess.process() method is called:

@ApplicationScoped
    class OrderProcessor {
      @PostConstruct
      void init() {
        // Do some expensive initialization logic
      }
      void process() {
        // Business logic
      }
    }
    @RequestScoped
    class OrderService {
      @Inject
      OrderProcessor processor; // A shared client proxy is injected
    
      void create(Order order) {
        if (order.isValid()) {
            // Processor is not initialized unless we have a valid order
            processor.process(order);
        }
      }
    }
Weld’s session context is also initilized lazily and doesn’t require an HTTP session to actually exist until a bean instance must be written (i.e. until a method of a @SessionScoped bean is invoked).

Drawbacks of @Dependent pseudo-scope

From performance point of view @Dependent is NOT a best fit for:

  • a bean that declares a producer which is frequently used (i.e. the produced bean is created very often)

  • a bean that declares an observer method which is frequently notified (i.e. the event is fired very often)

  • a bean which is used in EL expressions

For all these cases, a new @Dependent bean instance is created to handle the logic and destroyed when the invocation/evaluation completes. In other words, the bean instances are not reused. That’s not necessarily a problem if a bean does not have an "expensive" initialization or depends on others "heavyweight" components. But very often, a wider scope is more suitable.

Mapping CDI contexts to HTTP requests

By default, bult-in CDI contexts are activated at the beginning of an HTTP request processing and deactivated once the processing finishes. This might be an unnecessary overhead in certain situations, e.g. when serving static resources (images, JavaScript, etc.). Weld allows to activate the contexts only for a subset of requests only. A regular expression may be used for filtering HTTP requests that should have contexts active during their processing.

<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee/"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
        <context-param>
            <param-name>org.jboss.weld.context.mapping</param-name>
            <param-value>.*\.html</param-value> <!-- Only activate contexts for resources with html suffix, e.g. /some/path.html -->
        </context-param>
    </web-app>

Bean identifier index optimization

This optimization is used to reduce the HTTP session replication overhead (clustering use case). Simply put: Weld tries to minimize the amount of bytes send over the network. However, the inconsistency detection mechanism may cause problems in environments where application stop does not imply HTTP session destruction. Thus it’s disabled by default in Servlet containers. See also the reference guide for more info.


Weld Tip 2 - Development Mode

2016-10-7   tips   Martin Kouba

In this article we’re going to cover the special mode for application development. When enabled, a built-in tool called Probe provides a detailed insight into internals of a CDI application. Probe makes it easy to inspect:

  • bean archives

  • beans and 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

  • tracking of fired events

  • Weld configuration

  • and more!

Before you start reading, you might want to check the live demo hosted on OpenShift and see what Probe can offer. Ok, now let’s get it working!

How to enable the development mode

No surprise that the development mode is DISABLED by default. It should NEVER be used in production as it may have negative impact on performance and/or represent a potential security risk. Note that if you successfully enable the development mode you should see Weld Development Mode: ENABLED warning in the log during application bootstrap. Make sure to disable the development mode before deploying to production!

Web application

For any web application, set the Servlet initialization parameter org.jboss.weld.development to true:

<web-app>
        <context-param>
            <param-name>org.jboss.weld.development</param-name>
            <param-value>true</param-value>
        </context-param>
    </web-app>

WildFly

Since WildFly 10 it’s also possible to enable the Weld development mode globally (i.e. for all the applications deployed) by setting development-mode attribute to true:

/subsystem=weld:write-attribute(name=development-mode,value=true)

Weld SE

For a Java SE application, set the system property org.jboss.weld.development to true:

java -cp myCoolApp.jar -Dorg.jboss.weld.development=true com.foo.MyMain

or use the Weld.property() method:

org.jboss.weld.environment.se.Weld;
    
    public static void main(String[] args) {
       Weld weld = new Weld().property("org.jboss.weld.development", true);
       try (WeldContainer container = weld.initialize()) {
          ...
       }
    }

How does it actually work?

Probe collects CDI-related data from your application and then makes the data available through the REST API, eventually through the MXBean of name org.jboss.weld.probe:type=JsonData,context=ID where ID should be replaced with an idenfitier of an application.

Probe UI

Probe has also a web UI (single-page application) available at {webapp-context-path}/weld-probe (once your webapp starts), e.g. http://localhost:8080/weld-numberguess/weld-probe. By default, Probe also 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.

We believe the UI is quite intuitive but feel free to ask questions on any channel (irc, gitter, mailing list, etc.).

Tip
There are some configuration properties which allow to tune or disable Probe features, e.g. to restrict the set of components which will be monitored. See also Development Mode Configuration.

What if I don’t have a webapp?

Nothing is lost! JMX and weld-probe-client-adapter come to rescue. This "adapter" allows to reuse the default HTML UI even if there is no REST API available (non-web environments). The adapter either connects to a JMX server (Probe JMX support must be enabled) or loads data from an exported file (see also Does it work offline?), then starts an embedded Undertow webserver instance and exposes the default HTML client but using the data from the first step.

Does it work offline?

Sometimes it’s not possible to inspect a running system (e.g. due to security reasons). Probe allows to export the collected data and inspect it offline. There are two ways to export the data:

  1. Using REST API: HTTP GET {webapp-context-path}/weld-probe/export

  2. Configure Probe to export data after deployment (see also org.jboss.weld.probe.exportDataAfterDeployment property in Development Mode Configuration)

And now use the weld-probe-client-adapter again:

java -jar weld-probe-client-adapter-1.0.0.Final-shaded.jar /home/weld/weld-probe-export.zip

Weld Tip 1 - Logging

2016-10-1   tips   Martin Kouba

This is the first article from a series of short articles covering some useful Weld features. In this article we talk about logging. The topics for the next articles include: DEVELOPMENT MODE, PERFORMANCE, NON-EE ENVIRONMENTS and TESTING.

Motivation

Logging is usually no fancy stuff. But very often it’s the best thing to start with if problems arise. Moreover, it’s the easiest form of debugging.

In this article you will find:

Under the hood

Weld is using JBoss Logging. This is an abstraction layer wchich does not "write" any log messages at all. Instead, it effectively constructs a log message and then delegates to a back-end logging framework. The supported frameworks include jboss-logmanager, Log4j, SLF4J and JDK logging.

So which logging framework is actually used to write the Weld messages? Well, it depends on the environment. In a Java EE container (e.g. WildFly) the logging configuration is under the direction of the container. You should follow the container-specific guides to change the configuration (see for example WildFly - Logging Configuration and How do I enable debug logging for Weld in a specific container?).

A web application deployed to a servlet container usually bundles a logging framework and possibly some configuration file. In this case, the configuration is in hands of the application developer. If no logging framework is bundled follow the container-specific guides to change the configuration (e.g. Logging in Tomcat).

Tip
A system property org.jboss.logging.provider can be used to specify the logging framework directly. If not set, the JBoss Logging will attempt to find the "best match" on the classpath. See also LoggerProviders.

In Java SE the situation is very similar to servlet containers except the class loading is usually even less complicated (see also How do I enable debug logging for Weld SE?).

Set the log level and use categories to filter messages

The default log level is usually INFO. Weld does not log that much information with this level. You will have to set the log level to DEBUG (or even TRACE) to see what’s going on in your application. If you set the level globally (for all frameworks and libraries), the log files will be bloated and it will be very hard to get some relevant info from there. If you set the level for Weld only (i.e. for org.jboss.weld), it should be better. Moreover, it’s possible to use categories to filter messages from a particular "domain". Weld log messages are grouped into several categories:

  • org.jboss.weld.Bootstrap

  • org.jboss.weld.Validator

  • org.jboss.weld.Bean

  • org.jboss.weld.Context

  • org.jboss.weld.El

  • and others (see also org.jboss.weld.logging.Category)

So for example, if you’re only interested in log messages related to EL resolution set the log level for the org.jboss.weld.El category to TRACE (or level with corresponding priority). Another useful example is the check of Weld configuration. Simply set the log level to DEBUG and filter the org.jboss.weld.Configuration category:

DEBUG [Configuration] WELD-001907: Reading properties file: test.war/WEB-INF/classes/weld.properties
    DEBUG [Configuration] WELD-001903: Configuration key RESOLUTION_CACHE_SIZE already set to 1 000 in a source with higher priority, value 500 from system properties is ignored
    DEBUG [Configuration] WELD-001904: Unsupported configuration key found and ignored: com.foo.bar
    DEBUG [Configuration] WELD-001902: Configuration initialized: {CONCURRENT_DEPLOYMENT=false, RESOLUTION_CACHE_SIZE=1000, RELAXED_CONSTRUCTION=true}

Monitoring bootstrap

CDI is designed to fail fast. An extensive validation is performed during application initialization in order to avoid malicious errors at runtime. Container usually also logs a lot of interesting info during bootstrap. Let’s try to set the log level to DEBUG for the org.jboss.weld.Bootstrap category and see what we get.

Registered beans

As simple as it looks - Weld logs all the beans found in the application, e.g.:

DEBUG [Bootstrap] WELD-000106: Bean: Managed Bean [class org.jboss.cdi.tck.tests.lookup.dependency.resolution.broken.unsatisfied.Vanilla] with qualifiers [@Any @Default]
    DEBUG [Bootstrap] WELD-000106: Bean: Producer Method [String[]] with qualifiers [@BatchProperty @Any] declared as [[UnbackedAnnotatedMethod] @Produces @BatchProperty public org.jberet.creation.BatchBeanProducer.getStringArray(InjectionPoint)]

Actions performed by extensions

There is no doubt that portable extensions are really powerful. They can change almost anything. That’s great for framework/libraries developers. On the other hand, this may cause problems when looking for a bug. There is an application class provided by a developer but what does the CDI container actually see? Well, it depends…​ because portable extensions are allowed to redefine this. And that’s why Weld logs all the "modification" operations performed by extensions, such as ProcessAnnotatedType.veto():

DEBUG [Bootstrap] WELD-000148: ProcessAnnotatedType.veto() called by com.foo.MyExtension@50fed5b1 for [BackedAnnotatedType] public class com.foo.Foo
Tip
If your application deploys successfully, you can use Development Tools to inspect the runtime info (will be covered in one of the follow-up articles).

Weld 2.4.0.Final

2016-9-13   release   Martin Kouba

I am very pleased to announce the first stable version of Weld 2.4 (CDI 1.2). See also the release details. From now on, 2.4 is the current stable version of Weld and 2.3 is not actively developed anymore. Thanks to everyone involved in this release!

Most of the new features were already introduced in First release candidate of Weld 2.4. To sum it up:

  • Removed dependency on com.google.guava:guava

  • Enhanced version of javax.enterprise.inject.Instance

  • Veto AnnotatedType not annotated with a bean defining annotation

  • @ActivateRequestScope interceptor binding moved to Weld API and renamed to @ActivateRequestContext

  • Improved rolling upgrades support

  • Events - reflect the output of CDI-494

  • Probe - allow to filter unused beans

  • Cleanup, cleanup, cleanup…​

  • Initial Java 9 support

Moreover, 2.4.0.Final allows to export the Probe development tool data (to be discussed in one of the following blog posts) and fixes a minor problem in non-EE environments (see also WELD-2227).

In the coming weeks, the Weld team is also going to publish "Weld tips" - a series of concise articles. The intention is to familiarize developers with less known Weld features. There will be no hot news, just useful existing features (repetition is the mother of wisdom ;-).

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 Markus’s tutorial.