News

Arquillian container Weld 2.0.0.Beta1 released!

2016-7-21   arquillian , testing   Tomas Remes

We are pleased to announce a release of embedded Arquillian container adapter for Weld. This container has deserved some love for really long time. We tried to refactor it and introduced new master branch which now corresponds to the 2.0.0.x version stream. The original master was branched in 1.0. There is no more any arquillian-weld-ee-embedded-1.1 or arquillian-weld-se-embedded. It’s squashed to one arquillian-weld-embedded and you can configure environments either programmatically or using configuration properties. See link:https://github.com/arquillian/arquillian-container-weld This new version is going to be used in Weld as soon as possible.

Maven Coordinates:
    <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-weld-embedded</artifactId>
            <version>2.0.0.Beta1</version>
        </dependency>

We would really appreciate if you can try it and let us know your experience!


Weld 2.3.5.Final

2016-7-1   release , plans   Martin Kouba

The next version of the stable 2.3 branch has been released! See also the release details. Thanks to everyone involved in this release!

We plan to create the 2.4 branch of Weld within a few weeks. Weld 2.4 will remain a CDI 1.2 implementation. We would like to do some cleanup (e.g. remove deprecated classes from Weld SE), enhance the API and also add some new features. See also the list of issues for 2.4.0.CR1.

Notable bugfixes and improvements:

  • fixed static disposer method invocation (WELD-2176)

  • fixed private observer/producer/disposer invocation on a bean with decorator (WELD-2179)

  • fixed Instance.destroy() for dependent session beans (WELD-2148)

  • fixed ArraySet.hashCode() to comply with java.util.Set.hashCode() contract (WELD-2185)

  • log veto actions and modifications of lists returned by AfterTypeDiscovery (WELD-2170, WELD-2171)

  • log a warning when a class is annotated with a scope but does not declare an appropriate constructor (WELD-2178)

  • support extension deployed in multiple WARs in an EAR (WELD-2143)

  • detect non-unique BeanDeploymentArchive identifier (WELD-2165)

  • Weld Servlet

    • fixed extraction of bean archive id - problem occures with embedded Jetty (WELD-2161)

    • improve the way JandexDiscoveryStrategy identifies an annotation annotated with @NormalScope (WELD-2160)

    • weld-servlet-core declares dependency on weld-core-jsf

  • Weld SE

    • do not pass system properties to Weld configuration (WELD-2146)

  • Probe - allow to test bean availability in a given bean archive

  • many documentation and reference guide updates

WildFly Patch

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


Update on weld-vertx

2016-6-21   vertx , integration   Martin Kouba

This is a follow-up on the article Weld meets Vert.x. Weld team has just released the first alpha version of weld-vertx (artifacts are available in Maven Central). Since the last time we talked about weld-vertx two new features were added. First, it’s possible to inject the relevant io.vertx.core.Vertx and io.vertx.core.Context instances direcly into beans. Also there is a new module called weld-vertx-web which extends functionality of weld-vertx-core and io.vertx:vertx-web and allows to register Route handlers discovered during container initialization. In other words, it’s possible to configure a Route in a declarative way:

import javax.inject.Inject;
    
    import org.jboss.weld.vertx.web.WebRoute;
    
    import io.vertx.core.Handler;
    import io.vertx.ext.web.RoutingContext;
    
    // This annotation is used to configure a Route
    @WebRoute("/hello")
    public class HelloHandler implements Handler<RoutingContext> {
    
        @Inject
        SayHelloService service;
    
        @Override
        public void handle(RoutingContext ctx) {
            ctx.response().setStatusCode(200).end(service.hello());
        }
    
    }

The registered handler instances are NOT real bean instances, i.e. they’re not managed by the CDI container (similarly as Java EE components). However, the dependency injection is supported.

The central point of integration is the org.jboss.weld.vertx.web.WeldWebVerticle. This Verticle extends org.jboss.weld.vertx.WeldVerticle and provides the WeldWebVerticle.registerRoutes(Router) method:

 class MyApp {
    
         public static void main(String[] args) {
             final Vertx vertx = Vertx.vertx();
             final WeldWebVerticle weldVerticle = new WeldWebVerticle();
    
             vertx.deployVerticle(weldVerticle, result -> {
    
                 if (result.succeeded()) {
                     // Configure the router after Weld bootstrap finished
                     Router router = Router.router(vertx);
                     router.route().handler(BodyHandler.create());
                     weldVerticle.registerRoutes(router);
                     vertx.createHttpServer().requestHandler(router::accept).listen(8080);
                 }
             });
         }
     }

Give it a try and let us know if you have any idea how to extend the functionality of weld-vertx. Any feedback is appreciated!


Programmatic lookup improvements

2016-5-18   api , draft   Martin Kouba

