7 Validating and Converting Input

This chapter describes how to add conversion and validation capabilities to ADF Faces input components in your application. It also describes how to add custom JSF conversion and validation, how to handle and display any errors, including those not caused by validation.

This chapter includes the following sections:

7.1 About ADF Faces Converters and Validators

ADF Faces provides the ability to both convert and validate user provided data to help ensure data integrity. Use the Converters to convert the values on ADF forms to the type that the application accepts them and use Validators to impose validations on the input components.

ADF Faces input components support conversion capabilities. A web application can store data of many types, such as int, long, and date in the model layer. When viewed in a client browser, however, the user interface has to present the data in a manner that can be read or modified by the user. For example, a date field in a form might represent a java.util.Date object as a text string in the format mm/dd/yyyy. When a user edits a date field and submits the form, the string must be converted back to the type that is required by the application. Then the data is validated against any rules and conditions. Conversely, data stored as something other than a String type can be converted to a String for display and updating. Many components, such as af:inputDate, automatically provide a conversion capability.

ADF Faces input components also support validation capabilities. You can add one or more validator tags to the component. In addition, you can create your own custom validators to suit your business needs.

Validators and converters have a default hint message that is displayed to users when they click in the associated field. For converters, the hint usually tells the user the correct format to use for input values, based on the given pattern. For validators, the hint is used to convey what values are valid, based on the validation configured for the component. If conversion or validation fails, associated error messages are displayed to the user. These messages can be displayed in dialogs, or they can be displayed on the page itself next to the component whose conversion or validation failed. For information about displaying messages in an ADF Faces application, see Displaying Tips, Messages, and Help.

ADF Faces converters is a set of converters that extends the standard JSF converters. Since ADF Faces converters for input components operate on the client-side, errors in conversion can be caught at the client and thus avoid a round trip to the server. You can easily drag and drop ADF Faces converters into an input component.

ADF Faces validators also augment the standard JSF validators. ADF Faces validators can operate on both the client and server side. The client-side validators are in written JavaScript and validation errors caught on the client-side can be processed without a round-trip to the server.

7.1.1 ADF Faces Converters and Validators Use Cases and Examples

You use ADF Faces converters to convert input from an input component into the format the model expects. A typical use case is using an input component for entering numbers and including a converter to convert the string entered by the user into a number for the model to process. For example, an af:inputText component is used for a product Id attribute. You add the af:convertNumber converter to the af:inputText component to convert from String to Number. Another example is when you have an inputText component for an attribute for the cost of a product. You can use af:convertNumber to convert the input string into the proper currency format.

You add validators to input components in the same way to validate the input string. For instance, you can add a validator to the af:inputText component to check that the number of digits for the product Id are within the proper range. You add af:validateLength to af:inputText and set the minimum and maximum attributes to define the valid digit length.

7.1.2 Additional Functionality for ADF Faces Converters and Validators

You may find it helpful to understand other ADF Faces features before you implement your converters and validators. Following are links to other sections that may be useful.

7.2 Conversion, Validation, and the JSF Lifecycle

The conversion and validation capabilities supported by ADF Faces are basically performed at different phases of JSF lifecycle. You can learn about the phase at which conversion and validation takes place in JSF lifecycle and also learn about what happens when the conversion or validation fails.

When a form with data is submitted, the browser sends a request value to the server for each UI component whose editable value attribute is bound. Request values are decoded during the JSF Apply Request Values phase and the decoded value is saved locally on the component in the submittedValue attribute. If the value requires conversion (for example, if it is displayed as a String type but stored as a java.util.Date object), the data is converted to the correct type during the Process Validation phase on a per-UI-component basis.

If validation or conversion fails, the lifecycle proceeds to the Render Response phase and a corresponding error message is displayed on the page. If conversion and validation are successful, then the Update Model phase starts and the converted and validated values are used to update the model.

When a validation or conversion error occurs, the component whose validation or conversion failed places an associated error message in the queue and invalidates itself. The current page is then redisplayed with an error message. ADF Faces components provide a way of declaratively setting these messages.

For detailed information about how conversion and validation works in the JSF Lifecycle, see Using the JSF Lifecycle with ADF Faces .

7.3 Adding Conversion

ADF Faces converters are used to convert input from an input component into the format the model expects. You can use JDeveloper to automatically inserts a converter to the UI component or you can manually insert a converter into a UI component.

A web application can store data of many types (such as int, long, date) in the model layer. When viewed in a client browser, however, the user interface has to present the data in a manner that can be read or modified by the user. For example, a date field in a form might represent a java.util.Date object as a text string in the format mm/dd/yyyy. When a user edits a date field and submits the form, the string must be converted back to the type that is required by the application. You can set only one converter on a UI component.

When you create an af:inputText component and set an attribute that is of a type for which there is a converter, JDeveloper automatically adds that converter's tag as a child of the input component. This tag invokes the converter, which will convert the String type entered by the user back into the type expected by the object.

The JSF standard converters, which handle conversion between String types and simple data types, implement the javax.faces.convert.Converter interface. The supplied JSF standard converter classes are:

  • BigDecimalConverter

  • BigIntegerConverter

  • BooleanConverter

  • ByteConverter

  • CharacterConverter

  • DateTimeConverter

  • DoubleConverter

  • EnumConverter

  • FloatConverter

  • IntegerConverter

  • LongConverter

  • NumberConverter

  • ShortConverter

Table 7-1 shows the converters provided by ADF Faces.

Table 7-1 ADF Faces Converters

Converter Tag Name Description

ColorConverter

af:convertColor

Converts java.lang.String objects to java.awt.Color objects. You specify a set of color patterns as an attribute of the converter.

DateTimeConverter

af:convertDateTime

Converts java.lang.String objects to java.util.Date objects. You specify the pattern and style of the date as attributes of the converter.

NumberConverter

af:convertNumber

Converts java.lang.String objects to java.lang.Number objects. You specify the pattern and type of the number as attributes of the converter.

As with validators, the ADF Faces converters are also run on the client side.

If no converter is explicitly added, ADF Faces will attempt to create a converter based on the data type. Therefore, if the value is bound to any of the following types, you do not need to explicitly add a converter:

  • java.util.Date

  • java.util.Color

  • java.awt.Color

  • java.lang.Number

  • java.lang.Integer

  • java.lang.Long

  • java.lang.Short

  • java.lang.Byte

  • java.lang.Float

  • java.lang.Double

Unlike the converters listed in Table 7-1, the JavaScript-enabled converters are applied by type and used instead of the standard ones, overriding the class and id attributes. They do not have associated tags that can be nested in the component.

7.3.1 How to Add a Converter

You can also manually insert a converter into a UI component.

Before you begin:

It may be helpful to have an understanding of converters. See Adding Conversion.

You may also find it helpful to understand functionality that can be added using other ADF Faces features. See Additional Functionality for ADF Faces Converters and Validators.

To add ADF Faces converters that have tags:

  1. In the Structure window, right-click the component for which you would like to add a converter, choose Insert Inside component, then ADF Faces to insert an ADF Faces converter.

    You may also choose JSF > Converter to insert a JSF converter.

  2. Choose a converter tag (for example, Convert Date Time) and click OK.
  3. In the JSF page, select the component, and in the Properties window set values for the attributes, including any messages for conversion errors. For additional help, right-click any of the attributes and choose Help.

    You can set multiple patterns for some ADF Faces converters. See How to Specify Multiple Converter Patterns.

    ADF Faces lets you customize the detail portion of a conversion error message. By setting a value for a MessageDetailxyz attribute, where xyz is the conversion error type (for example, MessageDetailconvertDate), ADF Faces displays the custom message instead of a default message, if conversion fails. For information about creating messages, see Displaying Tips, Messages, and Help.

7.3.2 How to Specify Multiple Converter Patterns

Some converters support multiple patterns. Patterns specify the format of data accepted for conversion. Multiple patterns allow for more than one format. For example, a user could enter dates using a slash (/) or hyphen (-) as a separator. Note that not all converters support multiple patterns, although pattern matching is flexible and multiple patterns may not be needed.

The following example illustrates the use of a multiple pattern for the af:convertColor tag in which "255-255-000" and "FFFF00" are both acceptable values.

<af:inputColor colorData="#{adfFacesContext.colorPalette.default49}" id="sic3"
    label="Select a color" value="#{demoColor.colorValue4}" chooseId="chooseId">
  <af:convertColor patterns="rrr-ggg-bbb RRGGBB #RRGGBB"
    transparentAllowed="false"/>
</af:inputColor>

The following example illustrates the use of an af:convertDateTime tag in which "6/9/2007" and "2007/9/6" are both acceptable values.

  <af:inputDate id="mdf5" value="2004/09/06" label="attached converter">
    <af:convertDateTime pattern="yyyy/M/d" secondaryPattern="d/M/yyyy" />
  </af:inputDate>

The following example illustrates an af:convertNumber tag with the type attribute set to currency to accept "$78.57" and "$078.57" as values for conversion.

<af:inputText label="type=currency" value="#{validate.currency}" id="it1">
  <af:convertNumber type="currency"/>
</af:inputText>

7.3.3 How to Specify Negative Numbers for Converters

Negative numbers are used in financial applications and have attribute level support for client-side conversion using the af:convertNumber tag with the negativePrefix and negativeSuffix attributes to format negative values using specified prefix and suffix characters. For example, financial applications often format negative numbers using parentheses, where (99.00) represents the negative value for 99.00.

These attributes accomplish the same thing as specifying a converter pattern on the number converter, like #;(#), where the characters following the ";" in the pattern indicate the negative pattern and the open and close parenthesis in the expression represent the negative prefix and suffix respectively for negative numbers. However, converter patterns are not processed on the client side and require a server roundtrip to format the output.

You can eliminate the need for a server roundtrip to perform the conversion using the af:convertNumber tag. This client-side conversion will override any implied negative prefix/suffix using the converter pattern.

The following example illustrates an af:convertNumber tag with the negativePrefix and negativeSuffix attributes set to "(" and ")" respectively to accept values a user might enter such as "-99.00" and convert them to "(99.00)". With this setting, the conversion is handled on the client as soon as the user tabs out of the text input.

<af:inputText label="type=number"  id="it3">
  <af:convertNumber negativePrefix="(" negativeSuffix=")" type="number"/>
</af:inputText>

7.3.4 What Happens at Runtime: How Converters Work

When the user submits the page containing converters, the ADF Faces validate() method calls the converter's getAsObject() method to convert the String value to the required object type. When there is not an attached converter and if the component is bound to a bean property in the model, then ADF checks the model's data type and attempts to find the appropriate converter. If conversion fails, the component's valid attribute is set to false and JSF adds an error message to a queue that is maintained by FacesContext. If conversion is successful and there are validators attached to the component, the converted value is passed to the validators. If no validators are attached to the component, the converted value is stored as a local value that is later used to update the model.

7.3.5 What You May Need to Know About Number Converters

af:convertNumber supports either server-side or client-side conversion. The converter first attempts to perform number formatting, parsing and conversions on the fly within the browser thereby eliminating the need to perform a server roundtrip for formatting input numbers. However, client conversion is skipped in the following situations:

  • If the pattern attribute is specified. The converter will only run on the server.

  • If the input string contains more than 15 digits, which is the maximum precision supported by JavaScript number. The converter will only run on the server.

When af:convertNumber displays an input value with more decimal digits than specified by maxFractionDigits, by default it uses Java's HALF_EVEN method to round off the value.

If you want af:convertNumber to use a method other than HALF_EVEN (such as HALF_UP or FLOOR), follow these tips:

  • To configure a particular instance of af:convertNumber, set the roundingMode attribute to the desired value.

    For example:

    <af:convertNumber roundingMode="FLOOR" ... />
    
  • To configure all instances of af:convertNumber in your application, add the rounding-mode attribute in trinidad-config.xml and set it accordingly.

    For example:

    <trinidad-config xmlns="http://myfaces.apache.org/trinidad/config">
    ...
      <rounding-mode>FLOOR</rounding-mode>
    </trinidad-config>
    
    

The value of roundingMode must be supported by Java's RoundingMode. The value can be specified as a string in the .jspx or the config file, or as an EL expression bound to a method that returns RoundingMode type value.

Note:

Input value cannot be rounded at client-side unless the roundingMode is set to half-up. If roundingMode is not set to half-up, the input number is retained unaltered at client-side for a subsequent postback to perform the actual rounding on the server-side.

For more information about RoundingMode, see the Java API documentation.

7.3.6 What You May Need to Know About Date Time Converters

You should use a four-digit year pattern with a date converter to avoid ambiguity. If you are using a two-digit year format as the pattern, all four-digit year values appear as two digit year values. For example, if you are using a two-digit year format (such as MM-dd-yy) as the pattern, the date values 03-01-1910 and 03-01-2010 appear as 03-01-10 in the input field and could be interpreted incorrectly, though the server stores the correct year value.

Figure 7-1 shows the date values as they appear in the inputDate component, with an outputText component below that shows the original values stored on the server.

Figure 7-1 Date Converter With Two-Digit Year Format

This image is described in the surrounding text

If you are using a two-digit year format, all strings containing two-digit years will be resolved into a date within two-digit-year-start and two-digit-year-start + 100. For example, if two-digit-year-start value is 1912, the string 01/01/50 gets resolved to 01/01/1950. To enter dates outside this range, the end user should enter a date with the full (four-digit) year. For information about two-digit-year-start element and how to configure it, see What You May Need to Know About Elements in trinidad-config.xml.

Note:

While using a two-digit year format, two digit years will be placed in the range determined by two-digit-year-start even if the user is editing an existing value.

For example, assuming two-digit-year-start is set to 1950 (resolving year values to the range 1950 through 2050) and the inputDate component has value 03/01/1776 (displayed as 03/01/76). If the user modifies the value to 03/01/77, the new date would be 03/01/1977, not 03/01/1777 as may be expected.

If you want to use a 12-hour format (for example, MM/dd/yyyy - hh:mm) as the pattern with af:convertDateTime, you should also include the am/pm placeholder in the pattern (for example, MM/dd/yyyy - hh:mm a), otherwise the picker will not show am/pm options and the user will not be able to save the am/pm information. Figure 7-2 shows the inputDate component with and without am/pm placeholders in their patterns.

Figure 7-2 Using AM/PM Placeholder With af:convertDateTime

This image is described in the surrounding text

If you want to display timezone information by including the timezone placeholder (z) in the convertDateTime pattern (example, yyyy-MM-dd hh:mm:ss a z), note that the trinidad convertDateTime overrides the display of the timezone names. When used in conjunction with inputText or outputText, the converter displays the timezone in the format GMT + x. When used in conjunction with inputDate, the timezone is displayed from a selection of pre-configured display values, such as (UTC-08:00) Los Angeles - Pacific Time (PT).

7.4 Creating Custom ADF Faces Converters

You can create your own converters to meet your specific business needs. There are different procedures to create custom ADF Faces server-side converters or client-side converters.

Custom JSF converters run on the server-side using Java. ADF Faces Converters behave as JSF converters, but also support client-side conversion and validation using Javascript.

7.4.1 How to Create a Custom ADF Faces Converter

Creating a custom ADF Faces converter requires writing the business logic for the conversion and then registering the custom converter with the application. To use the custom ADF Faces converter, you use the f:converter tag and set the custom ADF Faces converter as a property of that tag, or you can use the converter attribute on the input component to bind to that converter.

To create a server-side converter, you must:

The ADF Framework supports client-side conversion and validation to minimize postbacks to the server. Client-side implementation is generally optional - if no client-side implementation is available, the framework will simply invoke the server-side converter during postback, just as in JSF.

