Contexts & Dependency Injection for Java

Since CDI 1.0

The best way to start is our user guide. You’ll also find a lot of resources on our learning CDI page. And when, ready, you really should check the CDI spec itself. See CDI download page for current CDI spec releases.

Since CDI 1.0

The bean archive descriptor beans.xml should be located at META-INF/beans.xml or WEB-INF/beans.xml.

Since CDI 1.0

You can find the XSD for beans.xml at the following location:

Since CDI 1.0

The beans.xml file is known as the bean archive descriptor. This answer addresses the purpose of this file and why it is needed.

The minimal bean descriptor

First, it’s important to understand that the XML bean descriptor in CDI (META-INF/beans.xml or WEB-INF/beans.xml) is not there to define beans in XML, like in other popular bean containers. Rather, you use this file to enable CDI services for the current bean archive that are difficult to define consistently in Java or which you don’t want to define in Java (e.g., to accomodate testing).

For example, in CDI, XML is used to enable interceptors (which are disabled by default) and define interceptor ordering. So the bean descriptor complements the metadata that is provided in the Java language syntax. (You may still want to define beans in XML for other reasons, but that is the concern of an extension).

Let’s first ask why the beans.xml is required, then look at what services it is used used to enable.

Why is beans.xml required?

You may be wondering, if beans are not described using XML, why do we need beans.xml at all? In particular, why do you need it if you don’t have anything that you would need the bean descriptor to enable (alternatives, interceptors or decorators)?

There are two things about CDI that we need to keep in mind:

  • CDI does not require any special declaration on a Java class to enable it to be injected - that’s right, no annotation or XML declaration at all!

  • CDI does not define any special kind of module - CDI beans can be deployed in a library jar, EJB jar, war, rar, or JVM classpath directory.

The CDI specification calls the process of identifying beans in modules bean discovery.

So there are potentially a lot of classes in the classpath which might be beans! We don’t want to force the container to scan every one of those classes at startup and build its internal metamodel for each of them. This really could make bean discovery very slow.

But there’s another reason we need to give the user some control over which classes are available for injection. We don’t want every class in the classpath to potentially match an injection point, including classes that were never intended to be injected into things. This would force the developer to have to use qualifiers much more often to disambiguate injection points.

So we have two choices. We could have the developer:

  • explicitly exclude modules which do not contain beans, or

  • explicitly declare modules which do contain beans.

Hopefully you agree that the second option is a much better way to go. In following this approach, CDI has the notion of a bean archive. A bean archive is just a module that has a file named beans.xml in the META-INF directory. The container looks for beans in bean archives. It ignores other modules.

Now, you might be wondering if we’ve got the granularity wrong here. Why should module be the right criteria to use for including/excluding a class? Why not consider:

  • a class-level annotation,

  • the package,

  • some type it implements or extends, or

  • some naming convention?

We’ve got the first option covered. Annotate a bean @Alternative, or with an alternative stereotype, and it will be considered disabled by CDI, as long as you don’t explicitly enable it in beans.xml. That’s not quite the same thing as excluding the class from scanning altogether, but it’s close. (One difference is that a portable extension with still get a ProcessAnnotatedType event for that class).

A future version of CDI might allow you to declare excluded packages in beans.xml. Excluding a bean by type or naming convention isn’t really that appealing. In the world of CDI, we use stereotypes for identifying architectural roles. We don’t use marker interfaces or naming conventions. Names really shouldn’t affect functionality as it is too fragile.

Enough theory, what elements are available in beans.xml?

Bean descriptor schema?

If you don’t need to activate any interceptors, decorators or alternatives (you just have plain beans that you need to use in an archive), the beans.xml file can be empty. If you do have one of these requirements, then you need to start popularing the descriptor.

The root element of a beans.xml file is beans, with the following schema:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
      http://java.sun.com/xml/ns/javaee
      http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

The beans element can have one or more of each of the following children:

  • interceptors

  • decorators

  • alternatives

Let’s look at each element in detail.

<interceptors>

By default, a bean archive has no enabled interceptors bound via interceptor bindings. An interceptor must be explicitly enabled by listing the fully qualified class name in a child <class> element of <interceptors>.

