Help

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.

The beans.xml file is know 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).

NOTE

The XML Bean Config module in Seam 3 allows you to declare and customize beans in beans.xml using an type-safe XML syntax.

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.