javax.enterprise.inject.Instance is sometimes invaluable companion. For example, Instance allows you to handle unsatisfied and ambiguous dependencies gracefully. E.g. it’s possible to avoid unnecessary deployment problems:

interface OrderProcessor {
      void process(Order order);
      int getPriority();
    }
    
    class OrderService {
    
      @Inject
      Instance<OrderProcessor> instance;
    
      void create(Order order) {
        if (!instance.isUnsatisfied() && !instance.isAmbiguous()) {
            instance.get().process(order);
        } else {
            // Log a warning or throw an exception
        }
      }
    }

It is less known that Instance extends Iterable and so it allows to iterate through contextual references of beans with the specified combination of required type and qualifiers. This might be useful if the set of beans satisfying the given type and qualifiers is not known beforehand. We may also need to resolve ambiguities manually, e.g. inspect all the instances and choose only those matching our needs.

@ApplicationScoped
    class OrderService {
    
      @Inject
      @Any
      Instance<OrderProcessor> instance;
    
      void create(Order order) {
        for (OrderProcessor processor : instance) {
            if (processor.getPriority() > 10) {
                processor.process(order);
            }
        }
      }
    }

Another interesting use case might be selecting exactly one implementation:

@ApplicationScoped
    class OrderService {
    
      @Inject
      @Any
      Instance<OrderProcessor> instance;
    
      void create(Order order) {
        List<OrderProcessor> processors = new ArrayList<>();
        for (OrderProcessor processor : instance) {
            processors.add(processor);
        }
        Collections.sort(processors, Comparator.<OrderProcessor> comparingInt(p -> p.getPriority()).reversed());
        // Use the processor with highest priority
        processors.get(0).ping();
      }
    }

This works nice. But we have to pay extra attention to the scopes. If a Processor implementation is @Dependent a similar usage results in memory leaks. What’s the reason? The Processor instance is the dependent object of Instance<OrderProcessor> which is the dependent object of OrderService. And so each Instance.get() will produce a new Processor bound to the lifecycle of the OrderService. To avoid the leak we should always call Instance.destroy() method in similar cases. However, Instance.destroy() always destroys the underlying contextual instance! Even if you pass e.g. a client proxy of an @ApplicationScoped bean. This is not always desirable. Currently, it’s quite complicated to detect a dependent bean inside the loop.

To extend the possibilities the Weld team is experimenting with org.jboss.weld.inject.WeldInstance - an enhanced version of javax.enterprise.inject.Instance. There are three new methods we find useful. The first one - getHandler() - allows to obtain a contextual reference handler which not only holds the contextual reference but also allows to inspect the metadata of the relevant bean and to destroy the underlying contextual instance. Moreover, the handler implements AutoCloseable:

import org.jboss.weld.inject.WeldInstance;
    
    class Foo {
    
      @Inject
      WeldInstance<Bar> instance;
    
      void doWork() {
        try (Handler<Bar> bar = instance.getHandler()) {
            bar.get().doBusiness();
            // Note that Bar will be automatically destroyed at the end of the try-with-resources statement
        }
    
        Handler<Bar> bar = instance.getHandler()
        bar.get().doBusiness();
        // Calls Instance.destroy()
        bar.destroy();
      }
    
    }

The next method - handlerIterator() - returns an iterator over contextual reference handlers. This might be useful if you need more control over contextual references inside the loop:

@ApplicationScoped
    class OrderService {
    
      @Inject
      @Any
      WeldInstance<OrderProcessor> instance;
    
      void create(Order order) {
        for (Iterator<Handler<OrderProcessor>> iterator = instance.handlerIterator(); iterator.hasNext();) {
                Handler<OrderProcessor> processor = iterator.next();
                processor.get().process(order);
                if (processor.getBean().getScope().equals(Dependent.class)) {
                    // Destroy only dependent processors
                    processor.destroy();
                }
            }
      }
    }

The last one is just a convenient method - isResolvable() - a replacement for !isUnsatisfied() && !isAmbiguous() which is the expression most users are interested in:

class OrderService {
    
      @Inject
      Instance<OrderProcessor> instance;
    
      void create(Order order) {
        if (instance.isResolvable()) {
            instance.get().process(order);
        } else {
            // Log a warning or throw an exception
        }
      }
    }

Weld team is considering adding org.jboss.weld.inject.WeldInstance to the Weld API (2.4 and 3.0). WeldInstance would be automatically available in Weld SE and Weld Servlet where the Weld API is always on the class path. It would be also available in Weld-powered EE containers - in this case, users would have to compile their application against the Weld API and exclude the Weld API artifact from the deployment (e.g. use provided scope in Maven).

See also WELD-2151 and the work in progress: https://github.com/mkouba/core/tree/WELD-2151. And feel free to add comments to this blog post. Any feedback is appreciated!