There may be zero or more interceptor class elements. The order of the class declarations determines the interceptor ordering. Interceptors which occur earlier in the list are called first. The same class may not be listed twice. And of course, the class must exist and it must be an interceptor class.

<interceptors>
   <class>com.acme.intercept.SecurityInterceptor</class>
   <class>com.acme.intercept.TransactionInterceptor</class>
</interceptors>

<decorators>

By default, a bean archive has no enabled decorators. A decorator must be explicitly enabled by listing the fully qualified class name in a child <class> element of <decorators>.

There may be zero or more decorator class elements. The order of the class declarations determines the decorator ordering. Decorators which occur earlier in the list are called first. The same class may not be listed twice. And of course, the class must exist and it must be an decorator class.

<decorators>
   <class>com.acme.decorate.BigAccountDecorator</class>
   <class>com.acme.decorate.SpecialGiftDecorator</class>
</decorators>

<alternatives>

An alternative is a bean that must be explicitly declared in the beans.xml file if it should be available for lookup, injection or EL resolution. By default, a bean archive has no active alternatives. An alternative must be explicitly declared using the fully qualified bean class name or stereotype class name in either a child <class> or <stereotype> element of <alternatives>, respectively.

An alternative is selected for the bean archive if either: the alternative is a managed bean or session bean and the bean class of the bean is listed, or the alternative is a producer method, field or resource, and the bean class that declares the method or field is listed, or any @Alternative stereotype of the alternative is listed.

There may be zero or more alternative bean class elements. The same class may not be listed twice. And of course, the class must exist and it must be an alternative bean class.

There may also be zero or more @Alternative stereotype elements. The same stereotype may not be listed twice. And of course, the stereotype class must exist and it must be an stereotype annotation.

<stereotypes>
   <class>com.acme.business.MockPaymentProcessor</class>
   <stereotype>com.acme.stereotype.Mock</stereotype>
</stereotypes>

And that’s it! A very simple schema, used only to activate and order CDI services.

Since CDI 1.0

You can find the aggregated JavaDoc for the whole Java EE 6 platform here. Java EE 7 is not available yet.

After encountering CDI for the first time, developers often ask why @Inject is in a different Java package and a different JAR file that CDI annotations like @Produces. The reason is somewhat political, but more a reflection of the fact that the Java EE 6 platform is an aggregation of multiple specifications. @Inject is defined in the JSR-330 specification, whereas @Produces is defined in the JSR-299 specification.

If you get the platform API JAR, then everything is in the same JAR file ;) But they are in different Java packages as a logical separation between specs. That’s just the way it is.

Since CDI 1.0

Both annotation groups originate from different APIs, and have been specified (more or less) independently. While the JSF scope annotations have a clear focus on the JSF view technology, CDI requires scope annotations that are present, no matter if JSF is deployed or not (CDI can be used without JSF). So CDI had no choice but defining it’s own scopes. Unfortunately, Java EE 6 did not align this very well.

You should always use scopes from javax.enterprise.context when using CDI

Since CDI 1.0

The @Model annotation does to things:

  • it makes the bean request-scoped (instead of dependent, the default)

  • it gives the bean an EL name

Creating a request-scoped and named bean is typically accomplished by apply the annotations @RequestScoped and @Named to the class, respectively. Since the combination of these annotations is so common in web applications, the built-in stereotype annotation @Model is provided by CDI as a shorthand.

Here’s an example:

@Model
public class SampleBean {
   private String value;
   public String getValue() { return value; }
   public String setValue(String value) { this.value = value; }
}

This bean can now be bound to an input field in a JSF view:

<h:inputText value="\#{sampleBean.value}"/>

If you need to access a bean directly by EL name in a JSF page, you probably need to give it a scope other than @Dependent. Otherwise, any value that gets set to the bean by a JSF input will be lost immediately. That’s why CDI features the @Model stereotype; it lets you give a bean a name, and set its scope to @RequestScoped in one stroke. If you need to access a bean that really has to have the scope @Dependent from a JSF page, inject it into a different bean, and expose it to EL via a getter method.

