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

luni, 23 martie 2015

[JSF Page Author Beginner's Guide] JSF <messages> component / HTML5 <ul>/<li> elements

The <h:messages> is used in JSF to display all info/warn/error/fatal messages in current page 
(renders HTML markup, <ul> / <li>)
Note Starting with JSF 2.0, in Development stage, JSF  automatically attached a <h:messages> child to the current page. (the Mojarra 2.2 does this in RenderKitUtils.renderUnhandledMessages() method by creating an instance of the HtmlMessages component with ID, javax_faces_developmentstage_messages). This is why you can see all messages without having an explicit <h:messages> or<h:message> in your page. 

Common/basic usage in JSF:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"     
      xmlns:h="http://xmlns.jcp.org/jsf/html">
 <h:head>
  <title>JSF messages examples</title>        
 </h:head>
 <h:body>
  <h:form>
   <h:outputLabel value="Name:" for="nameId"/>
   <h:inputText id="nameId" value="#{playerBean.name}" label="name"/>   
   <h:outputLabel value="Age:" for="ageId"/>
   <h:inputText id="ageId" value="#{playerBean.age}" label="age">
    <f:validateLongRange for="ageId" minimum="18" maximum="45" />
   </h:inputText>
   <h:commandButton value="Send"/>
   <h:messages/>
  </h:form>
 </h:body>
</html>

For an invalid value (e.g. empty string), the <h:messages> will be rendered in HTML as (caused by <f:validateLongRange> validator):

<ul><li> age: Validation Error: Value is not of the correct type. </li></ul>

For an invalid value (e.g. 10), the <h:messages> will be rendered in HTML as (caused by <f:validateLongRange> validator):

<ul><li> age: Validation Error: Specified attribute is not between the expected values of 18 and 45. </li></ul>

The PlayerBean will be:

package beans;

import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named
@SessionScoped
public class PlayerBean implements Serializable {

 private String age; 
 private String name;

 public String getAge() {
  return age;
 }

 public void setAge(String age) {
  this.age = age;
 }   

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }
}

Data flow in image:

More examples:
The next examples takes use of a custom validator that always return a invalid message containing summary and detail:

package beans;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

@FacesValidator(value = "myValidator")
public class MyValidator implements Validator {

 @Override
 public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {

  FacesMessage message = new FacesMessage();
  message.setDetail("Detail: I'm a dummy detail section.");
  message.setSummary("Summary: Dummy!");
  message.setSeverity(FacesMessage.SEVERITY_ERROR);
  throw new ValidatorException(message);
  }
}

Styling messages with inner CSS code
<h:form>
 <h:outputLabel value="Name:" for="nameId"/>
 <h:inputText id="nameId" value="#{playerBean.name}" label="name">
  <f:validator validatorId="myValidator"/>
 </h:inputText>
 <h:outputLabel value="Age:" for="ageId"/>
 <h:inputText id="ageId" value="#{playerBean.age}" label="age">
  <f:validateLongRange for="ageId" minimum="18" maximum="45" />
 </h:inputText>
 <h:commandButton value="Send"/>
 <h:messages style="color: red;"/>
</h:form>

Styling messages with CSS class
<h:form>
 <h:outputLabel value="Name:" for="nameId"/>
 <h:inputText id="nameId" value="#{playerBean.name}" label="name">
  <f:validator validatorId="myValidator"/>
 </h:inputText>
 <h:outputLabel value="Age:" for="ageId"/>
 <h:inputText id="ageId" value="#{playerBean.age}" label="age">
  <f:validateLongRange for="ageId" minimum="18" maximum="45" />
 </h:inputText>
 <h:commandButton value="Send"/>
 <h:messages styleClass="messagecss"/>
</h:form>

The infoStyle/infoClass - Styling info messages with inner style / CSS class (only FacesMessage.SEVERITY_INFO will have this style)
<h:form>
 <h:outputLabel value="Name:" for="nameId"/>
 <h:inputText id="nameId" value="#{playerBean.name}" label="name"/>                
 <h:outputLabel value="Age:" for="ageId"/>
 <h:inputText id="ageId" value="#{playerBean.age}" label="age">              
  <f:validateLongRange for="ageId" minimum="18" maximum="45" />
 </h:inputText>
 <h:commandButton value="Send" action="#{playerBean.info()}"/>
 <!-- infoStyle -->
 <h:messages infoStyle="color:green;font-size:20px;"/>
 <!-- infoClass -->
 <h:messages infoClass="infocss"/> 
</h:form>
In the first case, the inserted value, 10, is not valid, so the applications "stops" in the Process Validations phase, and a message of type error is returned. This message doesn't benefit of a custom CSS, so is  displayed via JSF default style. When a valid value is provided, the application flow reaches a dummy PlayerBean method, named info(). This method simply put in messages queue a global message of type info, which will be styled via infoStyle/infoClass:

public void info() {
 FacesContext context = FacesContext.getCurrentInstance();
 // add an info message
 context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "This is an info message !", "This message is just a dummy info message to see how it works !"));
}

