My JSF Books/Videos My JSF Tutorials OmniFaces/JSF PPTs
JSF 2.3 Tutorial
JSF Caching Tutorial
JSF Navigation Tutorial
JSF Scopes Tutorial
JSF Page Author Beginner's Guide
OmniFaces 2.3 Tutorial Examples
OmniFaces 2.2 Tutorial Examples
JSF Events Tutorial
OmniFaces Callbacks Usages
JSF State Tutorial
JSF and Design Patterns
JSF 2.3 New Features (2.3-m04)
Introduction to OmniFaces
25+ Reasons to use OmniFaces in JSF
OmniFaces Validators
OmniFaces Converters
JSF Design Patterns
Mastering OmniFaces
Reusable and less-verbose JSF code

My JSF Resources ...

Java EE Guardian
Member of JCG Program
Member MVB DZone
Blog curated on ZEEF
OmniFaces is an utility library for JSF, including PrimeFaces, RichFaces, ICEfaces ...

[OmniFaces Utilities] - Find the right JSF OmniFaces 2 utilities methods/functions

Search on blog

Petition by Java EE Guardians

Twitter

marți, 28 iunie 2016

CDI-JSF: Beans discovery modes

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.

Niciun comentariu :

Trimiteți un comentariu

JSF BOOKS COLLECTION

Postări populare

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors