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.

[OmniFaces utilities (2.4)] Create a copy of the array with items in reversed order


[OmniFaces utilities] The reverseArray() function returns a copy of the array with items in reversed order.

Function:
Usage:

Let's suppose that we have the following simple array defined in a bean:

@Named
@RequestScoped
public class MonthsBean {
   
 private String[] months = new String[] {"January", "February", "March", "April", "May", "June", "July", 
   "August", "September", "October", "November", "December"};

 public String[] getMonths() {
  return months;
 }           
}

Now, we can display the array as it was defined and in reverse order as below:

// as it was defined
<ui:repeat value="#{monthsBean.months}" var="item" varStatus="loop">
 #{loop.index + 1} : #{item} #{!loop.last ? ', ' : ''}
</ui:repeat>

Output:
1 : January , 2 : February , 3 : March , 4 : April , 5 : May , 6 : June , 
7 : July , 8 : August , 9 : September , 10 : October , 11 : November , 12 : December

// reversed (xmlns:of="http://omnifaces.org/functions")
<ui:repeat value="#{of:reverseArray(monthsBean.months)}" var="item" varStatus="loop">
 #{loop.index + 1} : #{item} #{!loop.last ? ', ' : ''}
</ui:repeat>

Output:
1 : December , 2 : November , 3 : October , 4 : September , 5 : August , 6 : July , 
7 : June , 8 : May , 9 : April , 10 : March , 11 : February , 12 : January

JSF 2.3 - Import constants/enums

Let's checkout a common practice for declaring constants in Java using the public static final declaration:

public class Circle {
 private static final float PI = 3.14f;
 private static final String UNIT = " radians";
 ...
}

Also, Java interfaces and enums are very useful in applications (they are part of the Java language ʺbricksʺ):

public interface Car {
 public String MODEL = "Logan";
 public String COUNTRY = "RO";
}

public enum Cars {
 CITROEN, LOGAN, BMW;
}

Now, letʹs suppose that we have these artifacts in a JSF application, as a JSF page author we need to use them in page via EL, as below:

·         Use constants:

#{Circle.PI}
#{Circle.UNIT}

·         Use interfaces and enums:

#{Car.MODEL}

There is no elegant way to say that the above usages will simply not work!

So, now let's consider the following example. First, we define an enum:

public enum PlayerEnum {

 FIRST, SECOND, THIRD;

 public Integer getRank() {
  switch (name()) {
          case "FIRST":
                return 1;
          case "SECOND":
                return 2;
          case "THIRD":
                return 3;
          default:
                return 0;
  }
 }
}

Further, we use this enum in a CDI managed bean:

@Named
@RequestScoped
public class PlayerBean implements Serializable {

 private static final long serialVersionUID = 1L;

 private PlayerEnum selectedPlayerEnum;
 public static final String NAME_C = "Rafael Nadal";

 public PlayerEnum getSelectedPlayerEnum() {
  return selectedPlayerEnum;
 }

 public void setSelectedPlayerEnum(PlayerEnum selectedPlayerEnum) {
  this.selectedPlayerEnum = selectedPlayerEnum;
 }
}

Well, OmniFaces comes with a tag handler named, <o:importConstants/> that is capable to map of all constant field values of the given fully qualified name of a type in the request scope (it works with enums also). This tag handler is detailed in the book Mastering OmniFaces. PrimeFaces also comes with support for import constants and enums. Before PrimeFaces Elite 5.3.8 this support was available in PrimeFaces Extension as <pe:importConstants/> and <pe:importEnum/>.  Afterwards, this support was moved from PrimeFaces extension to PrimeFaces Elite 5.3.8, and is available via <p:importConstants/> and <p:importEnum/>. This tags are detailed in book, PrimeFaces & OmniFaces - Powers Combined.

Starting with JSF 2.3-m07, we can import constants and enums via the  new <f:importConstants/> tag. Check the NAME_C constant from above. Well, this constant (and any other constant from PlayerBean) can be accessed via EL once we import them as below (the type attribute is required and its value represents the fully qualified name of the class/interface/enum to import the constant field values for):

<f:importConstants type="javaee8.jsf23.PlayerBean" />

The <f:importConstants/> supports the var attribute also. You can use it to indicate an alias (the name of the request attribute which exposes the mapping of the constants in the request scope), as
below:

<f:importConstants type="javaee8.jsf23.PlayerBean" var="CONSTANTS" />

Now, we can write this: #{CONSTANTS.NAME_C}

The PlayerEnum can be imported exactly the same:

<f:importConstants type="javaee8.jsf23.PlayerEnum" />

This allows us to loop the enum, as below (returns FIRST SECOND THIRD):

<ui:repeat value="#{PlayerEnum.values()}" var="t">
 #{t}
</ui:repeat>

Now, we can nominate the enum constants:

