[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[转帖]JSF for nonbelievers: JSF conversion and validation

上一篇:[备忘]灯具安装、膨胀螺栓使用经验……
下一篇:[整理]vbscript中头疼的参数传递方式

添加日期:2010/3/27 7:07:00 快速返回   返回列表 阅读5210次
From:http://www.ibm.com/developerworks/library/j-jsf3/

================================
This month, Rizon Software's CTO Paul Tabor joins me on my quest to dispel the FUD about JSF. In this article, we'll work through the concepts of JSF's conversion and validation framework, which is much simpler to use and far more flexible than you may think.

We'll start with an introduction to conversion and validation procedures as they apply to the JSF lifecycle, then demonstrate a default conversion and validation procedure in a simple JSF application. We'll also show you how to create and plug-in your own custom implementations to deal with more demanding scenarios. As Rick has in previous articles, we'll focus on both theory and practice, explaining the concepts and then walking through them with a working example. The example application will cover most conversion and validation use cases, albeit at a basic level.

Note that the default build environment for the example application is Maven, though an Ant script is also provided. You can download the example source by clicking the Code icon at the top or bottom of this page. For simplicity, you'll find the example setup the same as it was in the previous article. See 
Resources
 for further directions on the build environment setup, including directions for building and running the example application in Ant rather than Maven.

Conversion and validation
While it isn't necessary to understand the underpinnings of the JavaServer Faces lifecycle to use conversion and validation in a JSF Web application, it probably is a good idea to review some of the basics before jumping into conversion and validation specifics. Besides, a little dose of JSF lifecycle know-how can go a long way toward simplifying your Web application development efforts. It will also help you better understand JSF's pluggable capabilities.
Figure 1 outlines what we call the "basic JSF lifecycle." Basic simply implies a typical faces request-and-response scenario dealing with submitted form values.

Figure 1. Basic JSF lifecycle

按此在新窗口浏览图片
Obviously, different scenarios could differently impact the lifecycle descriptions highlighted here. We'll describe some of them a little later in the article. For now, you should simply note that conversion and validation processes occur at the phases of apply request valuesprocess validations, and render response.

We'll explain in a minute why conversion and validation happen at these phases, but first let's clear up a more basic question: What is conversion? Simply put, it's the process of ensuring data is of the right object or type. Here are two typical conversions:

  • string value is convertible to a java.util.Date 

  • string value is convertible to a Float



As for validation, it ensures data contains the expected content. Here are two typical validations:

  • java.util.Date is MM/yyyy format 

  • Float is between 1.0 and 100.0



Lifecycle phases of interest
The main purpose of conversion and validation is to ensure values have been properly sanitized before updating model data. 
Subsequently, when the time comes to invoke application methods to actually do something with that data, you can safely make certain assumptions about the state of your model. 
Conversion and validation allow you to focus on business logic rather than the tedious qualifications of input data such as null checks, length qualifiers, range boundaries, etc.

It makes sense, then, that conversion and validation processes happen before component data is bound to your backing bean model in the update model data lifecycle phase. As you saw in Figure 1, conversion occurs in the apply request values phase and validation in the process validations phase. These phases are highlighted in Figure 2.
Figure 2. Conversion and validation phases of interest

按此在新窗口浏览图片

About the immediate attribute
Note that the conversion and validation processes outlined in Figure 2 represent the application flow when the UIInput component's immediate attribute is set to false. 
Were the attribute set to true, conversion and validation would occur earlier in the lifecycle, during the apply request values phase (see Figure 3). 

A detailed discussion about using the immediate attribute is beyond the scope of this article, but there are instances where it is useful -- such as managing dynamic lists (which you may recall from the previous article in this series) and even bypassing validation altogether (when used with a UICommand component). 
Can you think of an application where it would be useful to bypass validation completely?
Figure 3 shows where conversion and validation would occur in the JSF application lifecycle were the immediate attribute set to true.
Figure 3. When the immediate attribute is true

按此在新窗口浏览图片

A working example
From here on we'll use an example application to demonstrate the concepts discussed. This month's example application will demonstrate JSF's conversion and validation capabilities. Bear in mind that the application is very simple and not necessarily comprehensive: Our goal isn't to build an application for use in the real world, after all! The example app will demonstrate the following:

  • Usage of standard JSF converters for converting form field data

  • Usage of standard JSF validation components for validating form field data
  •  
  • How to write custom converters and validator
  •  
  • How to register custom converters and validators in the faces-config.xml file

  • How to customize default error messages


The example application is a simple user registration form. Our objective is to gather user data such as name, age, e-mail address, and phone number. Then, we'll show you how to utilize JSF conversion and validation to ensure that the collected data is appropriate for the model.
The application utilizes three JSP pages:

  • index.jsp redirects the user to UserRegistration.jsp

  • UserRegistration.jsp contains the application's form fields

  • results.jsp notifies the application that the user was registered


We'll start start with a look at the options for coding JSF conversion processes.
=============================================================
JSF conversion
As previously mentioned, conversion is the process of ensuring data is of the right object or type; hence we convert strings values into other types like Date objects, primitive float, or Float objects. You can use built-in converters or write custom converters.
JSF supplies many standard data converters. You can also plug in your own custom converter by implementing the Converter interface, but more on that later. The following table shows converter ids and the corresponding implementation classes used by JSF for a simple data conversion. Most data conversions happen automatically.








javax.faces.BigDecimaljavax.faces.convert.BigDecimalConverter
javax.faces.BigIntegerjavax.faces.convert.BigIntegerConverter
javax.faces.Booleanjavax.faces.convert.BooleanConverter
javax.faces.Bytejavax.faces.convert.ByteConverter
javax.faces.Characterjavax.faces.convert.CharacterConverter
javax.faces.DateTimejavax.faces.convert.DateTimeConverter
javax.faces.Doublejavax.faces.convert.DoubleConverter
javax.faces.Floatjavax.faces.convert.FloatConverter

Figure 4 demonstrates a default conversion on the user's age. The JSF tag is configured as such:


<!-- UserRegistration.jsp -->
<h:inputText id="age" value="#{UserRegistration.user.age}"/>


    
Figure 4. User registration: default conversion on age

按此在新窗口浏览图片

A converter for every occasion
UserRegistration.user.age represents a value-binding property that is of type int. For bindings of either primitive types, or BigInteger/ BigDecimal, JSF chooses a standard converter. However, you may also use a specific converter for increased granularity using the <f:converter/> tag, as shown here.

<!-- UserRegistration.jsp -->
<h:inputText id="age" value="#{UserRegistration.user.age}">
             <f:converter id="javax.faces.Short"/>
</h:inputText>



In Figure 5 you see one scenario where JSF uses a standard converter. In this case, while age is actually a valid integer, conversion still fails because the value is not a short integer.
Figure 5. Using the f:converter tag

按此在新窗口浏览图片

Choosing a date format pattern
Although JSF handles primitives and such quite nicely by default, when dealing with date data you must specify the conversion tag <f:convertDateTime/>. This tag is based on the java.text package and utilizes short, long, and custom patterns. Here's an example:

<!-- UserRegistration.jsp -->
<h:inputText id="birthDate" value="#{UserRegistration.user.birthDate}">
             <f:convertDateTime pattern="MM/yyyy"/>
</h:inputText>


             
This example demonstrates how to use <f:convertDateTime/> to ensure the user's birth date is convertible into a date object formatted as MM/yyyy (month/year). See JSF's java.text.SimpleDataFormat (in 
Resources
) for a list of patterns.

Additional patterns
In addition to allowing you to convert date and time formats, JSF provides a special converter for dealing with numbers such as percentages or currency. This converter deals with grouping (such as commas), number of decimal digits, currency symbols, and such. For example, the following usage of <f:convertNumber/> is one technique for dealing with currency:


<!-- UserRegistration.jsp -->
<h:inputText id="salary" value="#{UserRegistration.user.salary}">
             <f:convertNumber maxFractionDigits="2"
                       groupingUsed="true"
                       currencySymbol="$"
                       maxIntegerDigits="7"
                       type="currency"/>
</h:inputText>


In Figure 6, you see some incorrectly formatted currency data and the resulting conversion error.
Figure 6. Using the f:convertNumber tag

按此在新窗口浏览图片
==================================================
Custom converters
Custom data conversion is necessary if you need to convert field data into an application-specific value object, as in the following examples:

  • String to PhoneNumber object (PhoneNumber.areaCode, PhoneNumber.prefix, ...) 

  • String to Name object (Name.first, Name.last) 

  • String to ProductCode object (ProductCode.partNum, ProductCode.rev, ...)


To create a custom converter, you must do the following:
1.Implement the Converter interface (a.k.a. javax.faces.convert.Converter).
2.Implement the getAsObject method, which converts a field (string) into an object (for example, PhoneNumber).
3.Implement the getAsString method, which converts an object (for example, PhoneNumber) into a string.
4.Register your custom converter in the Faces context.
5.Insert the converter into your JSPs with the  <f:converter/> tag.

You can see for yourself how these steps fit into the JSF application lifecycle. In Figure 7, JSF calls the getAsObject method of the custom converter during the apply request values phase. 
This is where the converter must convert the request string value into the desired object type, and then return the object for storage in the corresponding JSF component. 
When the value is rendered back to the view, JSF will call the getAsString method in the render response phase. 
This means the converter is also responsible for transforming the object data back in to a string representation.
Figure 7. Custom converter getAsObject and getAsString methods

按此在新窗口浏览图片
Creating a custom converter
We'll use a case study to demonstrate the implementation of the Converter interface, getAsObject and getAsString methods, and how to register the converter with the Faces context.
The goal of this case study is to convert a single field string value into a PhoneNumber object. We'll go through it step by step.

Step 1: Implement the Converter interface
This step implements the Converter interface.


import javax.faces.convert.Converter;
import org.apache.commons.lang.StringUtils;
...
public class PhoneConverter implements Converter {
    ...
}



Step 2: Implement the getAsObject method
This step converts a field value into a PhoneNumber object.


public class PhoneConverter implements Converter {
    ...
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (StringUtils.isEmpty(value)){ return null;}
        PhoneNumber phone = new PhoneNumber();
        String [] phoneComps = StringUtils.split(value," ,()-");
        String countryCode = phoneComps[0];
        phone.setCountryCode(countryCode);
        if ("1".equals(countryCode)){
            String areaCode = phoneComps[1];
            String prefix = phoneComps[2];
            String number = phoneComps[3];
            phone.setAreaCode(areaCode);
            phone.setPrefix(prefix);
            phone.setNumber(number);
        }else {
            phone.setNumber(value);
        }
        return phone;
    }    
}



