Menu

Multi-component validation in JSF

Goal

To validate more than one field at once in JSF 2+

Description

A typical use case in the projects I usually work on are validating that one start date is prior to an end date in a given form. To do that, before JSF 2, I used to hack a bit: adding the validation to a hidden field that was put in the page, after the two date fields and look for the appropriate fields during the hidden field’s processing, or to add that logic inside the method that would be invoked in the invoke application lifecycle of JSF.

With JSF 2 and system events, no hacks are necessary anymore. This recipe tells you how to implement that correctly.

How to

The recipe consists on the following 3 basic steps:

System event – define a “postValidate” system event inside a panelGroup (<h:panelGroup id=”date” layout=”block”>) that groups together the start and end date fields. Also in the f:event tag, define the method that will be invoked when that event is triggered (listener=”#{refundRequestHelper.validatePeriod}”) – shown in the first code snippet

Error message – Attach a message to the wrapping panelGroup (p:message for=”date” />) – shown in the first code snippet

Validator method – implement the method that checks the start and date field components and checks if their data is valid – shown in the second code snippet

The validator method shown next is for a project that is using JSF inside a Liferay portal implementation. Therefore, you will see usage of a LiferayFacesContext class, which means that, for straight JSF, i.e., outside a portlet bridge implementation, some minor adjustments would be required. For instance, liferayFacesContext.getMessage() gets a message property from the application’s resource bundle – the equivalent code without Liferay would be necessary here and, instead of liferayFacesContext.renderResponse(), we would need a FacesContext.getInstance().renderResponse() call. Finally, the call to JsfUtil.addErrorMessage() although simple, is shown in the following snippet too, to clarify things.

Explanations

In the postValidate event, all individual validations have already taken place. Still inside the validation JSF phase, we are allowed to get all component values and perform a multi-component validation as we did before. Then, by associating a message to a wrapping panel group, we are allowed to present an error message to that group of components, instead of showing it directly associated to one or both date components. I hope that, now, you will use and abuse of JSF 2 system events to implement multi-component validation 🙂