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 clientId, form2Id: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