Step 3: Implement the getAsString method
This step converts a PhoneNumber object into a string.


public class PhoneConverter implements Converter {
    ...
    public String getAsString(FacesContext context, 
                              UIComponent component, Object value) {
        return value.toString();
    }
}
public class PhoneNumber implements Serializable {
    ...
    public String toString(){
        if (countryCode.equals("1")){
            return countryCode + " " + areaCode 
                               + " " + prefix + " " + number;
        }else{
            return number;
        }
    }
}



Step 4: Register custom converter with faces context
Step 4 can be executed in one of two ways. The first option is to register the PhoneConverter class with the id of (for example) arcmind.PhoneConverter. This id will then be used by the <f:converter/> tag in your JSP pages. Here's the code for Step 4, option 1:


<converter>
  <converter-id>arcmind.PhoneConverter</converter-id>
  <converter-class>com.arcmind.converters.PhoneConverter</converter-class>
</converter>


Alternately, you could register the PhoneConverter class to handle all PhoneNumber objects automatically, as shown here.


<converter>
  <converter-for-class>com.arcmind.value.PhoneNumber</converter-for-class>
  <converter-class>com.arcmind.converters.PhoneConverter</converter-class>
</converter>



Step 5: Use the converter tag in your JSPs?
The execution of the next step will, of course, depend on the registration option you've chosen. If you chose to register the PhoneConverter class with the id of arcmind.PhoneConverter, then you'll use the <f:converter/>  tag as shown here.