Client-side implementation is required if the converter is used in conjunction with certain components which support client interaction without postback, such as inputNumberSlider, inputNumberSpinbox, and inputDate. To determine if a client converter is required for a component, refer to the component's tagdoc.

ADF Faces client-side converters work in the same way standard JSF conversion works on the server, except that JavaScript is used on the client. JavaScript converter objects can throw ConverterException exceptions and they support the getAsObject() and getAsString() methods.

To create a client-side converter, you must:

7.4.1.1 Implement Server-Side (Java) Conversion

ADF Faces converters are implemented on the server-side similarly to custom JSF converters.

  1. Create a Java class that implements the javax.faces.converter.Converter interface. The implementation must contain a public no-args constructor, a set of accessor methods for any attributes, and getAsObject and getAsString methods to implement the Converter interface.

    The getAsObject() method takes the FacesContext instance, the UI component, and the String value to be converted to a specified object, for example:

    public Object getAsObject(FacesContext context, 
                              UIComponent component, 
                              java.lang.String value){
        ..
    }
    

    The getAsString() method takes the FacesContext instance, the UI component, and the object to be converted to a String value, for example:

    public String getAsString(FacesContext context, 
                              UIComponent component, 
                              Object value){
        ..
    }
    

    For information about these classes, refer to the Javadoc or visit http://docs.oracle.com/javaee/index.html.

  2. Add the needed conversion logic. This logic should use javax.faces.convert.ConverterException to throw the appropriate exceptions and javax.faces.application.FacesMessage to generate the corresponding error messages.

    For information about the Converter interface and the FacesMessage error handlers, see the Javadoc for javax.faces.convert.ConverterException and javax.faces.application.FacesMessage, or visit http://docs.oracle.com/javaee/index.html.

If your application saves state on the client, the custom ADF Faces converter must implement the Serializable interface or the StateHolder interface, and the saveState(FacesContext) and restoreState(FacesContext, Object) methods of the StateHolder interface. See the Javadoc for the StateHolder interface of javax.faces.component package, or visit http://docs.oracle.com/javaee/index.html.

7.4.1.2 Register ADF Faces Converter in faces-config.xml

You should register the converter in the faces-config.xml file.

  1. Open the faces-config.xml file.

    The faces-config.xml file is located in the View_Project > WEB-INF node in the JDeveloper Applications window.

  2. In the editor window, click the Overview tab.
  3. Choose Converters and click Add to enter the converter information.

Click Help or press F1 for additional help in registering the converter.

7.4.1.3 Create a Client-Side Version of the Converter

Write a client JavaScript version of the converter, passing relevant information to a constructor, as shown in the following example.

function TrConverter()
{
}

/**
* Convert the specified model object value, into a String for display
* @param value Model object value to be converted 
* @param label label to identify the editableValueHolder to the user 
* @return the value as a string or undefined in case of no converter mechanism is
* available (see TrNumberConverter).
*/
TrConverter.prototype.getAsString = function(value, label){}

/**
* Convert the specified string value into a model data object 
* which can be passed to validators
* @param value String value to be converted 
* @param label label to identify the editableValueHolder to the user 
* @return the converted value or undefined in case of no converter mechanism is
* available (see TrNumberConverter).
*/

TrConverter.prototype.getAsObject = function(value, label){}

If errors are encountered, the client can throw a TrConverterException exception to show a TrFacesMessage error message.

The following example shows the signature for TrFacesMessage.

/**
 * Message similar to javax.faces.application.FacesMessage
 * @param summary - Localized summary message text
 * @param detail - Localized detail message text 
 * @param severity - An optional severity for this message.  Use constants
 * SEVERITY_INFO, SEVERITY_WARN, SEVERITY_ERROR, and
 *   SEVERITY_FATAL from the FacesMessage class.  Default is
 *   SEVERITY_INFO
 */
function TrFacesMessage(summary,detail,severity){
  ..
}

The following example shows the signature for TrFacesException.

/** 
* TrConverterException is an exception thrown by the getAsObject() or getAsString() 
* method of a Converter, to indicate that the requested conversion cannot be performed.
* @param facesMessage the TrFacesMessage associated with this exception
* @param summary Localized summary message text, used to create only if facesMessage is null
* @param detail Localized detail message text, used only if facesMessage is null
*/
function TrConverterException(facesMessage, summary, detail){
  ..
}

7.4.1.4 Modify the Server Converter to Enable Client Conversion

Change the server converter to implement ClientConverter interface, which indicates that the class supports client-side conversion. For information on the interface methods, see the ClientConverter javadoc on http://myfaces.apache.org.

The following example shows a custom javascript converter implementation for social security number.

function ssnGetAsString(value)
{
  return value.substring(0,3) + '-' + 
   value.substring(3,5) + '-' + 
   value.substring(5);
}
 
function ssnGetAsObject(value)
{
  if (!value)
    return (void 0);
    
  var len=value.length;
  var messageKey = SSNConverter.NOT;
  if (len < 9 )
    messageKey = SSNConverter.SHORT;
  else if (len > 11)
    messageKey = SSNConverter.LONG;
  else if (len == 9)
  { 
    if (!isNaN(value))
                      return value;
  }
  else if (len == 11 && value.charAt(3) == '-' && value.charAt(6) == '-')
  {
    var result = value.substring(0,3) + 
     value.substring(4,6) + 
     value.substring(7);
    
    if (!isNaN(result))
                return result;
  }
  
  if (messageKey!=void(0) && this._messages!=void(0))
    return new ConverterException(this._messages[messageKey]);
    
  return (void 0);
}
 
function SSNConverter(messages)
{
  this._messages = messages;
}
 
SSNConverter.prototype = new Converter();
SSNConverter.prototype.getAsString = ssnGetAsString;
SSNConverter.prototype.getAsObject = ssnGetAsObject;
 
SSNConverter.SHORT = 'S';
SSNConverter.LONG  = 'L';
SSNConverter.NOT   = 'N';

The following example shows a custom Java class that implements server implementation for social security number. The details of the Java code has been removed from the getAsObject() and getAsString() methods.

package oracle.adfdemo.view.faces.convertValidate;
 
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
 
import oracle.adf.view.faces.converter.ClientConverter;
/**
 * <p>Social Security number converter.</p>
 * 
 */
public class SSNConverter implements Converter, ClientConverter
{
public static final String CONVERTER_ID = "oracle.adfdemo.SSN";
 
public Object getAsObject(
  FacesContext context, 
  UIComponent component, 
  String value)
{
  // some Java code ...
}
 
public String getAsString(
  FacesContext context, 
  UIComponent component, 
  Object value)
{
  // some Java code ...
}
 
 
  public String getClientConversion(
FacesContext context,
   UIComponent component)
  {
// in a real app the messages would be translated
   return "new SSNConverter({" + 
   "S:'Value \"{0}\" in \"{1}\" is too short.'," + 
   "L:'Value \"{0}\" in \"{1}\" is too long.'," + 
   "N:'Value \"{0}\" in \"{1}\" " + 
   "is not a social security number.'})";
  }
 
  
  public String getClientScript(
   FacesContext context,
   UIComponent component)
  {  
// check if the script has already been returned this request
Object scriptReturned = 
context.getExternalContext().getRequestMap().get(CONVERTER_ID);
 
// if scriptReturned is null the script hasn't been returned yet  
if ( scriptReturned == null)
{
  context.getExternalContext().getRequestMap().put(CONVERTER_ID, 
   Boolean.TRUE);  
  return  _sSSNjs;
}
// if scriptReturned is not null, then script has already been returned,
// so don't return it again.
else
  return null;
 
   }
  private static final String _sSSNjs =
"function ssnGetAsString(value)"+
"{return value.substring(0,3) + '-' " + 
  "+ value.substring(3,5) + '-' + value.substring(5);}" +
"function ssnGetAsObject(value)" +
  "{if (!value)return (void 0);" + 
  "var len=value.length;"+
  "var messageKey = SSNConverter.NOT;" +
  "if (len < 9 )"+
    "messageKey = SSNConverter.SHORT;" +
  "else if (len > 11)"+
    "messageKey = SSNConverter.LONG;" +
  "else if (len == 9)" +
  "{ if (!isNaN(value))" +
     "return value;" +
  "}" +
  "else if (len == 11 && value.charAt(3) == '-' && " +
"value.charAt(6) == '-')" +
  "{" +
"var result = value.substring(0,3) + value.substring(4,6) + " + 
"value.substring(7);"+
"if (!isNaN(result))"+
  "return result;" +
  "}" +
 "if (messageKey!=void(0) && this._messages!=void(0))" +
   "return new ConverterException(this._messages[messageKey]);" +
 "return void(0);}" +
"function SSNConverter(messages)" +
  "{this._messages = messages;}" +
"SSNConverter.prototype = new Converter();" +
"SSNConverter.prototype.getAsString = ssnGetAsString;" +
"SSNConverter.prototype.getAsObject = ssnGetAsObject;" +
"SSNConverter.SHORT = 'S';" +
"SSNConverter.LONG  = 'L';" +
"SSNConverter.NOT   = 'N';";
  
}

7.4.2 Using Custom ADF Faces Converter on a JSF Page

If a custom ADF Faces converter is registered in an application under a class for a specific data type, whenever a component's value references a value binding that has the same type as the custom converter object, JSF will automatically use the converter of that class to convert the data. In that case, you do not need to use the converter attribute to register the custom converter on a component, as shown in the following code:

<af:inputText value="#{myBean.myProperty}"/>

where myProperty data type has the same type as the custom converter. Alternatively, you can bind your converter class to the converter attribute of the input component.

7.4.3 How to Declaratively Register a Client-Side Only Converter Script

The af:clientConverter tag provides UI developers with a declarative alternative to register a custom client-only converter script, while still allowing the use of pre-programmed methods.