A stereotype is an annotation that aggregates other annotations. @Model is one of the built-in stereotype in CDI and is defined as follows:

@Named
@RequestScoped
@Stereotype
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface Model {}

The @Model stereotype annotation is expected to be used frequently in web applications.

Since CDI 1.0

For every normal-scoped bean there is a proxy, and you are seeing the instantiation of two objects: one is the actual bean instance, the other one is the proxy. Both likely invoke the default constructor.

It’s generally considered a bad idea to do initialization in class construction code. Instead, when using managed beans (objects managed by the Java EE container) you should perform initialization in a @PostConstruct or @Inject annotated method.

@SessionScoped
public class SampleBean {
   private Map x;

   @PostConstruct
   protected void init() {
      x = new ConcurrentHashMap();
   }
}
Since CDI 1.0

A CDI implementation may choose to lazily instantiate a normal scoped bean. If you inject a shorter-lived bean into a longer-lived bean (e.g. session scoped into application scoped) then there is no obvious bean to instantiate at this point - depending on the active session for the thread a different bean instance will be injected.

Since CDI 1.0

Interceptors and decorators are applied for business method invocations. For a detailed overview of what a business method invocation is, it’s best to consult the JSR-299 specification, more specifically section 7.2.

  • Initializer methods are not intercepted, so an @Inject method will not be intercepted or decorated while the bean is initialized

  • Lifecycle invocations are interceptor calls themselves - so a @PostConstruct/@PreDestroy-annotated method will not be intercepted or decorated by an @AroundInvoke method when invoked by the container.

  • initializers and lifecycle interceptor methods defined on a bean may be intercepted if they are invoked directly by other beans in the application.

  • Other CDI methods such as producers, disposers and observers are intercepted all the time.

Remember that only references provided by the container are intercepted or decorated. This is important when considering self-invocations (calls to this) - these calls are not business method invocations and will not be intercepted and decorated.

To illustrate this concept, assuming that @InterceptMe is an interceptor binding:

class SelfInvokingClass {

   @InterceptMe
   public void methodA() {}

   @InterceptMe
   public void methodB() {
      this.methodA()
   }

}

class InvokerClass {

   @Inject SelfInvokingClass dependency;

   public void callMethodA() {
     dependency.methodA();
   }

   public void callMethodB() {
     dependency.methodB();
   }
}

When calling InvokerClass.callMethodA(), methodA() will be intercepted.

When calling InvokerClass.callMethodB(), methodB() will be intercepted, but methodA() (invoked from within methodB()) won’t be.

Since CDI 1.0

From reading the spec, you should know that Contexts and Dependency Injection (CDI) creates a bean for every class in a classpath with a beans.xml file. In the absence of any producer methods, you can inject an instance of class B into class A using the following annotated field:

public class A {
    @Inject B b;
}

In this case, both A and B are dependent-scoped beans, but that’s not important for this discussion.

When the injection is processed, an instance of B is instantiated by the container using the default constructor, or the constructor annotated with @Inject, and assigned to the field named b in an instance of class A.

But what if you instead wanted to use a producer method to create the instance of B. You might add the following producer class:

public class BProducer {
    public @Produces B createB() {
        B b = new B();
        // ...or get an instance some other way
        return b;
    }
}

The producer method could also be on the B class itself:

public class B {
   public @Produces B createB() {
      B b = new B();
      // ...or get an instance some other way
      return b;
   }
}

If you attempt to run the code with this producer method in place, you will get an AmbiguousResolutionException when the container boots. Why?

The problem is that you now have two ways to create an instance of B that is not otherwise qualified with any qualifiers. Should the container use B’s constructor or the producer method? The point is, the container is not going to guess. You have to be explicit.

Solution 1: Qualifiers

The quickest, easiest, and preferred way to be explicit is to assign a qualifier to the producer. By doing so, you are being more specific about which one you want the container to use.

Of course, you first need to create a binding type. Let’s call it @Preferred.

