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>http://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

jsf pass parameters with localized error messages

When the button ‘Show messages’ is clicked, the error messages are displayed.

jsf pass parameters with localized error messages

References

Download

You may also like...