Why is beans.xml required in CDI?

Posted by    |      

I've seen a couple of folks wondering why CDI requires a beans.xml file in every bean archive. If there's no alternatives, interceptors, or decorators to declare, why do you need to have the empty file?

Well, there's two things about CDI that we need to keep in mind:

  • CDI does not require any special declaration for a Java class 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:

  1. explicitly exclude modules which do not contain beans, or
  2. explicitly declare modules which do contain beans.

I think it's clear that the second option is a much better way to go. Thus, CDI has the notion of a bean archive. A bean archive is just a module that has a file named beans.xml in the metadata 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.

Well, I think 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.)

Excluding a package makes sense to me, and a future version of CDI might allow you to declare excluded packages in beans.xml.

Excluding a bean by type or naming convention doesn't appeal to me at all. In the world of CDI, we use stereotypes for identifying architectural roles. We don't use marker interfaces or naming conventions. I strongly disapprove of having names affect functionality.

We'll experiment with giving you some finer grained control over bean discovery in Weld. However, my expectation is that the current solution is going to work great for most people.


Back to top