Weld 3.0.0.Alpha16

2016-4-28   release , cdi2   Martin Kouba

The next experimental Weld version has been released! See also the release details. Thanks to everyone involved in this release!

This release includes a lot of bugfixes and improvements (e.g. all the notable tasks implemented in the latest stable version: Weld 2.3.4.Final). However, the main goal of this release is to align with CDI API 2.0.Alpha4, and in particular to implement the current version of "metadata builders" API (CDI-558). So that everyone can play with the API, discover possibilities and find potential issues. Note that this release also introduces a non-standard experimental feature: Weld SE synthetic container lifecycle event observers. So it should be even easier to get started - no extension class is needed in Weld SE.

Metadata configurators - basic ideas

Note that we don’t use the term "builder" because there is no build() method in the API. Also note that the API is not intended to cover every possible case. Instead, we would like to help with common tasks. And if necessary, an extension developer can always use the original replacement methods for more complicated stuff.

IMPORTANT POINTS:

  • an extension developer receives a configurator instance from a container lifecycle event

  • a configurator instance is always automatically processed at the end of the observer invocation

  • for bean discovery events (all events starting with Process):

    • configureX() methods return the same configurator instance (for the given observer method invocation)

    • the configurator is initialized/preconfigured with the component being processed, e.g. ProcessAnnotatedType.configureAnnotatedType() returns a configurator initialized with ProcessAnnotatedType.getAnnotatedType()

    • the result of the configurator will automatically replace the original component (e.g. AnnotatedType in case of ProcessAnnotatedType)

    • replacement methods (e.g. ProcessAnnotatedType.setAnnotatedType()) should not be used together with configurators (CDI-596)

  • for application lifecycle events (e.g. AfterBeanDiscovery):

    • addX() methods always return a new configurator instance

    • the configurator is always uninitialized/empty, but we should probably define some default values wherever it makes sense (e.g. Reception for observer methods)

    • the result of the configurator will be automatically added (e.g. Bean in case of AfterBeanDiscovery.addBean())

We have prepared some simple examples - see below. More advanced examples can be found in the TCK test cases. And as usual - feel free to add comments to this blog post. Any feedback is appreciated!

BeforeBeanDiscovery example

@Singleton
    class MyService {
        // This class is not placed in a bean archive
    }
    
    class MyExtension implements Extension {
    
        void beforeBeanDiscovery(@Observes BeforeBeanDiscovery event) {
            // Add MyService to the set of discovered classes and replace @Singleton with @ApplicationScoped
            event.addAnnotatedType(MyService.class.getName(), MyService.class)
                   .remove(Singleton.class)
                   .add(ApplicationScoped.Literal.INSTANCE);
        }
    }

ProcessAnnotatedType example

class MyExtension implements Extension {
    
        void processAnnotatedType(@Observes @WithAnnotations({ Observes.class, ObservesAsync.class }) ProcessAnnotatedType<?> event) {
            // Add interceptor binding to all methods annotated with @Observes or @ObservesAsync
            event.configureAnnotatedType()
                    .filterMethods(MyExtension::isObserver)
                    .forEach(methodConfigurator -> methodConfigurator.add(Monitored.Literal.INSTANCE))
        }
    
        static boolean isObserver(AnnotatedMethod<?> annotatedMethod) {
            return annotatedMethod.isAnnotationPresent(Observes.class) || annotatedMethod.isAnnotationPresent(ObservesAsync.class);
        }
    }

ProcessBeanAttributes example

class MyExtension implements Extension {
    
        void processBeanAttributes(@Observes ProcessBeanAttributes<?> event) {
            // For all beans remove the IllegalBeanType from the set of bean types
            if (event.getBeanAttributes().getTypes().contains(IllegalBeanType.class)) {
                Set<Type> legalTypes = new HashSet(event.getBeanAttributes().getTypes());
                legalTypes.remove(IllegalBeanType.class);
                event.configureBeanAttributes().types(legalTypes);
            }
        }
    }

AfterBeanDiscovery example

class MyExtension implements Extension {
    
        void afterBeanDiscovery(@Observes AfterBeanDiscovery event) {
            //  Add a new synthetic observer method - no need to use the fluent API
            ObserverMethodConfigurator<Foo> configurator = event.<Foo>addObserverMethod();
            configurator.observedType(Foo.class);
            configurator.reception(Reception.ALWAYS);
            configurator.transactionPhase(TransactionPhase.IN_PROGRESS);
            configurator.notifyWith((foo) -> System.out.println("Foo observed: " + foo));
    
            // Add dependent bean - Integer between 0 and 999
            event.addBean().addType(Integer.class).addQualifier(Random.Literal.INSTANCE)
                    .produceWith(() -> new java.util.Random().nextInt(1000))
        }
    }

WildFly Patch

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