@Target({ TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@Qualifier
@interface Preferred {}

Now use this qualifier type to qualify the instance of B produced by the @Produces method:

public class BProducer {
    public @Produces @Preferred B createB() {
        B b = new B();
        // ...
        return b;
    }
}

Now instead of using @Inject to inject the instance of B, you use @Inject @Preferred at the injection point. (@Inject would now inject the instance created using B’s constructor).

public class A {
    @Inject @Preferred B b;
}

The drawback of this approach is that you have to be explicit and sometimes, you don’t want to be explicit. You just want one approach to win over the other without having to further qualify it. That’s the function of alternatives.

Solution 2: Alternatives

An alternative is used to settle a bean resolution ambiguity. Putting the binding types aside for a moment, there is an ambiguity between B’s constructor and the producer method. It’s possible to flag the producer as an alternative and then activate that alternative in a beans.xml file.

Begin by adding the @Alternative annotation (formally @Policy) to the class containing the producer method.

public @Alternative class BProducer {
    public @Produces B createB() {
        B b = new B();
        // ...
        return b;
    }
}

Activate this alternative in a beans.xml file. The body of the <alternative> element is the fully-qualified class name of a class with the @Alternative annotation.

<beans>
  <alternatives>
     <alternative>BProducer</alternative>
  </alternatives>
</beans>

With that configuration in place, you can once again use the @Inject annotation alone to inject the instance of B.

public class A {
    @Inject B b;
}

Wrap-up

A key benefit of CDI is that nothing is left to chance. The AmbiguousResolutionException is an indicator that you have not given good instructions by way of metadata to the execution engine. You can use either binding types or alternatives to exact about which bean should be selected at an injection point.

Since CDI 1.0

Seam established the concept of conversations, which then CDI adopted. In parallel, JSF 2.0 was specified as JSR 314, with a long discussion whether conversation scope was worthwhile or not. Finally it was agreed on a compromise (Flash- and View-Scope), but a Conversation scope was not specified.

You must use CDI if you want conversations with JSF 2

Since CDI 1.1

Adding the @Vetoed annotation to all persistent entities is considered a best practice in most cases. The purpose of this annotation is to prevent the BeanManager from managing an entity as a CDI Bean.

When an entity is annotated @Vetoed no injections will take place. The reasoning behind this is to prevent the BeanManager to perform operations that may cause the JPA provider to break.

@Entity
@Vetoed
public class Foo {
   /* This will not be respected by the BeanManager */
   @Inject
   private Logger log;

   /* This annotation is managed by the EnityManager and not the BeanManager */
   @Column
   private String bar;
}

All JPA persistent entities should be marked with @Vetoed as this will prevent the CDI attempting to manage the lifecycle of the object, and makes it very clear that the object is not managed by CDI. You should do the same for MappedSuperclass, Embedded etc.

You can also annotate a package-info.java to veto all beans in the package.

Since CDI 1.0

Yes, an OSGi version of the CDI 1.0 API is available from the Apache specs project org.apache.geronimo.specs:geronimo-jcdi_1.0_spec:1.0

Since CDI 1.0

In other words, 'is the instance of my extension contextual and what is its scope?'

The container instantiates a single instance of each extension at the beginning of the application initialization process and maintains a reference to it until the application shuts down. The container delivers event notifications to this instance by calling its observer methods.

— CDI Expert Group
Section 11.5 CDI Specification

Speaking in code, the following assertion will be true (because there is always at least one bean):

public class TestExtension implements Extension {
    private List<Bean> beans = new ArrayList<Bean>();

    public void onProcessBean(@Observes ProcessBean e) {
        beans.add(e.getBean());
    }

    public void afterBeanDiscovery(@Observes AfterBeanDiscovery e) {
        assert beans.size() > 0;
    }
}

The possibilities of what you can do with extensions are limitless.

Since CDI 1.0

Sometimes it’s useful to have an AFTER_SUCCESS transactional observer. For example you could update a list when an entity is persisted. However, if you use:

public void userAdded(@Observes(during=TransactionPhase.AFTER_SUCCESS) @Added User user)
{
  // access a persistence context and refresh the user list
}

in a stateful session bean, you will get ''transaction is not active''. You need to use REQUEIRES_NEW by adding @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) to the bean or the to the method.