Inject beans into JBoss 7 Modules

It seems like JBoss 7.0 CDI has an issue with injecting beans that are located in shared libraries, and are not part of an EAR file. Irritating (but solved in the next version). However, I didn’t want to upgrade, so I decided to solve it instead.
Here’s a short step-by-step:


Deltaspike is an apache library that has several useful CDI extensions. Add it as a module to your jboss-as. You can use the following module.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.deltaspike">
        <resource-root path="deltaspike-core-api.jar" />
        <resource-root path="deltaspike-core-impl.jar" />
        <module name="" />
        <module name="javax.enterprise.api" />
        <module name="javax.inject.api" />


Reflections is a very useful library that allows you to find classes that has an annotation in runtime.
Add it as a module to your jboss-as.

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.reflections">
        <resource-root path="reflections.jar" />
        <module name="" />
        <module name="org.javassist" />
        <module name="org.slf4j" />

Module extensions

This is the heart of the solution. This module runs when the CDI container starts, and adds relevant beans to the CDI. Make sure this class is part of a JAR file that is inside your EAR file!

This code is greatly influenced from

package com.tona.cdi;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.enterprise.event.Observes;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.util.AnnotationLiteral;
import javax.inject.Named;
import javax.inject.Singleton;

import org.apache.deltaspike.core.util.bean.BeanBuilder;
import org.apache.deltaspike.core.util.metadata.builder.AnnotatedTypeBuilder;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class ModuleConfigurationExtension implements Extension {
    private static final Logger log = LoggerFactory.getLogger(ModuleConfigurationExtension.class);
    private final Map beans = new HashMap();

     * This method is automatically activated by CDI, and loads all classes in the com.tona package that has NAMED or
     * SINGLETON annotations.
     * @param bdd
    void readAllConfigurations(final @Observes BeforeBeanDiscovery bdd, BeanManager bm) {"Starting to load beans from modules");
        addBeansFromPackage(bdd, bm, "com.tona");

    private void addBeansFromPackage(final BeforeBeanDiscovery bdd, BeanManager bm, String packageName) {
        Reflections reflections = new Reflections(packageName);
        Set beanClasses = reflections.getTypesAnnotatedWith(Named.class);

        for (Class bean : beanClasses) {
            @SuppressWarnings({ "unchecked", "rawtypes" })
            AnnotatedType annotatedType = new AnnotatedTypeBuilder().readFromType(bean).create();
            Set foundBeans = bm.getBeans(annotatedType.getBaseType(), new AnnotationLiteral() {

            if (foundBeans.size() == 0) {
                String name;
                Named named = bean.getAnnotation(Named.class);
                if (named == null || Strings.isNullOrEmpty(named.value())) {
                    name = bean.getSimpleName();
                } else {
                    name = named.value();
                beans.put(name, annotatedType);

     * This method actually initializes the beans we discovered in <code>readAllConfigurations</code>. Again - this
     * method is automatically activated by CDI
     * @param abd
     * @param bm
     * @throws Exception
    public void addCdiBeans(final @Observes AfterBeanDiscovery abd, final BeanManager bm) throws Exception {"Starting to initialize beans from modules");

        for (Map.Entry bean : beans.entrySet()) {
            Set foundBeans = bm.getBeans(bean.getValue().getBaseType(), new AnnotationLiteral() {

            if (foundBeans.size() == 0) {
                final Bean cdiBean = createBean(bm, bean.getKey(), bean.getValue());
                log.debug("Added bean " + cdiBean.getName());

    private static Bean createBean(final BeanManager bm,
            final String name,
            final AnnotatedType annotatedType)
            throws Exception {
        final BeanBuilder beanBuilder = new BeanBuilder(bm).

        return beanBuilder.create();

Configuring the extension

Create a file called META-INF/services/javax.enterprise.inject.spi.Extension. It should only have the following line:


Updating your EAR file

The EAR file should have dependencies on the org.deltaspike and org.reflections module. Add it in the MANIFEST.MF file.