In my earlier posts, I explained how to get started with JSF2 and work with JSF View pages by adding HTML components such as labels, text fields etc. Today we will look into one of the most important component of any web framework i.e Resource Bundles and Custom Messages.
Resource Bundle
The phenomenon of storing the UI labels, date, status messages and other UI textual elements in a separate properties file instead of hardcoding these in a page is called resource bundling. It is the most convenient way of handling these kinds of resources as one can change these texts in the properties file instead of tinkering the xhtml file at a later stage.
Creating and invoking resource bundle involves the following steps
Create a properties file called resourcebundle.properties
. You can check the property file location from the project structure image given below or by downloading the project.
resourcebundle.properties"
1 2 3 4 5 6 7 8 |
name= Car name: Id = Car Id: color = Color: model = Model: regno = Registration Number: clear = Reset Details |
Create the JSF page by using the resource bundle to display the labels and error messages.
resourcebundle.xhtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml" xmlns:h="https://java.sun.com/jsf/html" xmlns:c="https://java.sun.com/jsf/core"> <h:head> <title>Resource Bundle</title> </h:head> <h:body> <h3>Resource Bundle Example</h3> <c:view> <c:loadBundle basename="com.journaldev.messages.resourcebundle" var="res" /> <h:form> <h:panelGrid columns="3"> <h:outputLabel value="#{res.name}"></h:outputLabel> <h:inputText value="#{car.cname}" id="cname"></h:inputText> <br /> <br /> <h:outputLabel value="#{res.Id}"></h:outputLabel> <h:inputText value="#{car.id}" id="Id"></h:inputText> <br /> <br /> <h:outputLabel value="#{res.color}"></h:outputLabel> <h:inputText value="#{car.color}" id="color"></h:inputText> <br /> <br /> <h:outputLabel value="#{res.model}"></h:outputLabel> <h:inputText value="#{car.model}" id="model"></h:inputText> <br /> <br /> <h:outputLabel value="#{res.regno}"></h:outputLabel> <h:inputText value="#{car.regno}" id="regno"></h:inputText> <br /> <br /> <h:commandButton action="#{car.clearAll()}" value="#{res.clear}"></h:commandButton> </h:panelGrid> </h:form> </c:view> </h:body> </html> |
To render the individual xhtml files, right click on the jsf/xhtml file in NetBeans IDE and click on Run. Or, run the project and point the browser to the desired xhtml page. Notice that I am loading the resource bundle file, it’s similar to importing a java class.
Now create a managed bean named Car.java
as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
package com.journaldev.jsf.beans; import java.io.Serializable; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; @ManagedBean(name="car") @SessionScoped public class Car implements Serializable { private static final long serialVersionUID = 1409682048108139241L; private String cname; private String color; private String Id; private String model; private String regno; public Car() { } public Car(String cname, String color, String Id, String model, String regno) { this.cname = cname; this.color = color; this.Id = Id; this.model = model; this.regno = regno; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getCname() { System.out.println("car name is" + cname); return cname; } public void setCname(String cname) { this.cname = cname; } public String getRegno() { return regno; } public void setRegno(String regno) { this.regno = regno; } public String getModel() { return model; } public void setModel(String model) { this.model = model; } public String getId() { return Id; } public void setId(String Id) { this.Id = Id; } public void clearAll() { this.Id = ""; this.cname = ""; this.color = ""; this.regno = ""; this.model = ""; } } |
Once done with these changes run the project to render the JSF page and it should look as shown below.
As you can notice the labels are picked up from the properties file. Now if we want to change say ‘Color’ label to more clear ‘Car Color’, we just have to edit the resourcebundle.properties
file which is easier than to change it in the xhtml file. This has clear advantages when the code is in production and we don’t want to meddle with the xhtml stuff which is already working very well.
Custom Messages
Custom messages in JSF allows users to define their own error messages conveniently. By default JSF provides some standard error messages depending on the context like say field type or field length validations. JSF field validations are an easier way of checking some common UI data correctness scenarios instead of writing JavaScript code or even JSP/java validations. We will discuss about the JSF default error messages elsewhere. Custom messages override these cryptic default messages with a more clear user defined one. Let’s understand how to configure our own error messages in the below example.
Create a JSF page named customerror.html
as
customerror.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml" xmlns:h="https://java.sun.com/jsf/html" xmlns:c="https://java.sun.com/jsf/core" > <h:body> <h3>Custom messages</h3> <h:form> <h:panelGrid columns="3"> <h:outputLabel value="Car Id"></h:outputLabel> <h:inputText value="#{car.id}" id="Id" required="true" requiredMessage="Car Id is mandatory"></h:inputText> <br /><br /> <h:outputLabel value="Car Name"></h:outputLabel> <h:inputText value="#{car.cname}" id="cname"> <c:validateLength minimum="5" maximum="10" for="cname" id="cname"/> </h:inputText> <h:message for="cname" style="color: red"></h:message> <h:commandButton action="#{car.id}" value="Submit"></h:commandButton> <br /><br /> </h:panelGrid> </h:form> </h:body> </html> |
The validateLength
method is used for checking the length of characters by accepting minimum and maximum where we can specify the number of characters and then the h:message
tag is used to print the error message. Also the required="true"
indicates that the field is mandatory and the requiredMessage is used to print the message as specified by the user.
JSF framework has standard keys for length check minimum and maximum error message, we can override them by adding below properties to our resource bundle file.
1 2 3 4 |
javax.faces.validator.LengthValidator.MINIMUM=Please enter a minimum of 5 characters javax.faces.validator.LengthValidator.MAXIMUM=Maximum length is exceeded. Please enter a string below 10 characters |
Now if you are wondering how JSF will know where to look for our custom defined error messages, it’s configured in faces-config.xhtml file as shown below.
faces-config.xhtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="UTF-8"?> <faces-config xmlns="https://java.sun.com/xml/ns/javaee" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" version="2.0"> <application> <message-bundle> com.journaldev.messages.resourcebundle </message-bundle> </application> </faces-config> |
Once done with these changes run the application which displays the following output.
As we can see, there is no need of extra code to throw our own custom error messages since we are using built in JSF validations and the properties file to pick up the text.
The project structure is as shown below:
This post is all about handling JSF Resources and Custom Messages. We will be looking into JSF Error Messages in the coming tutorial. In the mean time, you can download the project from below link and play around with it to learn more.