Seam Data Validation

0
85
8 min read

Data validation

In order to perform consistent data validation, we would ideally want to perform all data validation within our data model. We want to perform data validation in our data model so that we can then keep all of the validation code in one place, which should then make it easier to keep it up-to-date if we ever change our minds about allowable data values.

Seam makes extensive use of the Hibernate validation tools to perform validation of our domain model. The Hibernate validation tools grew from the Hibernate project (http://www.hibernate.org) to allow the validation of entities before they are persisted to the database. To use the Hibernate validation tools in an application, we need to add hibernate-validator.jar into the application’s class path, after which we can use annotations to define the validation that we want to use for our data model. Let’s look at a few validations that we can add to our sample Seam Calculator application.

In order to implement data validation with Seam, we need to apply annotations either to the member variables in a class or to the getter of the member variables. It’s good practice to always apply these annotations to the same place in a class. Hence, throughout this article, we will always apply our annotation to the getter methods within classes.

In our sample application, we are allowing numeric values to be entered via edit boxes on a JSF form. To perform data validation against these inputs, there are a few annotations that can help us.

Annotation

Description

@Min

The @Min annotation allows a minimum value for a numeric variable to be specified. An error message to be displayed if the variable’s value is less than the specified minimum can also be specified. The message parameter is optional. If it is not specified, then a sensible error message will be generated (similar to must be greater than or equal to …).

@Min(value=0, message=”…”)

@Max

The @Max annotation allows a maximum value for a numeric variable to be specified. An error message to be displayed if the variable’s value is greater than the specified maximum can also be specified. The message parameter is optional. If it is not specified, then a sensible error message will be generated (similar to must be less than or equal to …).

@Max(Value=100, message=”…”)

@Range

The @Range annotation allows a numeric range-that is, both minimum and maximum values-to be specified for a variable. An error message to be displayed if the variable’s value is outside the specified range can also be specified. The message parameter is optional. If it is not specified, then a sensible error message will be generated (similar to must be between … and …).

@Range(min=0, max=10, message=”…”)

At this point, you may be wondering why we need to have an @Range validator, when by combining the @Min and @Max validators, we can get a similar effect. If you want a different error message to be displayed when a variable is set above its maximum value as compared to the error message that is displayed when it is set below its minimum value, then the @Min and @Max annotations should be used. If you are happy with the same error message being displayed when a variable is set outside its minimum or maximum values, then the @Range validator should be used. Effectively, the @Min and @Max validators are providing a finer level of error message provision than the @Range validator.

The following code sample shows how these annotations can be applied to a sample application, to add basic data validation to our user inputs.

package com.davidsalter.seamcalculator;

import java.io.Serializable;

import org.jboss.seam.annotations.Name;
import org.jboss.seam.faces.FacesMessages;
import org.hibernate.validator.Max;
import org.hibernate.validator.Min;
import org.hibernate.validator.Range;

@Name("calculator")
public class Calculator implements Serializable {

private double value1;
private double value2;
private double answer;
@Min(value=0)
@Max(value=100)
public double getValue1() {
return value1;
}
public void setValue1(double value1) {
this.value1 = value1;
}
@Range(min=0, max=100)
public double getValue2() {
return value2;
}
public void setValue2(double value2) {
this.value2 = value2;
}
public double getAnswer() {
return answer;
}
...
}

Displaying errors to the user

In the previous section, we saw how to add data validation to our source code to stop invalid data from being entered into our domain model. Now that we have reached a level of data validation, we need to provide feedback to the user to inform them of any invalid data that they have entered.

JSF applications have the concept of messages that can be displayed associated with different components. For example, if we have a form asking for a date of birth to be entered, we could display a message next to the entry edit box if an invalid date were entered. JSF maintains a collection of these error messages, and the simplest way of providing feedback to the user is to display a list of all of the error messages that were generated as a part of the previous operation.

In order to obtain error messages within the JSF page, we need to tell JSF which components we want to be validated against the domain model. This is achieved by using the <s:validate/> or <s:validateAll/> tags. These are Seam-specific tags and are not a part of the standard JSF runtime. In order to use these tags, we need to add the following taglib reference to the top of the JSF page.

<%@ taglib uri="http://jboss.com/products/seam/taglib" prefix="s" %>

In order to use this tag library, we need to add a few additional JAR files into the WEB-INF/lib directory of our web application, namely:

  • jboss-el.jar
  • jboss-seam-ui.jar
  • jsf-api.jar
  • jsf-impl.jar

This tag library allows us to validate all of the components (<s:validateAll/>) within a block of JSF code, or individual components (<s:validate/>) within a JSF page.

To validate all components within a particular scope, wrap them all with the <s:validateAll/> tag as shown here:

<h:form>
<s:validateAll>
<h:inputText value="..." />
<h:inputText value="..." />
</s:validateAll>
</h:form>

To validate individual components, embed the <s:validate/> tag within the component, as shown in the following code fragment.

<h:form>
<h:inputText value="..." >
<s:validate/>
</h:inputText>

<h:inputText value="..." >
<s:validate/>
</h:inputText>
</h:form>

After specifying that we wish validation to occur against a specified set of controls, we can display error messages to the user. JSF maintains a collection of errors on a page, which can be displayed in its entirety to a user via the <h:messages/> tag.

Seam 2.x Web Development

It can sometimes be useful to show a list of all of the errors on a page, but it isn’t very useful to the user as it is impossible for them to say which error relates to which control on the form. Seam provides some additional support at this point to allow us to specify the formatting of a control to indicate error or warning messages to users.

Seam provides three different JSF facets (<f:facet/>) to allow HTML to be specified both before and after the offending input, along with a CSS style for the HTML. Within these facets, the <s:message/> tag can be used to output the message itself. This tag could be applied either before or after the input box, as per requirements.

Facet

Description

beforeInvalidField

This facet allows HTML to be displayed before the input that is in error. This HTML could contain either text or images to notify the user that an error has occurred.

<f:facet name=”beforeInvalidField”>

</f:facet>

afterInvalidField

This facet allows HTML to be displayed after the input that is in error. This HTML could contain either text or images to notify the user that an error has occurred.

<f:facet name=”afterInvalidField”>

</f:facet>

aroundInvalidField

This facet allows the CSS style of the text surrounding the input that is in error to be specified.

<f:facet name=”aroundInvalidField”>

</f:facet>

In order to specify these facets for a particular field, the <s:decorate/>  tag must be specified outside the facet scope.

<s:decorate>
<f:facet name="aroundInvalidField">
<s:span styleClass="invalidInput"/>
</f:facet>
<f:facet name="beforeInvalidField">
<f:verbatim>**</f:verbatim>
</f:facet>
<f:facet name="afterInvalidField">
<s:message/>
</f:facet>
<h:inputText value="#{calculator.value1}" required="true" >
<s:validate/>
</h:inputText>
</s:decorate>

In the preceding code snippet, we can see that a CSS style called invalidInput is being applied to any error or warning information that is to be displayed regarding the <inputText/> field. An erroneous input field is being adorned with a double asterisk (**) preceding the edit box, and the error message specific to the inputText field after is displayed in the edit box.

LEAVE A REPLY

Please enter your comment!
Please enter your name here