Implementing Client Side Validation for Custom Validators in ADF Faces

1

The SUN Reference Implementation of Java Server Faces has a limited number of Validators. The framework has plenty support for creation and integration of custom validators. It does not however come with out of the box support for client side validation. Validation only occurs on the middle tier after a form has been submitted – either in full or partially through an AJAX style operation – from the client to the server.

ADF Faces has extended this approach by providing JavaScript based Client Side validation that occurs inside the browser when the Form is submitted, and therefore before the request is sent to the server. When validation fails, no request is sent at all and the user is notified of this failure to submit as a result of validation errors. Again, the set of out of the box validators in ADF Faces is fairly liimited, but we are free to extend that set with our own validators. It turns out to be quite easy to implement client side validation in our own custom validators as well, utilizing the infrastructure in ADF Faces.

In this article, I will demonstrate how my custom GreaterThan validator is client-side-enabled within the context of ADF Faces.....

Implementing and activating client side validation with JSF validators requires three things:

  • The Validator class should implement the oracle.adf.view.faces.validator.ClientValidator interface
  • The form that contains the UI components to which the Validator is applied must be submitted by calling the submitForm() method provided by ADF Faces or using an af:commandButton. Using the normal submit() on the form will by pass client side validation.

Note: we do not need to change anything in the Tag class, the Tag Library description, the faces-config entry for the validator or the usage of the validator tag in our pages. We only have to change the Validator class itself and perhaps the way we submit the pages. (note: most ADF Faces applications will already submit the data form in the correct way). 

The ClientValidator interface has two methods we have to implement:

  1.     public String getClientScript(FacesContext facesContext,
                                      UIComponent uIComponent)
  2.     public String getClientValidation(FacesContext facesContext,
                                          UIComponent uIComponent)

The first method – getClientScript – return a JavaScript fragment that implements the Validator Interface. That essentially means this piece of JavaScript defines an object that has a function called validate that acceps a single input parameter:

function(value){} 

Whatever else this object contains, it must have this validate method.

An example implementation of getClientScript, for the GreaterThan validator, could look like this:

public String getClientScript(FacesContext facesContext, <br />                              UIComponent uIComponent) {<br />   return &quot;function GreaterThanValidator(p1)\n&quot; + <br />    &quot;{  this.greaterThanItem=p1; \n&quot; + <br />    &quot;}\n&quot; + <br />    &quot;GreaterThanValidator.prototype.validate = function(value){&quot; +<br />    &quot;greaterThanValue = document.getElementById(this.greaterThanItem.replace('.',':')).value;&quot;+<br />    &quot; if (!(value&gt; greaterThanValue)){ &quot; +<br />    &quot;    return new ValidatorException('Value in {0} must be greater than '+greaterThanValue&quot; +<br />    &quot;         +' (current value = {1})');}&quot;+<br />    &quot;};&quot;;<br />}   <br />

Note that this method returns a JavaScript fragment that creates a new Object called GreaterThanValidator. This object has a function called validate (the one required by the design contract) that accepts a single input parameter: the value of the item being validated. In addition, this object has a constructor that takes a single argument – the id of the element with which the current element’s value should be compared by the validator. The validate function locates the element whose ID matches the greaterThanItem property, retrieves its value and compares with the value passed into the function by the ADF Faces Client Side framework. If that value is not greater than the greaterThanValue, then a ValidatorException with an appropriate message is thrown. Note that a proper implementation would leverage the client side message localization framework in ADF Faces.

The second method the ClientValidator requires us to implement is the getClientValidation() method. This method should return the JavaScript code that is used to instantiate an instance of the validator. That means it should call the new operator for the Validator object defined through the code generated in getClientScript(), and pass the appropriate parameters to the constructor function. The example of the GreaterThanValidator we are discussing here takes a single parameter – the id of the element we need to compare the value-to-validate with. Our implementation of getClientValidation() is like this:

    public String getClientValidation(FacesContext facesContext, <br />                                      UIComponent uIComponent) {<br />        return &quot;new GreaterThanValidator('&quot;+getGreaterThanId()+&quot;')&quot;;<br />    }<br />&nbsp;

We are set once we have specified that our Validator class implements ClientValidator:

public class GreaterThanValidator implements Validator<br />                                            , oracle.adf.view.faces.validator.ClientValidator {<br />&nbsp;

At this point, we can redeploy the validator if we are using it in another application, or just test-drive in the same ViewController project:

 

When I run the application, enter the values as shown and press the submit button, the client side validation kicks in

 

Note: all configuration is the same as in the previous article Custom JSF Validator GreaterThan.

Turning off ADF Faces client side validation 

During development, it can be useful to quicky (and temporarily) switch off client side validation in our ADF Faces application. There is any easy way of doing this: add a client-validation-disabled element to the adf-faces-config.xml file in our WEB-INF library.

&lt;client-validation-disabled&gt;true&lt;/client-validation-disabled&gt;&nbsp;

Resources

My previous article on implementing the (server side) Custom JSF Validator GreaterThan

Oracle JDeveloper 10.1.3 documentation on implementing Validation in ADF Faces 

ADF Faces Client Side Converters and Validators (OTN article) 

A
DF Faces Client Validator
(JavaDoc)

ADF Faces: How suppress item validation on partial submit (Frank Nimphius blog)

Download the JDeveloper 10.1.3 ViewController Project (note: without the libraries adf-faces-impl.jar and jsf-impl.jar): jsfCustomClientValidationViewController.zip. 

 

 

Share.

About Author

Lucas Jellema, active in IT (and with Oracle) since 1994. Oracle ACE Director for Fusion Middleware. Consultant, trainer and instructor on diverse areas including Oracle Database (SQL & PLSQL), Service Oriented Architecture, BPM, ADF, Java in various shapes and forms and many other things. Author of the Oracle Press book: Oracle SOA Suite 11g Handbook. Frequent presenter on conferences such as JavaOne, Oracle OpenWorld, ODTUG Kaleidoscope, Devoxx and OBUG. Presenter for Oracle University Celebrity specials.

1 Comment

  1. When I run DemoValidateGreaterThan.jspx I am getting the following errors.
    java.lang.ClassCastException: javax.faces.component.html.HtmlForm
    at javax.faces.webapp.ValidatorTag.doStartTag(ValidatorTag.java:130)
    at _DemoValidateGreaterThan_jspx._jspService(_DemoValidateGreaterThan_jspx.java:71) [/DemoValidateGreaterThan.jspx]

    I am not sure why. I downloaded the code from “jsfCustomClientValidationViewController.zip”.

    Please suugest what might cause this issue.

    Thank you