Usually, input or output fields whose data is encrypted by cloud data protection services cannot be formatted on the server for the risk of data corruption. Such fields are generally identified by the protected attribute. The af:clientConverter tag is useful in situations where the data formatting requirements needs be delayed to the point of page rendering where it is safe to format protected data.
The tag is applied as a child to input or output tags where conversion is needed. It uses the getAsString and getAsObject attributes to accept an inline JavaScript expression. The tag also offers the getAsStringMethod and getAsObjectMethod attributes to call a JavaScript method instead.
To use the af:clientConverter tag:
  1. Set clientComponent to true on the parent input or output tag. Presence of client component is mandatory for the functioning of the client converter.
  2. Add an af:clientConverter tag to the input or output element to be formatted.
  3. To convert an input to a desired string format, provide the valid JavaScript expression in the getAsString attribute. Use the value variable to access the field value.
    The following example accepts a numeric input and formats it as a credit card number.
    <af:outputText value="1234567890123456" id="outputText1" clientComponent="true">
    <af:clientConverter getAsString="return value.substr(0,4) + '-' + value.substr(4,4) + '-' + value.substr(8,4) + '-' + value.substr(12,4);"/>
    </af:outputText>
    
  4. To convert a formatted string back to its original form, provide the valid JavaScript expression in the getAsObject attribute.
    This is useful for internal validation purposes. For example, the credit card field should have a length restriction validator for a maximum allowed length of 16. In the absence of a getAsObject implementation, the validator would receive “1234–5678–9012–3456” which has a length of 19 and would fail the validation. The following example accepts a formatted input and returns a numeric value.
    <af:inputText value="1234567890123456" id="inputText1" clientComponent="true">
    <af:clientConverter  getAsString="return value.substr(0,4) + '-' + value.substr(4,4) + '-' + value.substr(8,4) + '-' + value.substr(12,4);"
     getAsObject="return (value == null || value.length == 0)? value : value.replace(/-/g, '');" />
    </af:inputText>
    

    Note:

    If the converter is applied to an input field, the submitted value is taken from the field and not from the return value of getAsObject/getAsObjectMethod.
  5. As an alternative to using JavaScript inline, you can use previously created methods. To do this, use the getAsStringMethod and getAsObjectMethod attributes.
    If the expression language is too verbose, or if a method exists for reuse, these two attributes may be used. In the following example, the method formatCreditCardNumber() is called to tokenize a string input as a credit card number. The method parseCreditCardNumber() may be invoked to return the tokenized number to its original format.

    Note:

    The implementation of the getAsObject/getAsObjectMethod attributes is optional if the parent tag has no associated validator.
    <af:inputText value="#{demoInput.creditCardNumber}" id="inpt1">
            <af:clientConverter getAsStringMethod="formatCreditCardNumber" getAsObjectMethod="parseCreditCardNumber" hint="Credit Card digits"/>
    </af:inputText>
    
    The following example shows the sample methods formatCreditCardNumber() and parseCreditCardNumber(). Methods can be used inline with the af:resource tag or be part of a linked external JavaScript file.
    <af:resource type="javascript">
    /**
       * Formats a given credit card number string into a standard 4 digit space separated grouping. (xxx xxx xxx xxx)
       * @param {String} The unformatted credit card number string that needs to be formatted
       *
       * @return {String} The formatted credit card number
       */
      function formatCreditCardNumber(value)
      {
        if (value == null || value.length == 0)
          return value;
    
        var retVal = value.substr(0,4) + ' ';
        retVal += value.substr(4,4) + ' '
        retVal += value.substr(8,4) + ' '
        retVal += value.substr(12,4);
     
        return retVal;
      }
    
      /**
       * Parses the credit card number as formatted by the function formatCreditCardNumber back to a contiguous numeric string for postback.
       * @param {value} The formatted credit card number string that needs to be parsed
       *
       * @return {String} The parsed credit card number
       */
      function parseCreditCardNumber(value)
      {
        if (value == null || value.length == 0)
          return value;
    
        return value.replace(/ /g,'');
      }
    </af:resource>
    

7.5 Adding Validation

ADF Faces input components support validation capabilities. You can add validation for an input component using UI component attributes, Default ADF Faces validators, and Custom ADF Faces validators.

You can add validation so that when a user edits or enters data in a field and submits the form, the data is validated against any set rules and conditions. If validation fails, the application displays an error message. For example, in Figure 7-3 a specific date range for user input with a message hint is set by the af:validateDateTimeRange component and an error message is displayed in the message popup window when an invalid value is entered.

Figure 7-3 Date Range Validator with Error Message

This image is described in the surrounding text

On the view layer use ADF Faces validation when you want client-side validation. All validators provided by ADF Faces have a client-side peer. Many components have attributes that provide validation. See Using Validation Attributes. In addition, ADF Faces provides separate validation classes that can be run on both the client and the server. For details, see Using ADF Faces Validators. You can also create your own validators. For information about custom validators, see How to Create a Custom JSF Validator.

7.5.1 How to Add Validation

By default, ADF Faces syntactic and semantic validation occurs on both the client and server side. Client-side validation allows validators to catch and display data without requiring a round-trip to the server.

ADF Faces provides the following types of validation:

  • UI component attributes: ADF Faces input components provide attributes that can be used to validate data. For example, you can supply simple validation using the required attribute on ADF Faces input components to specify whether or not a value must be supplied. When the required attribute is set to true, the component must have a value. Otherwise the application displays an error message. See Using Validation Attributes.

  • Default ADF Faces validators: The validators supplied by the JSF framework provide common validation checks, such as validating date ranges and validating the length of entered data. See Using ADF Faces Validators.

  • Custom ADF Faces validators: You can create your own validators and then select them to be used in conjunction with UI components. See Creating Custom JSF Validation.

When validation is added, validation errors can be displayed inline or in a popup window on the page. For information about displaying messages created by validation errors, see Displaying Tips, Messages, and Help.

7.5.1.1 Using Validation Attributes

Many ADF Faces UI components have attributes that provide simple validation. For example, the af:inputDate component has maxValue and minValue attributes to specify the maximum and minimum number allowed for the Date value.

For additional help with UI component attributes, in the Properties window, right-click the attribute name and choose Help.

7.5.1.2 Using ADF Faces Validators

ADF Faces Validators are separate classes that can be run on the server or client. Table 7-2 describes the validators and their logic.

Table 7-2 ADF Faces Validators

Validator Tag Name Description

ByteLengthValidator

af:validateByteLength

Validates the byte length of strings when encoded. The maximumLength attribute of inputText is similar, but it limits the number of characters that the user can enter.

DateRestrictionValidator

af:validateDateRestriction

Validates that the entered date is valid with some given restrictions.

DateTimeRangeValidator

af:validateDateTimeRange

Validates that the entered date is within a given range. You specify the range as attributes of the validator.

DoubleRangeValidator

af:validateDoubleRange

Validates that a component value is within a specified range. The value must be convertible to a floating-point type.

LengthValidator

af:validateLength

Validates that the length of a component value is within a specified range. The value must be of type java.lang.String.

LongRangeValidator

af:validateLongRange

Validates that a component value is within a specified range. The value must be any numeric type or String that can be converted to a long data type.

RegExpValidator

af:validateRegExp

Validates the data using Java regular expression syntax.

Note:

To register a custom validator on a component, use a standard JSF f:validator tag. For information about using custom validators, see Creating Custom JSF Validation.

To add ADF Faces validators:

  1. In the Structure window, right-click the component for which you would like to add a validator, choose Insert Inside component, then ADF Faces to insert an ADF Faces validator.

    You may also choose JSF > Validator to insert a JSF reference implementation validator.

  2. Choose a validator tag (for example, Validate Date Time Range) and click OK.
  3. In the JSF page, select the component and in the Properties window, set values for the attributes, including any messages for validation errors that may occur, such as empty or incorrect required values.

    For additional help, right-click any of the attributes and choose Help.

    ADF Faces lets you customize the detail portion of a validation error message. By setting a value for a MessageDetailxyz attribute, where xyz is the validation error type (for example, MessageDetailmaximum), ADF Faces displays the custom message instead of a default message, if validation fails.

7.5.2 What Happens at Runtime: How Validators Work

When the user submits the page, ADF Faces checks the submitted value and runs conversion on any non-null value. The converted value is then passed to the validate() method. If the value is empty, the required attribute of the component is checked and an error message is generated if indicated. If the submitted value is non-null, the validation process continues and all validators on the component are called in order of their declaration.

Note:

ADF Faces provides extensions to the standard JSF validators, which have client-side support.

ADF Faces validation is performed during the Process Validations phase. If any errors are encountered, the components are invalidated and the associated messages are added to the queue in the FacesContext instance. The Update Model phase only happens when if there are no errors converting or validating. Once all validation is run on the components, control passes to the model layer, which runs the Validate Model Updates phase. As with the Process Validations phase, if any errors are encountered, the components are invalidated and the associated messages are added to the queue in the FacesContext instance.

The lifecycle then goes to the Render Response phase and redisplays the current page. If the component generates an error, ADF Faces automatically highlights the error. For instance, ADF Faces renders a red box around an inputText component when there is a validation error, as shown in Figure 7-4.

For information about adding error messages when a validation or conversion error occurs, see Displaying Hints and Error Messages for Validation and Conversion.

7.5.3 What You May Need to Know About Multiple Validators

You can set zero or more validators on a UI component. You can set the required attribute and use validators on a component. However, if you set the required attribute to true and the value is null or a zero-length string, the component is invalidated and any other validators registered on the component are not called.

This combination might be an issue if there is a valid case for the component to be empty. For example, if the page contains a Cancel button, the user should be able to click that button and navigate off the page without entering any data. To handle this case, you set the immediate attribute on the Cancel button's component to true. This attribute allows the action to be executed during the Apply Request Values phase. Then the default JSF action listener calls FacesContext.renderResponse(), thus bypassing the validation whenever the action is executed. See Using the JSF Lifecycle with ADF Faces .

7.6 Creating Custom JSF Validation

In ADF Faces, you can add your own validation logic to meet your specific business needs. You can create custom validation by adding a method that provides the required validation on a backing bean or by using JSF validators.

If you want custom validation logic for a component on a single page, you can create a validation method on the page's backing bean.

If you want to create logic that will be reused by various pages within the application, or if you want the validation to be able to run on the client side, you should create a JSF validator class. You can then create an ADF Faces version, which will allow the validator to run on the client.

7.6.1 How to Create a Backing Bean Validation Method

When you want custom validation for a component on a single page, create a method that provides the required validation on a backing bean.

Before you begin:

It may be helpful to have an understanding of custom JSF validation. See Creating Custom JSF Validation.

You may also find it helpful to understand functionality that can be added using other ADF Faces features. See Additional Functionality for ADF Faces Converters and Validators.

To add a backing bean validation method:

  1. Insert the component that will require validation into the JSF page.
  2. In the visual editor, double-click the component.
  3. In the Bind Validator Property dialog, enter or select the managed bean that will hold the validation method, or click New to create a new managed bean. Use the default method signature provided or select an existing method if the logic already exists.

    When you click OK in the dialog, JDeveloper adds a skeleton method to the code and opens the bean in the source editor.

  4. Add the required validation logic. This logic should use the javax.faces.validator.ValidatorException exception to throw the appropriate exceptions and the javax.faces.application.FacesMessage error message to generate the corresponding error messages.

    For information about the Validator interface and FacesMessage, see the Javadoc for javax.faces.validator.ValidatorException and javax.faces.application.FacesMessage, or visit http://docs.oracle.com/javaee/index.html.