The warnStyle/warnClass - Styling warning messages with inner style / CSS class (only FacesMessage.SEVERITY_WARN will have this style)
<h:form>
 <h:outputLabel value="Name:" for="nameId"/>
 <h:inputText id="nameId" value="#{playerBean.name}" label="name"/>                
 <h:outputLabel value="Age:" for="ageId"/>
 <h:inputText id="ageId" value="#{playerBean.age}" label="age">              
  <f:validateLongRange for="ageId" minimum="18" maximum="45" />
 </h:inputText>            
 <h:commandButton value="Send" action="#{playerBean.warn()}"/>
 <!-- warnStyle -->
 <h:messages warnStyle="color:orange;font-size:20px;"/> 
 <!-- warnClass -->
 <h:messages warnClass="warncss"/>
</h:form>
In the first case, the inserted value, 10, is not valid, so the applications "stops" in the Process Validations phase, and a message of type error is returned. This message doesn't benefit of a custom CSS, so is  displayed via JSF default style. When a valid value is provided, the application flow reaches a dummy PlayerBean method, named warn(). This method simply put in messages queue a global message of type warning, which will be styled via warnStyle/warnClass:

public void warn() {
 FacesContext context = FacesContext.getCurrentInstance();
 // add an warning message
 context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "This is an warning message !", "This message is just a dummy warning message to see how it works !"));
}

The errorStyle/errorClass - Styling error messages with inner style / CSS class (only FacesMessage.SEVERITY_ERROR will have this style)
<h:form>
 <h:outputLabel value="Name:" for="nameId"/>
 <h:inputText id="nameId" value="#{playerBean.name}" label="name"/>                
 <h:outputLabel value="Age:" for="ageId"/>
 <h:inputText id="ageId" value="#{playerBean.age}" label="age">              
  <f:validateLongRange for="ageId" minimum="18" maximum="45" />
 </h:inputText>            
 <h:commandButton value="Send" action="#{playerBean.error()}"/>
 <!-- errorStyle -->
 <h:messages errorStyle="color:red;font-size:20px;"/>      
 <!-- errorClass -->
 <h:messages errorClass="errorcss"/>
</h:form>
In the first case, the inserted value, 10, is not valid, so the applications "stops" in the Process Validations phase, and a message of type error is returned. This message is styled via errorStyle/errorClass. When a valid value is provided, the application flow reaches a dummy PlayerBean method, named error(). This method simply put in messages queue a global message of type error, which will be styled via warnStyle/warnClass:

public void error() {
 FacesContext context = FacesContext.getCurrentInstance();
 // add an error message
 context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "This is an error message !", "This message is just a dummy error message to see how it works !"));
}

The fatalStyle/fatalClass - Styling fatal error messages with inner style / CSS class (only FacesMessage.SEVERITY_FATAL will have this style)
<h:form>
 <h:outputLabel value="Name:" for="nameId"/>
 <h:inputText id="nameId" value="#{playerBean.name}" label="name"/>                
 <h:outputLabel value="Age:" for="ageId"/>
 <h:inputText id="ageId" value="#{playerBean.age}" label="age">              
  <f:validateLongRange for="ageId" minimum="18" maximum="45" />
 </h:inputText>                   
 <h:commandButton value="Send" action="#{playerBean.fatal()}"/>
 <!-- fatalStyle -->
 <h:messages fatalStyle="color:magenta;font-size:20px;"/>          
 <!-- fatalClass -->
 <h:messages fatalClass="fatalcss"/>
</h:form>
In the first case, the inserted value, 10, is not valid, so the applications "stops" in the Process Validations phase, and a message of type error is returned. This message doesn't benefit of a custom CSS, so is  displayed via JSF default style. When a valid value is provided, the application flow reaches a dummy PlayerBean method, named fatal(). This method simply put in messages queue a global message of type fatal, which will be styled via fatalStyle/fatalClass:

public void fatal() {
 FacesContext context = FacesContext.getCurrentInstance();
 // add an error message
 context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, "This is an fatal message !", "This message is just a dummy fatal message to see how it works !"));
}

The xxxStyle/xxxClass - Styling info/warn/error/fatal messages with inner style / CSS class
<h:form>
 <h:outputLabel value="Name:" for="nameId"/>
 <h:inputText id="nameId" value="#{playerBean.name}" label="name"/>            
 <h:outputLabel value="Age:" for="ageId"/>
 <h:inputText id="ageId" value="#{playerBean.age}" label="age"/>              
 <h:commandButton value="Send" action="#{playerBean.allMessage()}"/>
 <!-- xxxStyle -->
  <h:messages infoStyle="color:green;font-size:20px;" warnStyle="color:orange;font-size:20px;" errorStyle="color:red;font-size:20px;" fatalStyle="color:magenta;font-size:20px;"/>
 <!-- xxxClass -->
 <h:messages infoClass="infocss" warnClass="warncss" errorClass="errorcss" fatalClass="fatalcss"/> 
</h:form>
In this case, messages will be styled depending on their type. For testing purposes, we have used a method that generates four global message (an info, a warning, an error and a fatal message). Notice how each one gets the right style. This method is listed below:

public void allMessage() {
 FacesContext context = FacesContext.getCurrentInstance();
 context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "This is an info message !", "This message is just a dummy info message to see how it works !"));
 context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "This is an warning message !", "This message is just a dummy warning message to see how it works !"));
 context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "This is an error message !", "This message is just a dummy error message to see how it works !"));
 context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, "This is an fatal message !", "This message is just a dummy fatal message to see how it works !"));
}

Show messages summary, don't show detail - this is default
<h:form>
 <h:outputLabel value="Name:" for="nameId"/>
 <h:inputText id="nameId" value="#{playerBean.name}" label="name">
  <f:validator validatorId="myValidator"/>
 </h:inputText>
 <h:outputLabel value="Age:" for="ageId"/>
 <h:inputText id="ageId" value="#{playerBean.age}" label="age">
  <f:validateLongRange for="ageId" minimum="18" maximum="45" />
 </h:inputText>      
 <h:commandButton value="Send"/>        
 <h:messages showSummary="true" showDetail="false" errorClass="errorcss"/>                     
</h:form>

Show message detail, don't show summary
<h:form>
 <h:outputLabel value="Name:" for="nameId"/>
 <h:inputText id="nameId" value="#{playerBean.name}" label="name">
  <f:validator validatorId="myValidator"/>
 </h:inputText>
 <h:outputLabel value="Age:" for="ageId"/>
 <h:inputText id="ageId" value="#{playerBean.age}" label="age">
  <f:validateLongRange for="ageId" minimum="18" maximum="45" />
 </h:inputText>      
 <h:commandButton value="Send"/>        
 <h:messages showSummary="false" showDetail="true" errorClass="errorcss"/>                     
</h:form>

Show messages summary and detail
<h:form>
 <h:outputLabel value="Name:" for="nameId"/>
 <h:inputText id="nameId" value="#{playerBean.name}" label="name">
  <f:validator validatorId="myValidator"/>
 </h:inputText>
 <h:outputLabel value="Age:" for="ageId"/>
 <h:inputText id="ageId" value="#{playerBean.age}" label="age">
  <f:validateLongRange for="ageId" minimum="18" maximum="45" />
 </h:inputText>      
 <h:commandButton value="Send"/>        
 <h:messages showSummary="true" showDetail="true" errorClass="errorcss"/>                     
</h:form>

Show only global messages (default all messages are displayed)
<h:form id="form1Id">
 <h:outputLabel value="Name:" for="nameId"/>
 <h:inputText id="nameId" value="#{playerBean.name}" label="name"/>               
 <h:outputLabel value="Age:" for="ageId"/>
 <h:inputText id="ageId" value="#{playerBean.age}" label="age"/>                      
 <h:commandButton value="Send" action="#{playerBean.oneGlobalOneNot()}"/>        
  <h:messages globalOnly="true" infoClass="infocss" warnClass="warncss" errorClass="errorcss" fatalClass="fatalcss"/>                     
</h:form>
In this case, only global messages will be displayed (messages that are not associated with a clientId). For testing, the above code invoke a simple method, oneGlobalOneNot() which  generates a global message and a not-global message (associate it with clientId, formId:ageId):

public void oneGlobalOneNot() {
 FacesContext context = FacesContext.getCurrentInstance();
 context.addMessage("formId:ageId", new FacesMessage(FacesMessage.SEVERITY_INFO, "This is an info message (not global)!", "This message is just a dummy info message to see how it works (not global)!"));
 context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "This is an info message (global)!", "This message is just a dummy info message to see how it works (global)!"));
}

Show only messages for a certain component (not global messages)
<h:form id="form2Id">
 <h:outputLabel value="Name:" for="nameId"/>
 <h:inputText id="nameId" value="#{playerBean.name}" label="name"/>               
 <h:outputLabel value="Age:" for="ageId"/>
 <h:inputText id="ageId" value="#{playerBean.age}" label="age"/>                      
 <h:commandButton value="Send" action="#{playerBean.moreGlobalAndNotGlobal()}"/>        
 <h:messages for="form2Id:ageId" infoClass="infocss" warnClass="warncss" errorClass="errorcss" fatalClass="fatalcss"/>                     
</h:form>
Keep in mind that <h:messages> also support the for attribute, but this attribute is mutually exclusive with globalOnly and take precedence if used - <h:messages for="componentId"> can be used to show all messages attached to componentId. For testing purposes, the above code invokes a method named, moreGlobalAndNotGlobal() which generated a set of global and not-global messages, but only the not-global messages (those associated to clientIdform2Id:ageId) will be displayed thanks to the for attribute.

Complete source code on GitHub.
See also Mkyong.com.
More resources on Constantin Alin, ZEEF page.
Messages in JSF Extension on JSF ShowCase ZEEF page.

Niciun comentariu :

Trimiteți un comentariu

JSF BOOKS COLLECTION

Postări populare

OmniFaces/JSF Fans

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors