JSF Pass Parameters in Localized Error Messages
When an error occurs in the backend and you need to inform the user what happened, you can display an appropriate error message. JSF provides an easy utility to display these messages. You can either show global messages using the <h:messages>
or use property specific messages using <h:message>
. This example shows you how to add parameterized and localized messages using the FacesMessage
. We also enhance the messages with the bootstrap alert classes.
Maven Dependencies
We are working with the following dependencies. Note that we include the org.webjars.bootstrap
dependency. This library provides javascript and special bootstrap css files for jsf.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.memorynotfound.jsf.messages</groupId>
<artifactId>parameterize-messages</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>JSF - ${project.artifactId}</name>
<url>https://memorynotfound.com</url>
<packaging>war</packaging>
<properties>
<jsf.version>2.2.12</jsf.version>
</properties>
<dependencies>
<!-- JSF api and impl -->
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>${jsf.version}</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>${jsf.version}</version>
</dependency>
<!-- servlet provided by tomcat -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- bootstrap -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.6</version>
</dependency>
</dependencies>
</project>
Adding Messages via Managed Bean
We create a special utility class named MessageUtils
that has a method addErrorMessage
which takes an error key of the message we want to display and parameters that we want to pass to format the message. We set the Locale
using another utility class named JSFUtils
. These utility classes are explained later in this tutorial. Working with these utility classes makes it really easy to understand what’s happening in the code.
package com.memorynotfound.jsf;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import java.util.Locale;
@ManagedBean
@RequestScoped
public class CourseBean {
public String addErrorMessage(){
// displaying english message
JSFUtils.setLocale(new Locale("en"));
MessageUtils.addErrorMessage("error.retrieve.documents", new Object[]{"star-wars"});
// displaying french message
JSFUtils.setLocale(new Locale("fr"));
MessageUtils.addErrorMessage("error.retrieve.documents", new Object[]{"star-wars"});
return null;
}
}
Message Utility
The real logic of adding an error message is encapsulated in this MessageUtility
class. We create a FacesMessage
which we pass a FacesMessage.SEVERITY_ERROR
type which flags this message as an error message. Note that we add this message to the FacesContext
using the addMessage
method and we don’t specify a client id which makes this error message a global error message.
Next, we get the ResourceBundle
and call getString
to retrieve the key from the message bundle. We then add the specified parameters with the format
method of the MessageFormat
class.
package com.memorynotfound.jsf;
import javax.faces.application.FacesMessage;
import java.text.MessageFormat;
public class MessageUtils {
public static void addErrorMessage(final String message) {
FacesMessage fm = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message);
JSFUtils.getFacesContext().addMessage(null, fm);
}
public static void addErrorMessage(String key, final Object[] parameters) {
String message = JSFUtils.getResourceBundle("msg").getString(key);
String formattedMessage = MessageFormat.format(message, parameters);
addErrorMessage(formattedMessage);
}
}
JSF Utility
This JSFUtility
class is used for convenience and maintainable code.
package com.memorynotfound.jsf;
import javax.faces.application.Application;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import java.util.Locale;
import java.util.ResourceBundle;
public class JSFUtils {
public static FacesContext getFacesContext(){
return FacesContext.getCurrentInstance();
}
public static Application getApplication(){
return getFacesContext().getApplication();
}
public static UIViewRoot getViewRoot(){
return getFacesContext().getViewRoot();
}
public static void setLocale(Locale locale){
getViewRoot().setLocale(locale);
}
public static ResourceBundle getResourceBundle(String key){
return getApplication().getResourceBundle(getFacesContext(), key);
}
}
Messages
This is the messages_en.properties file located at src/main/resources/com/memorynotfound/ folder. This file holds all the english messages for our tutorial application.
error.retrieve.documents = Document with category {0} not found.
This is the messages_fr.properties file located at src/main/resources/com/memorynotfound/ folder. This file holds all the french messages for our tutorial application.
error.retrieve.documents = Impossible de charger des documents de la cat\u00E9gorie {0}.
Register messages in faces-config.xml
We need to register the message bundle in the faces-config.xml using the resource-bundle element, which is a child of the application element. We add a base-name, which is the package name relative to the classpath where we can find the messages.properties file. We also add a var, which is used earlier to get the resource bundle.
<faces-config 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/web-facesconfig_2_2.xsd" version="2.2">
<application>
<resource-bundle>
<base-name>com.memorynotfound.messages</base-name>
<var>msg</var>
</resource-bundle>
</application>
</faces-config>
Displaying the messages
We add the bootstrap css library specially for JSF using the <h:outputStylesheet>
. This style is used for enhancing our messages with the bootstrap alert classes. Next, we register the <h:messages>
element, which is a placeholder for our error messages. We define some classes for which css class to be used for which error type.
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<h:outputStylesheet library="webjars" name="/bootstrap/3.3.6/css/bootstrap.min-jsf.css"/>
</h:head>
<h:body>
<h2>JSF messages</h2>
<style>
ul {
list-style: none;
}
</style>
<h:form>
<h:messages infoClass="alert alert-success"
warnClass="alert alert-info"
errorClass="alert alert-warning"
fatalClass="alert alert-danger" />
<h:commandButton action="#{courseBean.addErrorMessage}" value="Show messages"/>
</h:form>
</h:body>
</html>
Demo
URL: http://localhost:8081/jsf-messages/index.xhtml
When the button ‘Show messages’ is clicked, the error messages are displayed.