7.6.2 What Happens When You Create a Backing Bean Validation Method

When you create a validation method, JDeveloper adds a skeleton method to the managed bean you selected. The following example shows the code JDeveloper generates.

public void inputText_validator(FacesContext facesContext, 
     UIComponent uiComponent, Object object) {
        // Add event code here...
}

When the form containing the input component is submitted, the method to which the validator attribute is bound is executed.

7.6.3 How to Create a Custom JSF Validator

Creating a custom validator requires writing the business logic for the validation by creating a Validator implementation of the interface, and then registering the custom validator with the application. You can also create a tag for the validator, or you can use the f:validator tag and the custom validator as an attribute for that tag.

You can then create a client-side version of the validator. ADF Faces client-side validation works in the same way that standard validation works on the server, except that JavaScript is used on the client. JavaScript validator objects can throw ValidatorExceptions exceptions and they support the validate() method.

Before you begin:

It may be helpful to have an understanding of custom JSF validation. See Creating Custom JSF Validation.

You may also find it helpful to understand functionality that can be added using other ADF Faces features. See Additional Functionality for ADF Faces Converters and Validators.

To create a custom JSF validator:

  1. Create a Java class that implements the javax.faces.validator.Validator interface. The implementation must contain a public no-args constructor, a set of accessor methods for any attributes, and a validate method to implement the Validator interface.

    public void validate(FacesContext facesContext, 
        UIComponent uiComponent, 
        Object object)
        throws ValidatorException {
    ..
    }
    

    For information about these classes, refer to the Javadoc or visit http://docs.oracle.com/javaee/index.html.

  2. Add the needed validation logic. This logic should use the javax.faces.validate.ValidatorException exception to throw the appropriate exceptions and the javax.faces.application.FacesMessage error message to generate the corresponding error messages.

    For information about the Validator interface and FacesMessage, see the Javadoc for javax.faces.validate.ValidatorException and javax.faces.application.FacesMessage, or visit http://docs.oracle.com/javaee/index.html.

  3. If your application saves state on the client, your custom validator must implement the Serializable interface, or the StateHolder interface, and the saveState(FacesContext) and restoreState(FacesContext, Object) methods of the StateHolder interface.

    See the Javadoc for the StateHolder interface of the javax.faces.component package.

  4. Register the validator in the faces-config.xml file.

    1. Open the faces-config.xml file.

      The faces-config.xml file is located in the View_Project > WEB-INF node in the JDeveloper Applications window.

    2. In the editor window, click the Overview tab.

    3. Choose Validators and click Add to add the validator information.

      Click Help or press F1 for additional help in registering the validator.

To create a client-side version of the validator:

  1. Write a JavaScript version of the validator, passing relevant information to a constructor.

  2. Implement the interface org.apache.myfaces.trinidad.validator.ClientValidator, which has two methods. The first method is getClientScript(), which returns an implementation of the JavaScript Validator object. The second method is getClientValidation(), which returns a JavaScript constructor that is used to instantiate an instance of the validator.

    The following example shows a validator in Java.

    public String getClientValidation(
    FacesContext context,
    UIComponent component)
    {
        return ("new SSNValidator('Invalid social security number.','Value \"{1}\"
                    must start with \"123\".')");
    }
    

    The Java validator calls the JavaScript validator shown in the following example.

    function SSNValidator(summary, detail)
    {
      this._detail = detail;
      this._summary = summary;
    }
    

To use a custom validator on a JSF page:

  • To use a custom validator that has a tag on a JSF page, you must manually nest it inside the component's tag.

    The following example shows a custom validator tag nested inside an inputText component. Note that the tag attributes are used to provide the values for the validator's properties that were declared in the faces-config.xml file.

<h:inputText id="empnumber" required="true">
  <hdemo:emValidator emPatterns="9999|9 9 9 9|9-9-9-9" />
</h:inputText>

To use a custom validator without a custom tag:

To use a custom validator without a custom tag, nest the validator's ID (as configured in faces-config.xml file) inside the f:validator tag. The validator's ID attribute supports EL expression such that the application can dynamically determine the validator to use.

  1. From the Structure window, right-click the input component for which you want to add validation, and choose Insert inside component > JSF > Validator.

  2. With input component selected, in the Properties window, select the validator's ID from the dropdown list and click OK.

    JDeveloper inserts code on the JSF page that makes the validator ID a property of the f:validator tag.

The following example shows the code on a JSF page for a validator using the f:validator tag.

<af:inputText id="empnumber" required="true">
  <f:validator validatorID="emValidator"/>
</af:inputText>

7.6.4 What Happens When You Use a Custom JSF Validator

When you use a custom JSF validator, the application accesses the validator class referenced in either the custom tag or the f:validator tag and executes the validate() method. This method executes logic against the value that is to be validated to determine if it is valid. If the validator has attributes, those attributes are also accessed and used in the validation routine. Like standard validators, if the custom validation fails, associated messages are placed in the message queue in the FacesContext instance.