<h:inputText id="phone" value="#{UserRegistration.user.phone}">
        <f:converter  converterId="arcmind.PhoneConverter" />
</h:inputText>  


If you chose to register the PhoneConverter class to handle all PhoneNumber objects automatically then you won't need to use the <f:converter/> tag in your JSPs. Here's the code for Step 5 without the converter tag.


<h:inputText id="phone" value="#{UserRegistration.user.phone}">
        [Look mom no converter!]
</h:inputText>  


And with that we're done with the conversion processing code for the example application! Here's what the app looks like so far.
Figure 8. Example app with conversion processing

按此在新窗口浏览图片
==========================================================
JSF validation
As you'll recall, JSF validation ensures the application data contains the expected content, such as:

  • java.util.Date is MM/yyyy format 

  • Float is between 1.0 and 100.0


  • There are four forms of validation within JSF:

    • Built-in validation components 

    • Application-level validation 

    • Custom validation components (which implement the Validator interface)
    •  
    • Validation methods in backing beans (inline)


    We'll explain and demonstrate each of these forms in the discussion that follows.

    The JSF validation lifecycle and components
    Figure 9 shows a lifecycle case study for the first name field of our user registration form. The code references are intended to be interpreted as pseudo-code.
    Figure 9. Validation in the JSF lifecycle

    按此在新窗口浏览图片
    Here's a list of the standard validation components supplied by JSF:

    • DoubleRangeValidator: Component's local value must be numeric type; must be in range specified by minimum and/or maximum values.

    • LongRangeValidator: Component's local value must be numeric type and convertible to long; must be in range specified by minimum and/or maximum values.

    • LengthValidator: Type must be string; length must be in range specified by minimum and/or maximum values.


    ==================================================
    Standard validation
    In our example app the user's age can be any valid integer (byte, short, int). Because it doesn't make sense to allow an age of, say, -2, you'll probably want to add some validation to the field. Here's some simple validation code for ensuring the model integrity of data in an age field:


    <h:inputText id="age" value="#{UserRegistration.user.age}">
              <f:validateLongRange maximum="150"
                                      minimum="0"/>
    </h:inputText>


    Once you have the age field sorted out, you might want to specify length restrictions on the first-name field. You could code this validation as follows:


    <h:inputText id="firstName"
                    value="#{UserRegistration.user.firstName}">
        <f:validateLength minimum="2" 
                             maximum="25" />
    </h:inputText>


    Figure 10 shows the default verbose validation messages generated by the above standard validation examples.
    Figure 10. Standard validation error messages

    按此在新窗口浏览图片
    Although it works for many scenarios, JSF's built-in validation is somewhat limited. When dealing with e-mail validation, phone numbers, URLs, dates, etc., it's sometimes better to write your own validator; but we'll get to that in just a bit.
    =============================================================
    Application-level validation
    In concept, application-level validation is really business logic validation. JSF separates form- and/or field-level validation from business-logic validation. Basically, application-level validation entails adding additional code to the backing bean methods that use the model to qualify the data already bound to your model. In the case of a shopping cart, form-level validation may validate whether a quantity entered is valid, but you would need business-logic validation to check whether the user had exceeded his or her credit limit. This is another example of the separation of concerns in JSF. 

    For example, let's say the user clicks a button that is bound to an action method, which gets invoked during the invoke application phase (refer back to 
    Figure 1
     for details). Prior to performing any manipulation of model data, which was presumably updated during the update model phase, you could add code that checks to see if the data entered is valid based on the application's business rules.

    For instance, in the example application, the user clicks the Register button, which is bound to the register() method of the application controller. We could add validation code to the register() method to determine whether the first-name field is blank or null. In cases where the field was null, we could also add a message to the FacesContext directing the associated component to return navigation to the current page. 

    Now, granted this is not a good example of business-rule logic. A better example would be checking to see if the user had exceeded his or her credit limit. In this case, instead of checking to see if the field was blank we could invoke a method on a model object to ensure that the current user wasn't already in the system.

    You can see an outline of this process in Figure 11.
    Figure 11. Application-level validation

    按此在新窗口浏览图片
    Notice how in the register() method, the message is added to the FacesContext as ${formId}:${fieldId}. Figure 12 shows the relationship between messages and component ids.

    Figure 12. A validation message

    按此在新窗口浏览图片

    Pros and cons of application-level validation
    Application-level validation is clearly straightforward and easy to do. However, this form of validation occurs after other forms of validation (standard, custom, component).
    The advantages of application-level validation are as follows:

    • Easy to implement

    • No need for a separate class (custom validator) 

    • No need for page author to specify validator


    The disadvantages of application-level validation are as follows:

    • Occurs after other forms of validation (standard, custom) 

    • Validation logic limited to backing bean method, resulting in limited re-use 

    • Can be difficult to manage in large applications and/or team environment


    Ultimately, application-level validation should be used only for circumstances requiring business-logic validation.
    ===================================================
    Custom validation components
    You will need to build your own custom validation components for data types that aren't supported by the standard JSF validators, including e-mail addresses and zip codes. You'll also need to build your own validators in cases where you want explicit control over the validation messages displayed to the end user. With JSF, you can create pluggable validation components that are re-usable throughout your Web applications.

    MyFaces is an open source implementation of JSF that provides many additional validators, including some that are not included in JSF. See 
    Resources
     to learn about MyFaces.

    The steps to create a custom validator are as follows; we'll go over them one by one:
    1.Create a class that implements the Validator interface (javax.faces.validator.Validator).
    2.Implement the validate method.
    3.Register your custom validator in the faces-confix.xml file.
    4.Use the <f:validator/> tag in your JSPs.

    Here's the example code to create a custom validator, step by step.

    Step 1: Implement the Validator interface
    The first step is to implement the Validator interface.


    import javax.faces.validator.Validator;
    import javax.faces.validator.ValidatorException;
    ...
    public class ZipCodeValidator implements Validator{
        private boolean plus4Required;
        private boolean plus4Optional;

        /** Accepts zip codes like 85710 */
        private static final String ZIP_REGEX = "[0-9]{5}";
        
        /** Accepts zip code plus 4 extensions like "-1119" or " 1119" */
        private static final String PLUS4_REQUIRED_REGEX = "[ |-]{1}[0-9]{4}";
        
        /** Optionally accepts a plus 4 */
        private static final String PLUS4_OPTIONAL_REGEX = "([ |-]{1}[0-9]{4})?";
        ...
    }


    Step 2: Implement the validate method
    Next, you need to implement the validate method.


    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
             
          /* Create the correct mask */
          Pattern mask =  null; 
             
          /* more on this method later */
          initProps(component);
          if (plus4Required){
                mask = Pattern.compile(ZIP_REGEX + PLUS4_REQUIRED_REGEX);
          } else if (plus4Optional){
                mask = Pattern.compile(ZIP_REGEX + PLUS4_OPTIONAL_REGEX);
          } else if (plus4Required && plus4Optional){
                throw new IllegalStateException("Plus 4 is either optional or required");
          }
          else {
                mask = Pattern.compile(ZIP_REGEX);
          }
                /* Get the string value of the current field */
          String zipField = (String)value; 
                 
                /* Check to see if the value is a zip code */
        Matcher matcher = mask.matcher(zipField);
             
        if (!matcher.matches()){
                 
           FacesMessage message = new FacesMessage();
           message.setDetail("Zip code not valid");
           message.setSummary("Zip code not valid");
           message.setSeverity(FacesMessage.SEVERITY_ERROR);
           throw new ValidatorException(message);
        }
     }



    Step 3: Register your custom validator with the FacesContext
    The code to register the custom validator with the FacesContext should look familiar to you by now.


      <validator>
        <validator-id>arcmind.zipCodeValidator</validator-id>
        <validator-class>com.arcmind.jsfquickstart.validation.ZipCodeValidator</validator-class>
      </validator>



    Step 4: Use the <f:validator/> tag in your JSPs
    The <f:validator/> tag declares use of the zipCodeValidator. The <f:validator/> tag sets the plus4Optional attribute to true. Note that this defines an attribute of the inputText component, not the validator!


      <h:inputText id="zipCode" value="#{UserRegistration.user.zipCode}">
          <f:validator validatorId="armind.zipCodeValidator"/>
          <f:attribute name="plus4Optional" value="true"/>
      </h:inputText>


    To read the plus4Optional attribute for the zipCodeinputText component, do the following:


    private void initProps(UIComponent component) {
      Boolean optional = Boolean.valueOf((String) component.getAttributes().
                                       get("plus4Optional"));
      Boolean required = Boolean.valueOf((String) component.getAttributes().
                                       get("plus4Required"));
      plus4Optional = optional==null ? plus4Optional : 
                             optional.booleanValue();
      plus4Required = required==null ? plus4Optional : 
                             required.booleanValue();
    }


    Overall, creating custom validators is fairly straightforward and makes validation reusable across many applications. The downside is that you do have to create another class and manage validator registration within the faces context. However, you can take the implementation of your custom validator one step further and make it look like built-in validation by creating a custom tag that utilizes the validator. For common validation concerns, such as e-mail validation, this approach can support design philosophies where code re-use and consistent application behavior are of utmost importance.
    ==================================================
    Validation methods in backing beans
    As an alternative to creating a separate validator class, you can simply implement custom validation in a backing bean method, as long as the method adheres to the same argument signature as the Validator interface's validate method. For instance, you might write the following method:


    [SomeBackingBean.java]
    public void validateEmail(FacesContext context, 
                              UIComponent toValidate,
                              Object value) {
        String email = (String) value;
        if (email.indexOf('@') == -1) {
           ((UIInput)toValidate).setValid(false);
            FacesMessage message = new FacesMessage("Invalid Email");
            context.addMessage(toValidate.getClientId(context), message);
        }
    }


    The method would then be used in the JSF tag via the validator attribute as shown here:


      <h:inputText id="email" 
                   value="#{UserRegistration.user.email}"
                   validator="#{UserRegistration.validateEmail}"   
                   required="true">
      </h:inputText>


    The validateEmail method is used by JSF to perform custom validation on an inputText component value bound to a user.email model property. If the e-mail format is invalid, then a message is added to the faces context for the associated component. Now, considering that this validation method is actually part of the backing bean, why does the value have to be generically evaluated with a component association in lieu of directly inspecting the local bean properties? For a hint, look at the prior lifecycle figures. Don't worry if you can't quite figure it out right now; we'll explain it all at the end of the article.

    Default validation
    Notice the required attribute of the email tag above. Utilizing the required attribute is a form of default validation. If the attribute is true then the corresponding component must have a value. One important note: if the required attribute is false, and no validation has been assigned to the tag/component, then JSF will skip validation for this component and leave the value and component state unchanged.
    Figure 13 is an overview of the forms of validation we've discussed.
    Figure 13. Validation overview

    按此在新窗口浏览图片
    =========================================================
    Custom messages
    As you might of noticed, the default conversion and validation messages provided by JSF are verbose and could generate confusion and irritability for end users who insist on entering invalid form data. Fortunately, it's possible to change the default messages supplied by JSF by creating your own message resource bundle. Contained in the jsf-impl.jar (or similar) is a message.properties file that contains the default messages shown in Figure 14.
    Figure 14. Default JSF conversion and validation messages

    按此在新窗口浏览图片

    You can change the default messages by creating your own message.properties file and switching out the message resource bundle in the faces context for the specified locale, as shown in Figure 15.
    Figure 15. Switching out the message resource bundles

    按此在新窗口浏览图片
    See 
    Resources
     to learn more about creating custom conversion and validation messages in JSF.
    ===========================================

    Working the JSF lifecycle
    We left a few loose ends for you to ponder earlier in the article, and the time has come to clean them up! One thing we mentioned was using 
    immediate attributes
     for UICommand buttons such as commandLink or commandButtons. We asked you to consider in what types of application scenarios you might want to skip validation.

    Basically, in any scenario where a user must enter data, that data must be validated. If the overall data entry is optional, however, then validation need not occur. One way of working around the validation phase of the JSF lifecycle is to utilize the UICommand component's immediate attribute, which can force the action to be invoked during the apply request values phase before the process validations phase (rather than during the invoke application phase, which occurs after the process validations phase). 

    The immediate attribute allows you to control page flow through standard navigation rules while bypassing validation altogether. You could implement this technique for specific scenarios such as online wizards with optional steps and/or forms (such as when the user clicks the Skip button to advance to the next view) or in cases where the user cancels out a form for some reason.

    The second loose end we left in the article is the question of why, if a validation method is actually part of a backing bean, its value must be generically evaluated with a component association. We told you to refer back to the 
    JSF application lifecycle
     and see if you could figure it out.

    The trick here is that, although the validateEmail inline validation method is part of the actual backing bean, the method must reference the value via component association rather than accessing the local properties directly. 

    Because validation occurs before the component values are bound to the model (in the update model values phase), 
    the model is in an unknown state. Therefore, you must write the inline custom validation logic as if it were dealing with validation in a custom Validator object. 
    This is also explains the requirement of maintaining the same method signature.

    What's interesting about both of these loose ends, of course, is that they ultimately lead back to the JSF application lifecycle. Together they illustrate the importance of understanding the lifecycle -- backwards, forwards, and inside out -- so that you can manipulate it when you need to.
    ==============================================
    Conclusion
    We've covered quite a bit of ground in this article when it comes to JSF conversion and validation. In fact, we've covered most of what you'll ever need to know about these processes to make them work in your applications (at least for this version of JSF)!

    Of course, we couldn't cover everything. For example, you might want to check out MyFaces (see 
    Resources
    ) for validator components not offered in JSF or discussed here. Additionally, while we discussed the most common conversion and validation techniques, there are some we couldn't include here. For instance, when writing custom components you can deal with conversion and/or validation directly within the component's decode/encode process (depending on the type of component and its functionality); but we'll have to save a more in-depth discussion of custom component development for a later time.

    Something else to keep in mind is that conversion and validation don't necessarily work well together. Conversion converts strings into objects, whereas most of the standard validators work on strings. 
    Therefore, you must execute caution when using custom convertors and validators together. For instance, our PhoneNumber object would not work with a length validator. 
    In this case, you would either have to write a custom validator, as well, or simply include any special validation logic in the custom converter. 
    We prefer the latter option because it allows us to simply associate a custom converter (with built-in validation logic) with a specific object type and have JSF handle that object type. 
    JSF does this for us automatically without having to specify any converter ids in the JSP. (Of course, some might call this lazy programming, and it isn't necessarily the best solution for all use cases.)

    We think the discussion in this month's article shows, once again, that JSF provides a flexible, powerful, and pluggable framework for Web application development. 
    In addition to standard converters and validators, JSF facilitates custom implementations to accommodate both application and framework developers alike. Ultimately, the conversion and validation strategy you choose is up to you. 

    JSF allows you to easily and quickly get started (standard converters, validators, inline validation) during prototyping, and migrate to more sophisticated production solutions (custom objects, custom messages) during later development phases. 

    And throughout it all, the JSF application lifecycle provides a reliable infrastructure for consistently ensuring data-model integrity.

    We'll wrap up this series next month, with an in-depth look at writing your own custom components in JSF.
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved