News

Weld Tip 4 - Testing CDI/Weld apps

2017-2-1   tips   Tomas Remes, Matej Novotny

In this follow-up article of our Weld Tips series we are going to focus on testing of CDI/Weld applications. Let’s discover options for unit testing in the first part and then continue with integration testing. To set things straight - by integration testing we mean testing in some kind of container and hence in certain environment (SE, servlet, full EE server). However, no matter the environment we always make use of Arquillian integration testing framework.

Using Weld in JUnit tests

Recently we created Weld JUnit extension which uses JUnit4 @Rule to initialize a Weld SE container before each test method execution. For further information please check following blogpost.

Arquillian as the chosen framework for testing

While Arquillian may look complex at first, it is certainly worth it. Here are some of the advantages it gives you:

  • Allows usage of CDI @javax.inject.Inject directly in test classes

  • Works well with ShrinkWrap making archive creation and deployment a breeze

    • ShrinkWrap can create any type of deployment archive (WAR, JAR, even infamous EAR) with exactly the capabilities you wish it to have

    • You can use dedicated beans.xml or @Alternatives for given test case

  • Portability - allows to write one test and run it on any container

    • Arquillian only needs correct adapter; therefore, combined with Maven profiles this gives you some nice fire power for matrix testing

  • Allows for very complex testing scenarios

    • For instance you can create several deployments which you then manually (if you so wish) deploy/undeploy

    • This makes it viable even for cluster testing (session replication, failover scenarios, …​)

  • Can start the application server itself or can just connect to running one

In fact writing tests with Arquillian is quite straightforward. It’s basically about right usage of right annotations. Basic test could like this: [ source, java ]

 package org.arquillian.example;
    
     import javax.inject.Inject;
     import org.jboss.arquillian.container.test.api.Deployment;
     import org.jboss.arquillian.junit.Arquillian;
     import org.jboss.shrinkwrap.api.ShrinkWrap;
     import org.jboss.shrinkwrap.api.asset.EmptyAsset;
     import org.jboss.shrinkwrap.api.spec.JavaArchive;
     import org.junit.Assert;
     import org.junit.Test;
     import org.junit.runner.RunWith;
    
     @RunWith(Arquillian.class)
     public class GreeterTest {
    
         // This static method builds the virtual test deployment archive
         @Deployment
         public static JavaArchive createDeployment() {
             return ShrinkWrap.create(JavaArchive.class)
                 .addClass(Greeter.class)
                 .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
         }
    
         @Inject
         Greeter greeter;
    
         @Test
         public void should_create_greeting() {
            Assert.assertEquals("Hello, Earthling!", greeter.createGreeting("Earthling"));
         }
     }

If you are a complete Arquillian rookie, you might want to look at their Getting started guide. Should you just need an inspiration, you needn’t look any further than our testsuite. To support the though of Arquillian usefulness for CDI/Weld testing, we may also point out that even CDI TCK tests use it.

Now, let’s take a look at different environments and then round it up with Arquillian Weld Embedded container, which can be used in each and every environment.

Java EE application server

When you want to test your application in Java EE application server you basically need to create your test deployment archive, deploy it, execute the test and undeploy the archive. As stated above, ShrinkWrap covers the archive creation (typically WAR or EAR). When it comes to deployment/undeployment, Arquillian controls that, unless you take the reins and control it yourself - just keep an eye for dangling deployments. You also get to chose between using so called managed container, where Arquillian starts and stops the desired container for you, and remote container where Arquillian tries to connect to already running container. Since we are talking Java EE application server, you can use CDI out of the box. Just pay attention to test mode you are using. You can check available Arquillian container adapters here.

For example to use Arquillian WildFly Managed container you need to define following dependency: [ source, xml ]

               <dependency>
                       <groupId>org.wildfly.arquillian</groupId>
                       <artifactId>wildfly-arquillian-container-managed</artifactId>
                       <version>1.1.0.Final</version>
                       <scope>test</scope>
                   </dependency>

Servlet environment

In basic Servlet environment you need to deploy all the dependencies of Weld Servlet integration (as CDI API, Interceptors API, etc.) to your Servlet container and thus embedded container option could be sufficient. As you can see Arquillian offers embedded container adapters for all well known Servlet containers such as Tomcat, Jetty and Undertow.

For example to use Arquillian Embedded Tomcat container you need to define following dependency: [ source, xml ]

               <dependency>
                        <groupId>org.jboss.arquillian.container</groupId>
                        <artifactId>arquillian-tomcat-embedded-8</artifactId>
                        <version>1.0.0.CR8</version>
                        <scope>test</scope>
                    </dependency>

Java SE environment

Java SE is not effectively a container, however it could be very handy to have an option to easily configure classpath elements of your test. This is exactly what Arquillian container SE offers. With this extension you can build your test classpath and the test executes remotely over JMX in new isolated JVM process. You can find basic information in README or you can take look into already mentioned CDI TCK tests where you can find SE testgroup which involves all SE related tests.

The maven dependency for this extension looks like this: [ source, xml ]

               <dependency>
                       <groupId>org.jboss.arquillian.container</groupId>
                       <artifactId>container-se-managed</artifactId>
                       <version>1.0.1.Final</version>
                   </dependency>

Arquillian Weld Embedded container

First of all - this test container is suitable in situations when you know you don’t need to work with full Java EE application server and you are OK with dummy mock EJB, JTA, JPA etc. services. As stated in the beginning of this article, you can use it for any environment but you have to keep it mind, that other technologies/services will be mocked only. By default, this container operates in SE mode, as you don’t need to mock anything there, but you can use a system property (Denvironment=EE) or a programmatic approach in order to make it work in other environments. For full list of supported environments, see Environments.java. We recommend you to take a glance at README file - especially those few lines about flat deployment structure (this means this container is not very suitable for testing EAR deployments) and configuration property for setting testing environment.

The maven dependency for this container could look like this: [ source, xml ]

               <dependency>
                        <groupId>org.jboss.arquillian.container</groupId>
                        <artifactId>arquillian-weld-embedded</artifactId>
                        <version>2.0.0.Beta4</version>
                        <scope>test</scope>
                    </dependency>

Weld 3.0.0.CR1

2017-1-23   release   Martin Kouba

I am very pleased to announce the release of Weld 3.0.0.CR1 (aligned with CDI 2.0-PFD). See also the release details. Thanks to everyone involved in this release! This version of Weld will be part of the JSR 365 Approval Ballot (watch CDI spec website for news). The Beta1 version of Weld 3 turned out to be sufficiently stable and so the first release candidate is mostly dedicated to cleanup and minor optimizations. We would like to release Weld 3.0.0.Final (stable version of CDI 2.0) in early February.

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.Beta1

2016-12-19   release   Martin Kouba

I am very pleased to announce the first Beta version of Weld 3.0.0 (CDI 2.0). See also the release details. Thanks to everyone involved in this release!

This is an important milestone. CDI 2.0 is now considered "feature complete" and so the next Weld 3 versions should be mostly dedicated to cleanup and optimization. The next version will be Weld 3.0.0.CR1 (ETA in mid January). Finally, we would like to release Weld 3.0.0.Final in early February.

New and noteworthy

  • javax.enterprise.inject.spi.InterceptionFactory implementation (WELD-2257)

  • ProcessSyntheticObserverMethod container lifecycle event (WELD-2279)

  • BeforeDestroyed event fired before a context is actually destroyed (WELD-2269)

  • "trimmed" bean archives (WELD-2268)

  • context control - ActivateRequestContext interceptor binding (WELD-2267) and RequestContextController built-in bean (WELD-2266)

  • ProcessSyntheticBean container lifecycle event (WELD-2265)

  • few proposals did not make it into CDI 2.0 and so we enhanced the Weld API:

    • org.jboss.weld.inject.WeldInstance (already part of Weld 2.4 API)

    • org.jboss.weld.interceptor.WeldInvocationContext allows to obtain a set of interceptor bindings for a lifecycle callback, business method, timeout method, or constructor (see also CDI-468)

    • org.jboss.weld.bootstrap.event.WeldAfterBeanDiscovery allows to obtain an InterceptorConfigurator to configure a new Interceptor bean

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 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.