#{PlayerEnum.FIRST} // returns FIRST
#{PlayerEnum.FIRST.rank} // returns 1

We can put all together and provide enum values as dropdown items:

<h:form>
 <h:selectOneMenu value="#{playerBean.selectedPlayerEnum}">
  <f:selectItems value="#{PlayerEnum}" />
  <f:ajax render="@form" />
 </h:selectOneMenu>
 #{playerBean.selectedPlayerEnum}
 [#{playerBean.selectedPlayerEnum == PlayerEnum.FIRST}]
</h:form>

Even more, we can provide the enum values as dropdown items via the var attribute:

<h:form>
 <h:selectOneMenu value="#{playerBean.selectedPlayerEnum}">
  <f:selectItems value="#{PlayerEnum.values()}" var="t" itemLabel="#{t.rank}" itemValue="#{t}" />
  <f:ajax render="@form" />
 </h:selectOneMenu>
 #{playerBean.selectedPlayerEnum}
 [#{playerBean.selectedPlayerEnum == PlayerEnum.FIRST}]
</h:form>

We can glue all the examples above in the below view:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
   
 <f:metadata>
  <f:importConstants type="javaee8.jsf23.PlayerEnum" />
  <f:importConstants type="javaee8.jsf23.PlayerBean" />
  <f:importConstants type="javaee8.jsf23.PlayerBean" var="CONSTANTS" />
 </f:metadata>
 <h:head>
  <title>JSF 2.3 - ImportConstants</title>             
 </h:head>
 <h:body>                  
  <h5>Display the 'NAME_C' constant value</h5>
  <h:outputText value="#{PlayerBean.NAME_C}"/><br/>
  <h:outputText value="#{CONSTANTS.NAME_C}"/><br/>

  <h5>Loop enum values</h5>
  <ui:repeat value="#{PlayerEnum.values()}" var="t">
   #{t}
  </ui:repeat>

  <h5>Providing enum values as dropdown items and test again 'FIRST'</h5>
  <h:form>
   <h:selectOneMenu value="#{playerBean.selectedPlayerEnum}">       
    <f:selectItems value="#{PlayerEnum}" />
    <f:ajax render="@form" />
   </h:selectOneMenu>
   #{playerBean.selectedPlayerEnum}
   [#{playerBean.selectedPlayerEnum == PlayerEnum.FIRST}]
  </h:form>

  <h5>Providing enum values as dropdown items by var  and test again 'FIRST'</h5>
  <h:form>
   <h:selectOneMenu value="#{playerBean.selectedPlayerEnum}">       
    <f:selectItems value="#{PlayerEnum.values()}" var="t" itemLabel="#{t.rank}" itemValue="#{t}" />
    <f:ajax render="@form" />
   </h:selectOneMenu>
   #{playerBean.selectedPlayerEnum}
   [#{playerBean.selectedPlayerEnum == PlayerEnum.FIRST}]
  </h:form>
 </h:body>
</html>

The complete application is available here.

joi, 23 iunie 2016

[OmniFaces utilities 2.4] Check if the given object is serializable


[OmniFaces utilities] The isSerializable() method returns true if the given object is serializable.

Method:
Usage:

Example 1 - test Object:

import org.omnifaces.util.Utils;
...
Utils.isSerializable(new Object()); // return false

Example 2 - test two classes

// Serializable class
public class ShopingCart implements Serializable {
 ...    
}

// NOT Serializable class
public class Item {
 ...    
}

Utils.isSerializable(new ShopingCart()); // return true
Utils.isSerializable(new Item()); // return false

JSF 2.3 Auto detect Converter based on 1st UISelectMany item

Starting with JSF 2.3, more exactly with m07, we can take advantage of using the auto detection of convertors based on 1st UISelectMany item.The story behind the issue solved in JSF 2.3 is easy to understand via two examples. 

Example 1:

Let's suppose the following code:

<h:form>          
 <h:selectManyListbox value="#{playerBean.selectedRanks}" converter="javax.faces.Integer">               
  <f:selectItems value="#{playerBean.playersRanks}"/>
 </h:selectManyListbox>
 <h:commandButton value="Select" action="#{playerBean.selectedAction()}"/>
</h:form> 

Let's start by supposing that the above built-in converter is not specified. Basically, the playersRanks is a list of integers that "populates" our list, and the selectedRanks represents the user selections:

private ArrayList<Integer> selectedRanks;
private static final ArrayList<Integer> playersRanks;

static {
 playersRanks = new ArrayList<>();
 playersRanks.add(1);
 playersRanks.add(2);
 playersRanks.add(3);
}

public ArrayList<Integer> getPlayersRanks() {
 return playersRanks;
}

public ArrayList<Integer> getSelectedRanks() {
 return selectedRanks;
}

public void setSelectedRanks(ArrayList<Integer> selectedRanks) {
 this.selectedRanks = selectedRanks;
}

So, the user may select the ranks and submit them without issues/errors. Even if no error occurred, we can notice a "strange" behavior if we try to run the following snippet of code:

<ui:repeat value="#{playerBean.selectedRanks}" var="i">
 #{i}: #{i.getClass()}
</ui:repeat>

The output reveals that the selected ranks are strings, not integers as we expected to see:

1: class java.lang.String
3: class java.lang.String

The explanation relies on the fact that "the generic type information of List<Integer> is lost during runtime and therefore JSF/EL who sees only List is not able to identify that the generic type is Integer and assumes it to be default String (as that's the default type of the underlying HttpServletRequest#getParameter()call during apply request values phase) - BalusC".

There are two approaches:
·         explicitly specify a Converter
·         use Integer[] instead

In this case, we can use the built-in javax.faces.Integer built-in converter. Now, we can perform the same test and the output will be:

1: class java.lang.Integer
3: class java.lang.Integer

Example 2:

This use case continue the story from the above use case. Cosider this code:

<h:form>          
 <h:selectManyListbox value="#{playerBean.selectedPlayersList}" converter="playerConverter">               
  <f:selectItems value="#{playerBean.playersList}" var="t" itemLabel="#{t.label}" itemValue="#{t}"/>
 </h:selectManyListbox>
 <h:commandButton value="Select" action="#{playerBean.selectedAction()}"/>
</h:form>

Basically, this time we use data for which we don't have a built-in converter available. The custom converter used here is needed because this time the list is "populated" with several Player instances:

private ArrayList<Player> selectedPlayersList;
private static final ArrayList<Player> playersList;

static {
 playersList = new ArrayList<>();
 playersList.add(new Player("Rafa", "Rafael Nadal"));
 playersList.add(new Player("Roger F", "Roger Federer"));
 playersList.add(new Player("Nole", "Novak Djokovic"));
}

public ArrayList<Player> getPlayersList() {
 return playersList;
}

public ArrayList<Player> getSelectedPlayersList() {
 return selectedPlayersList;
}

public void setSelectedPlayersList(ArrayList<Player> selectedPlayersList) {
 this.selectedPlayersList = selectedPlayersList;
}

// Player class snippet of code 
public class Player implements Serializable {
   
 private String label;
 private String value;

 public Player(String label, String value) {
  this.label = label;
  this.value = value;
 }
 ...

Remember from the above use case that the generic type of List<> is lost during runtime. Since the selected items are treated as strings instead of Player instances, the below code will cause an error because #{i.label} cannot be evaluated:

<ui:repeat value="#{playerBean.selectedPlayersList}" var="i">
 #{i.label}: #{i.getClass()}
</ui:repeat>

Since there is no built-in converter for converting strings to Player instances, we need a custom converter as below:

@FacesConverter("playerConverter")
public class PlayerConverter implements Converter {

 @Override
 public Object getAsObject(FacesContext context, UIComponent component,String value) {
  String[] parts = value.split("/");
  return new Player(parts[0],parts[1]);
 }

 @Override
 public String getAsString(FacesContext context, UIComponent component,Object value) {
  return value.toString();
 }   
}

Now, everything works as expected!

JSF 2.3
Well, while example 1 is pretty simple to "fix", the second example is not so easy since it requires us to write a custom converter. But, JSF 2.3 comes with a new feature that is capable to detect Converter based on 1st UISelectMany item and save us for using a built-in converter or writing a custom one for this purpose. So, in JSF 2.3 the below two codes will work as expected:

1: there is no need to specify a built-in conveter
<h:form>          
 <h:selectManyListbox value="#{playerBean.selectedRanks}" converter="javax.faces.Integer">               
  <f:selectItems value="#{playerBean.playersRanks}"/>
 </h:selectManyListbox>
 <h:commandButton value="Select" action="#{playerBean.selectedAction()}"/>
</h:form> 

<ui:repeat value="#{playerBean.selectedRanks}" var="i">
 #{i}: #{i.getClass()}
</ui:repeat>

2: there is no need to write/specify a custom converter
<h:form>          
 <h:selectManyListbox value="#{playerBean.selectedPlayersList}" converter="playerConverter">               
  <f:selectItems value="#{playerBean.playersList}" var="t" itemLabel="#{t.label}" itemValue="#{t}"/>
 </h:selectManyListbox>
 <h:commandButton value="Select" action="#{playerBean.selectedAction()}"/>
</h:form>

<ui:repeat value="#{playerBean.selectedPlayersList}" var="i">
 #{i.label}: #{i.getClass()}
</ui:repeat>

For studying the implementation please download Mojarra source code and check out the javax.faces.component.UISelectMany, com.sun.faces.renderkit.html_basic.MenuRenderer (especially,  MenuRenderer#getConverterForSelectManyValues()method) and com.sun.faces.util.getConverterForClass().

JSF BOOKS COLLECTION

Postări populare

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors