When we write applications that involves CDI we need to activate CDI by
adding in our project a file named beans.xml. Usually, this file will look like below:
<?xml
version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
</beans>
In this post, we are interested in the part highlighted in red. If you
never notice that part before, then this quick post is for you. Let's see what
is happening when we have bean-discovery-mode="all",
and for this let's consider a simple interface with two implementations, as
follows:
public
interface IFoo {
public void fooSlaveAction();
}
@RequestScoped
public class
FooImplAnnotated implements IFoo {
private static final Logger LOG =
Logger.getLogger(FooImplAnnotated.class.getName());
@Override
public void fooSlaveAction() {
LOG.info("FooImplAnnotated#fooSlaveAction() invoked ...");
}
}
public class
FooImplNoAnnotation implements IFoo {
private static final Logger LOG =
Logger.getLogger(FooImplNoAnnotation.class.getName());
@Override
public void fooSlaveAction() {
LOG.info("FooImplNoAnnotation#fooSlaveAction() was invoked
...");
}
}
As you can see, the main difference between these two implementations
consist in the fact that FooImplAnnotated
is annotated with a CDI annotation, @RequestScoped. Well, now let's inject these
two implementation in a third CDI bean:
@Named
@RequestScoped
public class
FooBean {
// inject the annotated bean
@Inject
private FooImplAnnotated fooAnnotated;
// inject the no-annotation bean
@Inject
private FooImplNoAnnotation fooNoAnnotation;
public void fooMasterAction(){
// call fooSlaveAction() of the annotated
bean
fooAnnotated.fooSlaveAction();
// call fooSlaveAction() of the no annotation
bean
fooNoAnnotation.fooSlaveAction();
}
}
If we test this application (for example by calling the fooMasterAction() method via a simple EL as #{fooBean.fooMasterAction()}), we will get the following messages in the server log:
FooImplAnnotated#fooSlaveAction()
invoked ...
FooImplNoAnnotation#fooSlaveAction()
was invoked ...
Ok, this is the effect of using bean-discovery-mode="all"
who tells CDI to discover all beans. No, let's alter the beans.xml as switch
the value of bean-discovery-mode
from all to
annotated:
<?xml
version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="annotated">
</beans>
This time the test will fail with an error of type org.jboss.weld.exceptions.DeploymentException:
WELD-001408: Unsatisfied dependencies for type FooImplNoAnnotation with
qualifiers @Default. Well, the problem is that the FooImplNoAnnotation is
not discoverable and it cannot be injected in FooBean. Since we are looking only for
annotated implementation, we can re-write our FooBean like below:
@Named
@RequestScoped
public class
FooBean {
// inject the annotated bean
@Inject
private IFoo fooAnnotated;
public void fooMasterAction() {
// call
fooSlaveAction() of the annotated bean
fooAnnotated.fooSlaveAction();
}
}
Now, the test will pass again, and the server log will reveal this
message:
FooImplAnnotated#fooSlaveAction()
invoked ...Since the
FooImplNoAnnotation
is not discoverable, CDI has choose
the single available implementation,
FooImplAnnotated. Of course, if we make the
FooImplNoAnnotation discoverable
by adding a CDI annotation to it, then CDI will cause
ambiguous
dependencies errors.
Ok, finally, let's switch the value of bean-discovery-mode from annotated to none:
<?xml
version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="none">
</beans>
This time the test will not cause any error and no messages will be
available in the server log. We just told CDI to not try to discover any bean.
The complete example is available
here.