Help

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.

13 comments:
 
21. Dec 2009, 06:15 CET | Link
Piero Sartini | piero(AT)sartini.de

I am not sure I like this behaviour. IMHO it would be way better to have the possibility to define top level packages that are used while discovering beans. In general I like to define what should be included, not what should be excluded.

While prototyping a webapp, it's convenient to have all my classes inside one war - and split them into different modules when they get more stable.Also, how does CDI play together with other IoC containers? Take Tapestry as an example: someone would need to exclude all tapestry-ioc managed classes (pages, components, services, ...) in order to use CDI inside the war. Not very developer friendly.

Maybe I am missing something.. so please take this as the oppinion of someone who just started to learn CDI.

ReplyQuote
 
28. Jan 2010, 05:21 CET | Link
Thomas

Gavin, you saved my day! I was searching for 3 days, why my @Injects are not working, reading this, I know why.

Greets from Germany

 
12. Apr 2010, 03:26 CET | Link

One thing I am struggling with in CDI is the fact that there is basically only one global scope. If I understand correctly, when I have one interface X and an implementation XImpl in the same bean archive then XImpl will be injected when '@Inject X x' is used.

However, when I add a new bean archive to my classpath that contains another implementation of X, then all of a sudden a different implementation would be used. This might be desired behavior but could also be very unwelcome.

In other words, what I would like to be able to define is something like an injection domain, where an injection domain would consist of an explicit list of packages or even classes. Then, for a given injection I could define the injection domain explicitly.

Another question I have is w.r.t. unit testing. In unit test code, I typically create a mock object (for instance using Mockito), like so: X x = mock(X.class);

Then I want to verify interactions on x and want to make sure that my mock is injected instead of the normal implementation. The only way I see that this is currently possible is by defining an alternative and then creating a separate beans.xml only for unit test to enable a mock alternative. Of course, the mock defined in beans.xml is not the mock I create in my unit test (I don't even know the classname of this mock). So from the unit test I would need to make my mock object available as static and then from the mock class declared in the beans.xml delegate to my mock object. This approach is rather cumbersome. Is there perhaps another way to do this?

 
12. Apr 2010, 03:28 CET | Link

Small correction: adding another bean archive with another implementation would lead to an ambiguity that I would need to resolve.

 
23. Dec 2013, 09:15 CET | Link

Looking for a quick and Discount Coach Outlet Online simple sewing craft for Halloween? How about a ‘Boogie Monster’ Tissue Holder from Creative Cheap Coach Factory Outlet Store Team member, Jessica! This easy Halloween craft is kid friendly and fun! Plus you can make them in under 15 minutes.

 
02. Jan 2014, 08:48 CET | Link

Click HELP for text formatting instructions. Then edit this text and check the preview.

 
08. Jan 2014, 13:39 CET | Link

The software's license gives the user the right to use the software in the licensed environment. Some software comes with the license when purchased off the shelf, or an OEM license when bundled with hardware. Other software comes with a free software license, granting the recipient the rights to modify and redistribute the software. Software can also be in the form of freeware or shareware.

 
28. Mar 2014, 22:51 CET | Link

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.

 
12. Apr 2014, 11:46 CET | Link

This post is so informative especially the images posted here do make this blog more outstanding in comparison to others maybe this post needs to be briefed here

 
12. Apr 2014, 11:48 CET | Link

Really these contents needs to be shared on social networking sites as they are really the brief and great masterpieces here

 
12. Apr 2014, 11:49 CET | Link

Got some depth knowledge in advance after having a quick and brief glance on to it, thanks a lot for sharing here on this webpage.

 
12. Apr 2014, 12:06 CET | Link

No content is comparable and admirable then this mentioned for the explanations, a must one to read for everyone.

 
12. Apr 2014, 12:07 CET | Link

Great information shared with the users here, if eel delighted with it.

Post Comment