diff --git a/spring-framework-reference/src/validation.xml b/spring-framework-reference/src/validation.xml index 916318fe445..5f4e4e575e2 100644 --- a/spring-framework-reference/src/validation.xml +++ b/spring-framework-reference/src/validation.xml @@ -9,43 +9,56 @@ Introduction There are pros and cons for considering validation as business logic, - and Spring offers a design for validation (and data binding) that - does not exclude either one of them. Specifically validation should not be - tied to the web tier, should be easy to localize and it should be - possible to plug in any validator available. Considering the above, Spring - has come up with a Validator interface that - is both basic and eminently usable in every layer of an application. + and Spring offers a design for validation (and data binding) that does not + exclude either one of them. Specifically validation should not be tied to + the web tier, should be easy to localize and it should be possible to plug + in any validator available. Considering the above, Spring has come up with + a Validator interface that is both basic + ands eminently usable in every layer of an application. - Data binding is useful for allowing user input to be dynamically - bound to the domain model of an application (or whatever objects you use - to process user input). Spring provides the so-called - DataBinder to do exactly that. The - Validator and the - DataBinder make up the validation package, - which is primarily used in but not limited to the MVC framework. + Data binding is useful for allowing user input to be dynamically bound + to the domain model of an application (or whatever objects you use to + process user input). Spring provides the so-called + DataBinder to do exactly that. The + Validator and the + DataBinder make up the + validation package, which is primarily used in but not + limited to the MVC framework. - The BeanWrapper is a fundamental concept in the - Spring Framework and is used in a lot of places. However, you probably - will not have the need to use the BeanWrapper directly. Because this - is reference documentation however, we felt that some explanation might be - in order. We will explain the BeanWrapper in this chapter since, if you were - going to use it at all, you would most likely do so when trying to bind data to objects. + The BeanWrapper is a fundamental + concept in the Spring Framework and is used in a lot of places. However, + you probably will not have the need to use the + BeanWrapper directly. Because this is + reference documentation however, we felt that some explanation might be in + order. We will explain the BeanWrapper in + this chapter since, if you were going to use it at all, you would most + likely do so when trying to bind data to objects. - Spring's DataBinder and the lower-level BeanWrapper both use PropertyEditors to parse and format property values. - The PropertyEditor concept is part of the JavaBeans specification, and is also explained in this chapter. - Spring 3 introduces a "core.convert" package that provides a general type conversion facility, as well as a higher-level "format" package for formatting UI field values. - These new packages may be used as simpler alternatives to PropertyEditors, and will also be discussed in this chapter. - + Spring's DataBinder and the lower-level BeanWrapper both use + PropertyEditors to parse and format property values. The + PropertyEditor concept is part of the + JavaBeans specification, and is also explained in this chapter. Spring 3 + introduces a "core.convert" package that provides a general type + conversion facility, as well as a higher-level "format" package for + formatting UI field values. These new packages may be used as simpler + alternatives to PropertyEditors, and will also be discussed in this + chapter. -
- Validation using Spring's <interfacename>Validator</interfacename> interface - Spring features a Validator interface that you can - use to validate objects. The Validator interface works using - an Errors object so that while validating, validators can report - validation failures to the Errors object. - Let's consider a small data object: - + Validation using Spring's <interfacename>Validator</interfacename> + interface + + Spring features a Validator interface + that you can use to validate objects. The + Validator interface works using an + Errors object so that while validating, + validators can report validation failures to the + Errors object. + + Let's consider a small data object: + + // the usual getters and setters... - We're going to provide validation behavior for the Person - class by implementing the following two methods of the - org.springframework.validation.Validator interface: - - - supports(Class) - Can this - Validator validate instances of the supplied - Class? - - - validate(Object, org.springframework.validation.Errors) - - validates the given object and in case of validation errors, registers - those with the given Errors object - - - - - Implementing a Validator is fairly straightforward, - especially when you know of the ValidationUtils helper class - that the Spring Framework also provides. - We're going to provide validation behavior for the + Person class by implementing the following two + methods of the + org.springframework.validation.Validator + interface: + + supports(Class) - Can this + Validator validate instances of the + supplied Class? + + + validate(Object, + org.springframework.validation.Errors) - validates the + given object and in case of validation errors, registers those with + the given Errors object + + + + Implementing a Validator is fairly + straightforward, especially when you know of the + ValidationUtils helper class that the Spring + Framework also provides. + + /** * This Validator validates just Person instances */ - As you can see, the static rejectIfEmpty(..) - method on the ValidationUtils class is used to reject the - 'name' property if it is null or the empty string. - Have a look at the Javadoc for the ValidationUtils class to see - what functionality it provides besides the example shown previously. - While it is certainly possible to implement a single - Validator class to validate each of the nested objects - in a rich object, it may be better to encapsulate the validation logic for each nested - class of object in its own Validator implementation. A - simple example of a 'rich' object would be a - Customer that is composed of two String - properties (a first and second name) and a complex Address object. - Address objects may be used independently of - Customer objects, and so a distinct - AddressValidator has been implemented. If you want your - CustomerValidator to reuse the logic contained within the - AddressValidator class without resorting to copy-and-paste, - you can dependency-inject or instantiate an AddressValidator - within your CustomerValidator, and use it like so: - As you can see, the static + rejectIfEmpty(..) method on the + ValidationUtils class is used to reject the + 'name' property if it is null or the + empty string. Have a look at the Javadoc for the + ValidationUtils class to see what functionality it + provides besides the example shown previously. - public CustomerValidator(Validator addressValidator) { - if (addressValidator == null) { - throw new IllegalArgumentException( - "The supplied [Validator] is required and must not be null."); - } - if (!addressValidator.supports(Address.class)) { - throw new IllegalArgumentException( - "The supplied [Validator] must support the validation of [Address] instances."); - } - this.addressValidator = addressValidator; - } + While it is certainly possible to implement a single + Validator class to validate each of the + nested objects in a rich object, it may be better to encapsulate the + validation logic for each nested class of object in its own + Validator implementation. A simple example + of a 'rich' object would be a + Customer that is composed of two + String properties (a first and second name) and a + complex Address object. + Address objects may be used independently of + Customer objects, and so a distinct + AddressValidator has been implemented. If you want + your CustomerValidator to reuse the logic contained + within the AddressValidator class without resorting + to copy-and-paste, you can dependency-inject or instantiate an + AddressValidator within your + CustomerValidator, and use it like so: + + /** * This Validator validates Customer instances, and any subclasses of Customer too */ - Validation errors are reported to the Errors - object passed to the validator. In case of Spring Web MVC you can use - <spring:bind/> tag to inspect the error messages, but - of course you can also inspect the errors object yourself. More information about - the methods it offers can be found from the Javadoc. -
-
- Resolving codes to error messages - We've talked about databinding and validation. Outputting messages corresponding to - validation errors is the last thing we need to discuss. In the example we've shown - above, we rejected the name and the age field. - If we're going to output the error messages by using a MessageSource, - we will do so using the error code we've given when rejecting the field ('name' and 'age' - in this case). When you call (either directly, or indirectly, using for example the - ValidationUtils class) rejectValue or one of - the other reject methods from the Errors - interface, the underlying implementation will not only register the code you've - passed in, but also a number of additional error codes. What error codes it registers - is determined by the MessageCodesResolver that is used. - By default, the DefaultMessageCodesResolver is used, which for example - not only registers a message with the code you gave, but also messages that include the - field name you passed to the reject method. So in case you reject a field using - rejectValue("age", "too.darn.old"), apart from the - too.darn.old code, Spring will also register - too.darn.old.age and too.darn.old.age.int - (so the first will include the field name and the second will include the type of the - field); this is done as a convenience to aid developers in targeting error - messages and suchlike. - More information on the MessageCodesResolver and the default - strategy can be found online with the Javadocs for - MessageCodesResolver - and - DefaultMessageCodesResolver - respectively. -
+ + Validation errors are reported to the + Errors object passed to the validator. In + case of Spring Web MVC you can use <spring:bind/> + tag to inspect the error messages, but of course you can also inspect the + errors object yourself. More information about the methods it offers can + be found from the Javadoc. + + +
+ Resolving codes to error messages + + We've talked about databinding and validation. Outputting messages + corresponding to validation errors is the last thing we need to discuss. + In the example we've shown above, we rejected the name + and the age field. If we're going to output the error + messages by using a MessageSource, we will + do so using the error code we've given when rejecting the field ('name' + and 'age' in this case). When you call (either directly, or indirectly, + using for example the ValidationUtils class) + rejectValue or one of the other + reject methods from the + Errors interface, the underlying + implementation will not only register the code you've passed in, but also + a number of additional error codes. What error codes it registers is + determined by the MessageCodesResolver that + is used. By default, the + DefaultMessageCodesResolver is used, which for + example not only registers a message with the code you gave, but also + messages that include the field name you passed to the reject method. So + in case you reject a field using rejectValue("age", + "too.darn.old"), apart from the too.darn.old + code, Spring will also register too.darn.old.age and + too.darn.old.age.int (so the first will include the + field name and the second will include the type of the field); this is + done as a convenience to aid developers in targeting error messages and + suchlike. + + More information on the + MessageCodesResolver and the default + strategy can be found online with the Javadocs for MessageCodesResolver and DefaultMessageCodesResolver respectively. +
- Bean manipulation and the <interfacename>BeanWrapper</interfacename> + Bean manipulation and the + <interfacename>BeanWrapper</interfacename> The org.springframework.beans package adheres to - the JavaBeans standard provided by Sun. A JavaBean is simply a class with - a default no-argument constructor, which follows a naming convention - where (by way of an example) a property named bingoMadness would have a setter - method setBingoMadness(..) and a getter method getBingoMadness(). - For more information about JavaBeans and the specification, please refer - to Sun's website ( java.sun.com/products/javabeans). + the JavaBeans standard provided by Sun. A JavaBean is simply a class with + a default no-argument constructor, which follows a naming convention where + (by way of an example) a property named bingoMadness + would have a setter method setBingoMadness(..) + and a getter method getBingoMadness(). For more + information about JavaBeans and the specification, please refer to Sun's + website ( java.sun.com/products/javabeans). One quite important class in the beans package is the - BeanWrapper interface and its corresponding - implementation (BeanWrapperImpl). As quoted from the - Javadoc, the BeanWrapper offers functionality to set and get property - values (individually or in bulk), get property descriptors, and to query - properties to determine if they are readable or writable. Also, the - BeanWrapper offers support for nested properties, enabling the setting of - properties on sub-properties to an unlimited depth. Then, the BeanWrapper - supports the ability to add standard JavaBeans - PropertyChangeListeners and - VetoableChangeListeners, without the need for - supporting code in the target class. Last but not least, the BeanWrapper - provides support for the setting of indexed properties. The BeanWrapper - usually isn't used by application code directly, but by the - DataBinder and the - BeanFactory. + BeanWrapper interface and its corresponding + implementation (BeanWrapperImpl). As quoted from + the Javadoc, the BeanWrapper offers + functionality to set and get property values (individually or in bulk), + get property descriptors, and to query properties to determine if they are + readable or writable. Also, the BeanWrapper + offers support for nested properties, enabling the setting of properties + on sub-properties to an unlimited depth. Then, the + BeanWrapper supports the ability to add + standard JavaBeans PropertyChangeListeners + and VetoableChangeListeners, without the + need for supporting code in the target class. Last but not least, the + BeanWrapper provides support for the + setting of indexed properties. The + BeanWrapper usually isn't used by + application code directly, but by the + DataBinder and the + BeanFactory. - The way the BeanWrapper works is partly indicated by its name: - it wraps a bean to perform actions on that bean, like - setting and retrieving properties. + The way the BeanWrapper works is partly + indicated by its name: it wraps a bean to perform + actions on that bean, like setting and retrieving properties.
Setting and getting basic and nested properties Setting and getting properties is done using the - setPropertyValue(s) and - getPropertyValue(s) methods that both come with a - couple of overloaded variants. They're all described in more detail in - the Javadoc Spring comes with. What's important to know is that there - are a couple of conventions for indicating properties of an object. A - couple of examples: - - Examples of properties + setPropertyValue(s) and + getPropertyValue(s) methods that both come with a + couple of overloaded variants. They're all described in more detail in + the Javadoc Spring comes with. What's important to know is that there + are a couple of conventions for indicating properties of an object. A + couple of examples: - - - - - - Expression - Explanation - - +
+ Examples of properties - - - name + + + + + + Expression + Explanation + + - Indicates the property name - corresponding to the methods getName() or - isName() and + + + name + + Indicates the property name + corresponding to the methods getName() + or isName() and setName(..) - + - - account.name + + account.name - Indicates the nested property name - of the property account corresponding e.g. - to the methods getAccount().setName() or + Indicates the nested property name of + the property account corresponding e.g. to + the methods getAccount().setName() or getAccount().getName() - + - - account[2] + + account[2] - Indicates the third element of the - indexed property account. Indexed - properties can be of type array, - list or other naturally - ordered collection - + Indicates the third element of the + indexed property account. Indexed properties + can be of type array, list + or other naturally ordered + collection + - - account[COMPANYNAME] + + account[COMPANYNAME] - Indicates the value of the map entry indexed by the key + Indicates the value of the map entry indexed by the key COMPANYNAME of the Map property account - - - -
+ + + + - Below you'll find some examples of working with the BeanWrapper to - get and set properties. + Below you'll find some examples of working with the + BeanWrapper to get and set + properties. - (This next section is not vitally important to you if you're not - planning to work with the BeanWrapper directly. If you're - just using the DataBinder and the - BeanFactory and their out-of-the-box implementation, you - should skip ahead to the section about - PropertyEditors.) + (This next section is not vitally important to you if + you're not planning to work with the + BeanWrapper directly. If you're just + using the DataBinder and the + BeanFactory and their out-of-the-box + implementation, you should skip ahead to the section about + PropertyEditors.) Consider the following two classes: - - The following code snippets show some examples of how to retrieve - and manipulate some of the properties of instantiated - Companies and Employees: + and manipulate some of the properties of instantiated + Companies and Employees: + // setting the company name..
- Built-in <interface>PropertyEditor</interface> implementations + Built-in <interface>PropertyEditor</interface> + implementations - Spring uses the concept of PropertyEditors to effect the conversion - between an Object and a String. If you think about it, - it sometimes might be handy to be able to represent properties in a different way than the object itself. - For example, a Date can be represented in a human readable way (as the - String '2007-14-09'), while we're still able to convert the - human readable form back to the original date (or even better: convert any date entered in a human readable - form, back to Date objects). This behavior can be achieved by - registering custom editors, of type java.beans.PropertyEditor. - Registering custom editors on a BeanWrapper or alternately in a specific IoC - container as mentioned in the previous chapter, gives it the knowledge of how to convert properties to the - desired type. Read more about PropertyEditors in the Javadoc of the - java.beans package provided by Sun. + Spring uses the concept of PropertyEditors to + effect the conversion between an Object and a + String. If you think about it, it sometimes might + be handy to be able to represent properties in a different way than the + object itself. For example, a Date can be + represented in a human readable way (as the + String '2007-14-09'), while + we're still able to convert the human readable form back to the original + date (or even better: convert any date entered in a human readable form, + back to Date objects). This behavior can be + achieved by registering custom editors, of type + java.beans.PropertyEditor. Registering + custom editors on a BeanWrapper or + alternately in a specific IoC container as mentioned in the previous + chapter, gives it the knowledge of how to convert properties to the + desired type. Read more about + PropertyEditors in the Javadoc of the + java.beans package provided by Sun. - A couple of examples where property editing is used in Spring: - - - setting properties on beans is done - using PropertyEditors. When mentioning - java.lang.String as the value of a property of - some bean you're declaring in XML file, Spring will (if the setter - of the corresponding property has a Class-parameter) use the - ClassEditor to try to resolve the parameter to - a Class object. - + A couple of examples where property editing is used in Spring: + + + setting properties on beans is done using + PropertyEditors. When mentioning + java.lang.String as the value of a property of + some bean you're declaring in XML file, Spring will (if the setter + of the corresponding property has a + Class-parameter) use the + ClassEditor to try to resolve the parameter + to a Class object. + - - parsing HTTP request parameters in - Spring's MVC framework is done using all kinds of PropertyEditors - that you can manually bind in all subclasses of the - CommandController. - - - + + parsing HTTP request parameters in Spring's + MVC framework is done using all kinds of + PropertyEditors that you can manually bind in all + subclasses of the CommandController. + + - Spring has a number of built-in PropertyEditors to make life easy. - Each of those is listed below and they are all located in the - org.springframework.beans.propertyeditors package. Most, but not all (as indicated below), - are registered by default by BeanWrapperImpl. Where the property editor is configurable - in some fashion, you can of course still register your own variant to override the default one: + Spring has a number of built-in PropertyEditors + to make life easy. Each of those is listed below and they are all + located in the + org.springframework.beans.propertyeditors package. + Most, but not all (as indicated below), are registered by default by + BeanWrapperImpl. Where the property editor is + configurable in some fashion, you can of course still register your own + variant to override the default one: - Built-in <literal>PropertyEditors</literal> + Built-in <literal>PropertyEditors</literal> - - - + + + - - - Class - Explanation - - + + + Class + Explanation + + - - - ByteArrayPropertyEditor + + + ByteArrayPropertyEditor - Editor for byte arrays. Strings will simply be - converted to their corresponding byte representations. - Registered by default by BeanWrapperImpl. - + Editor for byte arrays. Strings will simply be converted to + their corresponding byte representations. Registered by default + by BeanWrapperImpl. + - - ClassEditor + + ClassEditor - Parses Strings representing classes to actual classes - and the other way around. When a class is not found, an - IllegalArgumentException is thrown. Registered by default by + Parses Strings representing classes to actual classes and + the other way around. When a class is not found, an + IllegalArgumentException is thrown. + Registered by default by BeanWrapperImpl. - + - - CustomBooleanEditor + + CustomBooleanEditor - Customizable property editor for Boolean properties. - Registered by default by BeanWrapperImpl, but, can be + Customizable property editor for + Boolean properties. Registered by default + by BeanWrapperImpl, but, can be overridden by registering custom instance of it as custom editor. - - - CustomCollectionEditor - Property editor for Collections, converting any source - Collection to a given target Collection type. - - - CustomDateEditor + + + CustomCollectionEditor + Property editor for Collections, converting any source + Collection to a given target + Collection type. + + + CustomDateEditor - Customizable property editor for java.util.Date, - supporting a custom DateFormat. NOT registered by default. Must - be user registered as needed with appropriate format. - + Customizable property editor for java.util.Date, supporting + a custom DateFormat. NOT registered by default. Must be user + registered as needed with appropriate format. + - - CustomNumberEditor + + CustomNumberEditor - Customizable property editor for any Number subclass - like Integer, Long, - Float, Double. Registered - by default by BeanWrapperImpl, but can be - overridden by registering custom instance of it as a custom editor. - + Customizable property editor for any Number subclass like + Integer, Long, + Float, Double. + Registered by default by BeanWrapperImpl, + but can be overridden by registering custom instance of it as a + custom editor. + - - FileEditor + + FileEditor - Capable of resolving Strings to - java.io.File objects. Registered by default by - BeanWrapperImpl. - + Capable of resolving Strings to + java.io.File objects. Registered by + default by BeanWrapperImpl. + - - InputStreamEditor + + InputStreamEditor - One-way property editor, capable of taking a text - string and producing (via an intermediate ResourceEditor and + One-way property editor, capable of taking a text string + and producing (via an intermediate + ResourceEditor and Resource) an - InputStream, so InputStream - properties may be directly set as Strings. Note that the default usage - will not close the InputStream for - you! Registered by default by BeanWrapperImpl. - + InputStream, so + InputStream properties may be + directly set as Strings. Note that the default usage will not + close the InputStream for you! + Registered by default by + BeanWrapperImpl. + - - LocaleEditor + + LocaleEditor - Capable of resolving Strings to + Capable of resolving Strings to Locale objects and vice versa (the String format is [language]_[country]_[variant], which is the same thing the toString() method of Locale provides). Registered by default by BeanWrapperImpl. - + - - PatternEditor + + PatternEditor - Capable of resolving Strings to JDK 1.5 + Capable of resolving Strings to JDK 1.5 Pattern objects and vice versa. - + - - PropertiesEditor + + PropertiesEditor - Capable of converting Strings (formatted using the - format as defined in the Javadoc for the java.lang.Properties - class) to Properties objects. Registered by - default by BeanWrapperImpl. - + Capable of converting Strings (formatted using the format + as defined in the Javadoc for the java.lang.Properties class) to + Properties objects. Registered by default + by BeanWrapperImpl. + - - StringTrimmerEditor + + StringTrimmerEditor - Property editor that trims Strings. Optionally allows - transforming an empty string into a null value. NOT - registered by default; must be user registered as needed. - + Property editor that trims Strings. Optionally allows + transforming an empty string into a null + value. NOT registered by default; must be user registered as + needed. + - - URLEditor + + URLEditor - Capable of resolving a String representation of a URL - to an actual URL object. Registered by - default by BeanWrapperImpl. - - - -
+ Capable of resolving a String representation of a URL to an + actual URL object. Registered by default + by BeanWrapperImpl. + + + + - - Spring uses the java.beans.PropertyEditorManager to set - the search path for property editors that might be needed. The search path also includes - sun.bean.editors, which includes - PropertyEditor implementations for types such as - Font, Color, and most of the primitive types. - Note also that the standard JavaBeans infrastructure will automatically discover - PropertyEditor classes (without you having to register them - explicitly) if they are in the same package as the class they handle, and have the same name - as that class, with 'Editor' appended; for example, one could have the - following class and package structure, which would be sufficient for the - FooEditor class to be recognized and used as the - PropertyEditor for Foo-typed - properties. - - Spring uses the + java.beans.PropertyEditorManager to set + the search path for property editors that might be needed. The search + path also includes sun.bean.editors, which includes + PropertyEditor implementations for types + such as Font, Color, and + most of the primitive types. Note also that the standard JavaBeans + infrastructure will automatically discover + PropertyEditor classes (without you + having to register them explicitly) if they are in the same package as + the class they handle, and have the same name as that class, with + 'Editor' appended; for example, one could have the + following class and package structure, which would be sufficient for the + FooEditor class to be recognized and used as the + PropertyEditor for + Foo-typed properties. + // the PropertyEditor for the Foo class - Note that you can also use the standard BeanInfo JavaBeans - mechanism here as well (described - in not-amazing-detail here). - Find below an example of using the BeanInfo mechanism for - explicitly registering one or more PropertyEditor instances - with the properties of an associated class. - Note that you can also use the standard + BeanInfo JavaBeans mechanism here as well + (described in not-amazing-detail here). Find below an example of using the + BeanInfo mechanism for explicitly + registering one or more PropertyEditor + instances with the properties of an associated class. + // the BeanInfo for the Foo class - - Here is the Java source code for the referenced FooBeanInfo class. This - would associate a CustomNumberEditor with the age - property of the Foo class. - - Here is the Java source code for the referenced + FooBeanInfo class. This would associate a + CustomNumberEditor with the + age property of the Foo class. + + +
+ Registering additional custom + <interfacename>PropertyEditors</interfacename> -
- Registering additional custom <interfacename>PropertyEditors</interfacename> + When setting bean properties as a string value, a Spring IoC + container ultimately uses standard JavaBeans + PropertyEditors to convert these Strings to the + complex type of the property. Spring pre-registers a number of custom + PropertyEditors (for example, to convert a + classname expressed as a string into a real + Class object). Additionally, Java's standard + JavaBeans PropertyEditor lookup + mechanism allows a PropertyEditor for a class + simply to be named appropriately and placed in the same package as the + class it provides support for, to be found automatically. - When setting bean properties as a string value, a Spring IoC container - ultimately uses standard JavaBeans PropertyEditors to convert these - Strings to the complex type of the property. Spring pre-registers a number - of custom PropertyEditors (for example, to convert a classname expressed - as a string into a real Class object). Additionally, Java's standard - JavaBeans PropertyEditor lookup mechanism allows a - PropertyEditor for a class simply to be named appropriately and - placed in the same package as the class it provides support for, to be found automatically. - If there is a need to register other custom PropertyEditors, there - are several mechanisms available. The most manual approach, which is not normally convenient or - recommended, is to simply use the registerCustomEditor() method of the - ConfigurableBeanFactory interface, assuming you have a - BeanFactory reference. Another, slightly more convenient, mechanism is to use - a special bean factory post-processor called CustomEditorConfigurer. - Although bean factory post-processors can be used with BeanFactory - implementations, the CustomEditorConfigurer has a nested property setup, so it is - strongly recommended that it is used with the ApplicationContext, where - it may be deployed in similar fashion to any other bean, and automatically detected and applied. - Note that all bean factories and application contexts automatically use a number of built-in property - editors, through their use of something called a BeanWrapper to handle - property conversions. The standard property editors that the BeanWrapper - registers are listed in the previous section. Additionally, - ApplicationContexts also override or add an additional number of editors - to handle resource lookups in a manner appropriate to the specific application context type. + If there is a need to register other custom + PropertyEditors, there are several mechanisms + available. The most manual approach, which is not normally convenient + or recommended, is to simply use the + registerCustomEditor() method of the + ConfigurableBeanFactory interface, + assuming you have a BeanFactory + reference. Another, slightly more convenient, mechanism is to use a + special bean factory post-processor called + CustomEditorConfigurer. Although bean factory + post-processors can be used with + BeanFactory implementations, the + CustomEditorConfigurer has a nested property + setup, so it is strongly recommended that it is used with the + ApplicationContext, where it may be + deployed in similar fashion to any other bean, and automatically + detected and applied. - Standard JavaBeans PropertyEditor instances are used to convert - property values expressed as strings to the actual complex type of the property. - CustomEditorConfigurer, a bean factory post-processor, may be used to conveniently - add support for additional PropertyEditor instances to an - ApplicationContext. - Consider a user class ExoticType, and another class - DependsOnExoticType which needs ExoticType set as a property: + Note that all bean factories and application contexts + automatically use a number of built-in property editors, through their + use of something called a BeanWrapper + to handle property conversions. The standard property editors that the + BeanWrapper registers are listed in + the previous section. + Additionally, ApplicationContexts also override or + add an additional number of editors to handle resource lookups in a + manner appropriate to the specific application context type. + + Standard JavaBeans PropertyEditor + instances are used to convert property values expressed as strings to + the actual complex type of the property. + CustomEditorConfigurer, a bean factory + post-processor, may be used to conveniently add support for additional + PropertyEditor instances to an + ApplicationContext. + + Consider a user class ExoticType, and + another class DependsOnExoticType which needs + ExoticType set as a property: + + - When things are properly set up, we want to be able to assign the type property as a string, which a - PropertyEditor will behind the scenes convert into an actual - ExoticType instance: - + + When things are properly set up, we want to be able to assign the + type property as a string, which a + PropertyEditor will behind the scenes + convert into an actual ExoticType + instance: + + ]]> - The PropertyEditor implementation could look similar to this: - // converts string representation to ExoticType objectThe PropertyEditor implementation + could look similar to this: + // converts string representation to ExoticType object - Finally, we use CustomEditorConfigurer to register the new - PropertyEditor with the ApplicationContext, - which will then be able to use it as needed: - + + Finally, we use CustomEditorConfigurer to + register the new PropertyEditor with + the ApplicationContext, which will then + be able to use it as needed: + + @@ -651,29 +749,44 @@ public class ExoticTypeEditor extends PropertyEditorSupport { ]]> -
- Using <interfacename>PropertyEditorRegistrars</interfacename> +
+ Using + <interfacename>PropertyEditorRegistrars</interfacename> - Another mechanism for registering property editors with the Spring container is to create and use - a PropertyEditorRegistrar. This interface is particularly useful when you - need to use the same set of property editors in several different situations: write a corresponding - registrar and reuse that in each case. PropertyEditorRegistrars work in conjunction - with an interface called PropertyEditorRegistry, an interface - that is implemented by the Spring BeanWrapper (and - DataBinder). PropertyEditorRegistrars are particularly - convenient when used in conjunction with the CustomEditorConfigurer - (introduced here), which exposes a - property called setPropertyEditorRegistrars(..): - PropertyEditorRegistrars added to a CustomEditorConfigurer in this - fashion can easily be shared with DataBinder and Spring MVC - Controllers. Furthermore, it avoids the need for synchronization on custom - editors: a PropertyEditorRegistrar is expected to create fresh - PropertyEditor instances for each bean creation attempt. - Using a PropertyEditorRegistrar is perhaps best illustrated with an - example. First off, you need to create your own PropertyEditorRegistrar - implementation: + Another mechanism for registering property editors with the + Spring container is to create and use a + PropertyEditorRegistrar. This + interface is particularly useful when you need to use the same set + of property editors in several different situations: write a + corresponding registrar and reuse that in each case. + PropertyEditorRegistrars work in conjunction with + an interface called + PropertyEditorRegistry, an interface + that is implemented by the Spring + BeanWrapper (and + DataBinder). + PropertyEditorRegistrars are particularly + convenient when used in conjunction with the + CustomEditorConfigurer (introduced here), which exposes a property called + setPropertyEditorRegistrars(..): + PropertyEditorRegistrars added to a + CustomEditorConfigurer in this fashion can + easily be shared with DataBinder and + Spring MVC Controllers. Furthermore, + it avoids the need for synchronization on custom editors: a + PropertyEditorRegistrar is expected + to create fresh PropertyEditor + instances for each bean creation attempt. - Using a PropertyEditorRegistrar + is perhaps best illustrated with an example. First off, you need to + create your own + PropertyEditorRegistrar + implementation: + + // you could register as many custom property editors as are required here... - See also the org.springframework.beans.support.ResourceEditorRegistrar for an - example PropertyEditorRegistrar implementation. Notice how in its - implementation of the registerCustomEditors(..) method it creates new instances - of each property editor. - Next we configure a CustomEditorConfigurer and inject an - instance of our CustomPropertyEditorRegistrar into it: - + + See also the + org.springframework.beans.support.ResourceEditorRegistrar + for an example + PropertyEditorRegistrar + implementation. Notice how in its implementation of the + registerCustomEditors(..) method it creates + new instances of each property editor. + + Next we configure a + CustomEditorConfigurer and inject an instance + of our CustomPropertyEditorRegistrar into + it: + @@ -701,14 +821,19 @@ public final class CustomPropertyEditorRegistrar implements PropertyEditorRegist ]]> - Finally, and in a bit of a departure from the focus of this chapter, for those of you using - Spring's MVC web framework, using PropertyEditorRegistrars - in conjunction with data-binding Controllers (such as - SimpleFormController) can be very convenient. Find below an example of using a - PropertyEditorRegistrar in the implementation of an initBinder(..) - method: + Finally, and in a bit of a departure from the focus of this + chapter, for those of you using Spring's MVC web + framework, using + PropertyEditorRegistrars in + conjunction with data-binding + Controllers (such as + SimpleFormController) can be very convenient. + Find below an example of using a + PropertyEditorRegistrar in the + implementation of an initBinder(..) + method: - // other methods to do with registering a User - This style of PropertyEditor registration can lead to concise code (the - implementation of initBinder(..) is just one line long!), and allows common - PropertyEditor registration code to be encapsulated in a class and then - shared amongst as many Controllers as needed. - -
- -
- + This style of PropertyEditor + registration can lead to concise code (the implementation of + initBinder(..) is just one line long!), and + allows common PropertyEditor + registration code to be encapsulated in a class and then shared + amongst as many Controllers as + needed. +
+
-
- Spring 3 Type Conversion - - Spring 3 introduces a core.convert package that provides a general type conversion system. - The system defines an SPI to implement type conversion logic, as well as an API to execute type conversions at runtime. - Within a Spring container, this system can be used as an alternative to PropertyEditors to convert externalized bean property value strings to required property types. - The public API may also be used anywhere in your application where type conversion is needed. - -
- Converter SPI - - The SPI to implement type conversion logic is simple and strongly typed: - - + Spring 3 Type Conversion + + Spring 3 introduces a core.convert package that + provides a general type conversion system. The system defines an SPI to + implement type conversion logic, as well as an API to execute type + conversions at runtime. Within a Spring container, this system can be used + as an alternative to PropertyEditors to convert externalized bean property + value strings to required property types. The public API may also be used + anywhere in your application where type conversion is needed. + +
+ Converter SPI + + The SPI to implement type conversion logic is simple and strongly + typed: + + { - T convert(S source); - + T convert(S source); + }]]> - - To create your own Converter, simply implement the interface above. - Parameterize S as the type you are converting from, and T as the type you are converting to. - For each call to convert(S), the source argument is guaranteed to be NOT null. - Your Converter may throw any Exception if conversion fails. - An IllegalArgumentException should be thrown to report an invalid source value. - Take care to ensure your Converter implementation is thread-safe. - - - Several converter implementations are provided in the core.convert.support package as a convenience. - These include converters from Strings to Numbers and other common types. - Consider StringToInteger as an example Converter implementation: - - -package org.springframework.core.convert.support; - + + To create your own Converter, simply implement the interface above. + Parameterize S as the type you are converting from, and T as the type + you are converting to. For each call to convert(S), the source argument + is guaranteed to be NOT null. Your Converter may throw any Exception if + conversion fails. An IllegalArgumentException should be thrown to report + an invalid source value. Take care to ensure your Converter + implementation is thread-safe. + + Several converter implementations are provided in the + core.convert.support package as a convenience. + These include converters from Strings to Numbers and other common types. + Consider StringToInteger as an example Converter + implementation: + + package org.springframework.core.convert.support; + final class StringToInteger implements Converter<String, Integer> { public Integer convert(String source) { return Integer.valueOf(source); } - + } -
-
- ConverterFactory - - When you need to centralize the conversion logic for an entire class hierarchy, for example, when converting from String to java.lang.Enum objects, implement ConverterFactory: - - + +
+ ConverterFactory + + When you need to centralize the conversion logic for an entire + class hierarchy, for example, when converting from String to + java.lang.Enum objects, implement + ConverterFactory: + + { - Converter getConverter(Class targetType); - + Converter getConverter(Class targetType); + }]]> - - Parameterize S to be type you are converting from and R to be base type defining the range of classes you can convert to. - Then implement getConverter(Class<T>), where T is a subclass of R. - - - Consider the StringToEnum ConverterFactory as an example: - - Parameterize S to be type you are converting from and R to be base + type defining the range of classes you can convert + to. Then implement getConverter(Class<T>), where T is a subclass + of R. + + Consider the StringToEnum ConverterFactory + as an example: + + { @@ -813,26 +949,31 @@ final class StringToEnumConverterFactory implements ConverterFactory implements Converter { private Class enumType; - + public StringToEnumConverter(Class enumType) { this.enumType = enumType; } - + public T convert(String source) { return (T) Enum.valueOf(this.enumType, source.trim()); } } }]]> -
-
- GenericConverter - - When you require a sophisticated Converter implementation, consider the GenericConverter interface. - With a more flexible but less strongly typed signature, a GenericConverter supports converting between multiple source and target types. - In addition, a GenericConverter makes available source and target field context you can use when implementing your conversion logic. - Such context allows a type conversion to be driven by a field annotation, or generic information declared on a field signature. - - + +
+ GenericConverter + + When you require a sophisticated Converter implementation, consider + the GenericConverter interface. With a more flexible but less strongly + typed signature, a GenericConverter supports converting between multiple + source and target types. In addition, a GenericConverter makes available + source and target field context you can use when implementing your + conversion logic. Such context allows a type conversion to be driven by + a field annotation, or generic information declared on a field + signature. + + - - - To implement a GenericConverter, have getConvertibleTypes() return the supported source->target type pairs. - Then implement convert(Object, TypeDescriptor, TypeDescriptor) to implement your conversion logic. - The source TypeDescriptor provides access to the source field holding the value being converted. - The target TypeDescriptor provides access to the target field where the converted value will be set. - - - A good example of a GenericConverter is a converter that converts between a Java Array and a Collection. - Such an ArrayToCollectionConverter introspects the field that declares the target Collection type to resolve the Collection's element type. - This allows each element in the source array to be converted to the Collection element type before the Collection is set on the target field. - - - - Because GenericConverter is a more complex SPI interface, only use it when you need it. - Favor Converter or ConverterFactory for basic type conversion needs. - - -
- ConditionalGenericConverter - - Sometimes you only want a Converter to execute if a specific condition holds true. - For example, you might only want to execute a Converter if a specific annotation is present on the target field. - Or you might only want to execute a Converter if a specific method, such as static valueOf method, is defined on the target class. - ConditionalGenericConverter is an subinterface of GenericConverter that allows you to define such custom matching criteria: - - + + To implement a GenericConverter, have getConvertibleTypes() return + the supported source->target type pairs. Then implement + convert(Object, TypeDescriptor, TypeDescriptor) to implement your + conversion logic. The source TypeDescriptor provides access to the + source field holding the value being converted. The target + TypeDescriptor provides access to the target field where the converted + value will be set. + + A good example of a GenericConverter is a converter that converts + between a Java Array and a Collection. Such an + ArrayToCollectionConverter introspects the field that declares the + target Collection type to resolve the Collection's element type. This + allows each element in the source array to be converted to the + Collection element type before the Collection is set on the target + field. + + Because GenericConverter is a more complex SPI interface, only + use it when you need it. Favor Converter or ConverterFactory for basic + type conversion needs. + + +
+ ConditionalGenericConverter + + Sometimes you only want a Converter to execute if a specific + condition holds true. For example, you might only want to execute a + Converter if a specific annotation is present on the target field. Or + you might only want to execute a Converter if a specific method, such + as static valueOf method, is defined on the target class. + ConditionalGenericConverter is an subinterface of GenericConverter + that allows you to define such custom matching criteria: + + - - - A good example of a ConditionalGenericConverter is an EntityConverter that converts between an persistent entity identifier and an entity reference. - Such a EntityConverter might only match if the target entity type declares a static finder method e.g. findAccount(Long). - You would perform such a finder method check in the implementation of matches(TypeDescriptor, TypeDescriptor). - -
-
-
- ConversionService API - - The ConversionService defines a unified API for executing type conversion logic at runtime. - Converters are often executed behind this facade interface: - - + + A good example of a ConditionalGenericConverter is an + EntityConverter that converts between an persistent entity identifier + and an entity reference. Such a EntityConverter might only match if + the target entity type declares a static finder method e.g. + findAccount(Long). You would perform such a finder method check in the + implementation of matches(TypeDescriptor, TypeDescriptor). +
+
+ +
+ ConversionService API + + The ConversionService defines a unified API for executing type + conversion logic at runtime. Converters are often executed behind this + facade interface: + + sourceType, Class targetType); - + T convert(Object source, Class targetType); - + boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType); Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType); - + }]]> - - Most ConversionService implementations also implement ConverterRegistry, which provides an SPI for registering converters. - Internally, a ConversionService implementation delegates to its registered converters to carry out type conversion logic. - - - A robust ConversionService implementation is provided in the core.convert.support package. - GenericConversionService is the general-purpose implementation suitable for use in most environments. - ConversionServiceFactory provides a convenient factory for creating common ConversionService configurations. - -
-
- Configuring a ConversionService - - A ConversionService is a stateless object designed to be instantiated at application startup, then shared between multiple threads. - In a Spring application, you typically configure a ConversionService instance per Spring container (or ApplicationContext). - That ConversionService will be picked up by Spring and then used whenever a type conversion needs to be performed by the framework. - You may also inject this ConversionService into any of your beans and invoke it directly. - - - - If no ConversionService is registered with Spring, the original PropertyEditor-based system is used. - - - - To register a default ConversionService with Spring, add the following bean definition with id conversionService: - - Most ConversionService implementations also implement + ConverterRegistry, which provides an SPI for + registering converters. Internally, a ConversionService implementation + delegates to its registered converters to carry out type conversion + logic. + + A robust ConversionService implementation is provided in the + core.convert.support package. + GenericConversionService is the general-purpose + implementation suitable for use in most environments. + ConversionServiceFactory provides a convenient + factory for creating common ConversionService configurations. +
+ +
+ Configuring a ConversionService + + A ConversionService is a stateless object designed to be + instantiated at application startup, then shared between multiple + threads. In a Spring application, you typically configure a + ConversionService instance per Spring container (or ApplicationContext). + That ConversionService will be picked up by Spring and then used + whenever a type conversion needs to be performed by the framework. You + may also inject this ConversionService into any of your beans and invoke + it directly. + + If no ConversionService is registered with Spring, the original + PropertyEditor-based system is used. + + + To register a default ConversionService with Spring, add the + following bean definition with id conversionService: + ]]> - - - A default ConversionService can convert between strings, numbers, enums, collections, maps, and other common types. - To suppliment or override the default converters with your own custom converter(s), set the converters property. - Property values may implement either of the Converter, ConverterFactory, or GenericConverter interfaces. - - + + A default ConversionService can convert between strings, numbers, + enums, collections, maps, and other common types. To suppliment or + override the default converters with your own custom converter(s), set + the converters property. Property values may implement + either of the Converter, ConverterFactory, or GenericConverter + interfaces. + + @@ -944,13 +1106,15 @@ public interface ConversionService { ]]> -
-
- Using a ConversionService programatically - - To work with a ConversionService instance programatically, simply inject a reference to it like you would for any other bean: - - + +
+ Using a ConversionService programatically + + To work with a ConversionService instance programatically, simply + inject a reference to it like you would for any other bean: + + -
-
- -
- Spring 3 Field Formatting - - As discussed in the previous section, core.convert is a general-purpose type conversion system. - It provides a unified ConversionService API as well as a strongly-typed Converter SPI for implementing conversion logic from one type to another. - A Spring Container uses this system to bind bean property values. - In addition, both the Spring Expression Language (SpEL) and DataBinder use this system to bind field values. - For example, when SpEL needs to coerce a Short to a Long to complete an expression.setValue(Object bean, Object value) attempt, the core.convert system performs the coercion. - - - Now consider the type conversion requirements of a typical client environment such as a web or desktop application. - In such environments, you typically convert from String to support the client postback process, as well as back to String to support the view rendering process. - In addition, you often need to localize String values. - The more general core.convert Converter SPI does not address such formatting requirements directly. - To directly address them, Spring 3 introduces a convenient Formatter SPI that provides a simple and robust alternative to PropertyEditors for client environments. - - - In general, use the Converter SPI when you need to implement general-purpose type conversion logic; for example, for converting between a java.util.Date and and java.lang.Long. - Use the Formatter SPI when you're working in a client environment, such as a web application, and need to parse and print localized field values. - The ConversionService provides a unified type conversion API for both SPIs. - -
- Formatter SPI - - The Formatter SPI to implement field formatting logic is simple and strongly typed: - - +
+ +
+ Spring 3 Field Formatting + + As discussed in the previous section, core.convert is a general-purpose type + conversion system. It provides a unified ConversionService API as well as + a strongly-typed Converter SPI for implementing conversion logic from one + type to another. A Spring Container uses this system to bind bean property + values. In addition, both the Spring Expression Language (SpEL) and + DataBinder use this system to bind field values. For example, when SpEL + needs to coerce a Short to a + Long to complete an + expression.setValue(Object bean, Object value) + attempt, the core.convert system performs the coercion. + + Now consider the type conversion requirements of a typical client + environment such as a web or desktop application. In such environments, + you typically convert from String to support the + client postback process, as well as back to String to + support the view rendering process. In addition, you often need to + localize String values. The more general core.convert + Converter SPI does not address such formatting + requirements directly. To directly address them, Spring 3 introduces a + convenient Formatter SPI that provides a simple and robust alternative to + PropertyEditors for client environments. + + In general, use the Converter SPI when you need to implement + general-purpose type conversion logic; for example, for converting between + a java.util.Date and and java.lang.Long. Use the Formatter SPI when you're + working in a client environment, such as a web application, and need to + parse and print localized field values. The ConversionService provides a + unified type conversion API for both SPIs. + +
+ Formatter SPI + + The Formatter SPI to implement field formatting logic is simple and + strongly typed: + extends Printer, Parser { }]]> - - - Where Formatter extends from the Printer and Parser building-block interfaces: - - + + Where Formatter extends from the Printer and Parser building-block + interfaces: + { String print(T fieldValue, Locale locale); }]]> - - + { T parse(String clientValue, Locale locale) throws ParseException; }]]> - - - To create your own Formatter, simply implement the Formatter interface above. - Parameterize T to be the type of object you wish to format, for example, java.util.Date. - Implement the print operation to print an instance of T for display in the client locale. - Implement the parse operation to parse an instance of T from the formatted representation returned from the client locale. - Your Formatter should throw a ParseException or IllegalArgumentException if a parse attempt fails. - Take care to ensure your Formatter implementation is thread-safe. - - - Several Formatter implementations are provided in format subpackages as a convenience. - The number package provides a NumberFormatter, CurrencyFormatter, and PercentFormatter to format java.lang.Number objects using a java.text.NumberFormat. - The datetime package provides a DateFormatter to format java.util.Date objects with a java.text.DateFormat. - The datetime.joda package provides comprehensive datetime formatting support based on the Joda Time library. - - - Consider DateFormatter as an example Formatter implementation: - - + + To create your own Formatter, simply implement the Formatter + interface above. Parameterize T to be the type of object you wish to + format, for example, java.util.Date. Implement + the print operation to print an instance of T + for display in the client locale. Implement the + parse operation to parse an instance of T from + the formatted representation returned from the client locale. Your + Formatter should throw a ParseException or IllegalArgumentException if a + parse attempt fails. Take care to ensure your Formatter implementation + is thread-safe. + + Several Formatter implementations are provided in + format subpackages as a convenience. The + number package provides a NumberFormatter, + CurrencyFormatter, and PercentFormatter to format java.lang.Number + objects using a java.text.NumberFormat. The + datetime package provides a DateFormatter to format + java.util.Date objects with a java.text.DateFormat. The + datetime.joda package provides comprehensive + datetime formatting support based on the Joda Time library. + + Consider DateFormatter as an example + Formatter implementation: + + { private String pattern; - + public DateFormatter(String pattern) { this.pattern = pattern; } - + public String print(Date date, Locale locale) { if (date == null) { return ""; @@ -1062,51 +1247,57 @@ public final class DateFormatter implements Formatter { } }]]> - - The Spring team welcomes community-driven Formatter contributions; see http://jira.springframework.org to contribute. - -
-
- Annotation-driven Formatting - - As you will see, field formatting can be configured by field type or annotation. - To bind an Annotation to a formatter, implement AnnotationFormatterFactory: - - The Spring team welcomes community-driven Formatter contributions; + see http://jira.springframework.org to contribute. +
+ +
+ Annotation-driven Formatting + + As you will see, field formatting can be configured by field type + or annotation. To bind an Annotation to a formatter, implement + AnnotationFormatterFactory: + + { - Set> getFieldTypes(); - + Set> getFieldTypes(); + Printer getPrinter(A annotation, Class fieldType); - + Parser getParser(A annotation, Class fieldType); -}]]> - - - Parameterize A to be the field annotationType you wish to associate formatting logic with, for example org.springframework.format.annotation.DateTimeFormat. - Have getFieldTypes return the types of fields the annotation may be used on. - Have getPrinter return a Printer to print the value of an annotated field. - Have getParser return a Parser to parse a clientValue for an annotated field. - - - The example AnnotationFormatterFactory implementation below binds the @NumberFormat Annotation to a formatter. - This annotation allows either a number style or pattern to be specified: - - + + Parameterize A to be the field annotationType you wish to associate + formatting logic with, for example + org.springframework.format.annotation.DateTimeFormat. Have + getFieldTypes return the types of fields the + annotation may be used on. Have getPrinter + return a Printer to print the value of an annotated field. Have + getParser return a Parser to parse a + clientValue for an annotated field. + + The example AnnotationFormatterFactory implementation below binds + the @NumberFormat Annotation to a formatter. This annotation allows + either a number style or pattern to be specified: + + { public Set> getFieldTypes() { - return new HashSet>(asList(new Class[] { + return new HashSet>(asList(new Class[] { Short.class, Integer.class, Long.class, Float.class, Double.class, BigDecimal.class, BigInteger.class })); } - + public Printer getPrinter(NumberFormat annotation, Class fieldType) { return configureFormatterFrom(annotation, fieldType); } - + public Parser getParser(NumberFormat annotation, Class fieldType) { return configureFormatterFrom(annotation, fieldType); } @@ -1125,51 +1316,54 @@ public final class NumberFormatAnnotationFormatterFactory implements AnnotationF } } } -}]]> - - - To trigger formatting, simply annotate fields with @NumberFormat: - - + + To trigger formatting, simply annotate fields with @NumberFormat: + + - -
- Format Annotation API - - A portable format annotation API exists in the org.springframework.format.annotation package. - Use @NumberFormat to format java.lang.Number fields. - Use @DateTimeFormat to format java.util.Date, java.util.Calendar, java.util.Long, or Joda Time fields. - - - The example below uses @DateTimeFormat to format a java.util.Date as a ISO Date (yyyy-MM-dd): - - + +
+ Format Annotation API + + A portable format annotation API exists in the + org.springframework.format.annotation package. + Use @NumberFormat to format java.lang.Number fields. Use + @DateTimeFormat to format java.util.Date, java.util.Calendar, + java.util.Long, or Joda Time fields. + + The example below uses @DateTimeFormat to format a java.util.Date + as a ISO Date (yyyy-MM-dd): + + - -
-
-
- FormatterRegistry SPI - - At runtime, Formatters are registered in a FormatterRegistry. - The FormatterRegistry SPI allows you to configure Formatting rules centrally, instead of duplicating such configuration across your Controllers. - For example, you might want to enforce that all Date fields are formatted a certain way, or fields with a specific annotation are formatted in a certain way. - With a shared FormatterRegistry, you define these rules once and they are applied whenever formatting is needed. - - - Review the FormatterRegistry SPI below: - - +
+
+ +
+ FormatterRegistry SPI + + At runtime, Formatters are registered in a FormatterRegistry. The + FormatterRegistry SPI allows you to configure Formatting rules + centrally, instead of duplicating such configuration across your + Controllers. For example, you might want to enforce that all Date fields + are formatted a certain way, or fields with a specific annotation are + formatted in a certain way. With a shared FormatterRegistry, you define + these rules once and they are applied whenever formatting is needed. + + Review the FormatterRegistry SPI below: + + fieldType, Formatter formatter); void addFormatterForAnnotation(AnnotationFormatterFactory factory); - + }]]> - - As shown above, Formatters can be registered by fieldType or annotation. - FormattingConversionService is the implementation of FormatterRegistry suitable for most environments. - This implementation may be configured programatically, or declaratively as a Spring bean using FormattingConversionServiceFactoryBean. - Because this implemementation also implements ConversionService, it can be directly configured for use with Spring's DataBinder and the Spring Expression Language (SpEL). - -
-
- Configuring Formatting in Spring MVC - - In a Spring MVC application, you may configure a custom ConversionService instance explicity as an attribute of the annotation-driven element of the MVC namespace. - This ConversionService will then be used anytime a type conversion is required during Controller model binding. - If not configured explicitly, Spring MVC will automatically register default formatters and converters for common types such as numbers and dates. - - - To rely on default formatting rules, no custom configuration is required in your Spring MVC config XML: - - As shown above, Formatters can be registered by fieldType or + annotation. FormattingConversionService is the + implementation of FormatterRegistry suitable for + most environments. This implementation may be configured + programatically, or declaratively as a Spring bean using + FormattingConversionServiceFactoryBean. Because + this implemementation also implements + ConversionService, it can be directly configured + for use with Spring's DataBinder and the Spring Expression Language + (SpEL). +
+ +
+ Configuring Formatting in Spring MVC + + In a Spring MVC application, you may configure a custom + ConversionService instance explicity as an attribute of the + annotation-driven element of the MVC namespace. This + ConversionService will then be used anytime a type conversion is + required during Controller model binding. If not configured explicitly, + Spring MVC will automatically register default formatters and converters + for common types such as numbers and dates. + + To rely on default formatting rules, no custom configuration is + required in your Spring MVC config XML: + + - + -]]> - - - With this one-line of configuation, default formatters for Numbers and Date types will be installed, including support for the @NumberFormat and @DateTimeFormat annotations. - Full support for the Joda Time formatting library is also installed if Joda Time is present on the classpath. - - - To inject a ConversionService instance with custom formatters and converters registered, set the conversion-service attribute: - - + + With this one-line of configuation, default formatters for Numbers + and Date types will be installed, including support for the + @NumberFormat and @DateTimeFormat annotations. Full support for the Joda + Time formatting library is also installed if Joda Time is present on the + classpath. + + To inject a ConversionService instance with custom formatters and + converters registered, set the conversion-service attribute: + - + - + -]]> - - - A custom ConversionService instance is often constructed by a FactoryBean that internally registers custom Formatters and Converters programatically before the ConversionService is returned. - See FormattingConversionServiceFactoryBean for an example. - -
-
-
- Spring 3 Validation - - Spring 3 introduces several enhancements to its validation support. - First, the JSR-303 Bean Validation API is now fully supported. - Second, when used programatically, Spring's DataBinder can now validate objects as well as bind to them. - Third, Spring MVC now has support for declaratively validating @Controller inputs. - -
- Overview of the JSR-303 Bean Validation API - - JSR-303 standardizes validation constraint declaration and metadata for the Java platform. - Using this API, you annotate domain model properties with declarative validation constraints and the runtime enforces them. - There are a number of built-in constraints you can take advantage of. - You may also define your own custom constraints. - - - To illustrate, consider a simple PersonForm model with two properties: - - + + A custom ConversionService instance is often constructed by a + FactoryBean that internally registers custom Formatters and Converters + programatically before the ConversionService is returned. See + FormattingConversionServiceFactoryBean for an example. +
+
+ +
+ Spring 3 Validation + + Spring 3 introduces several enhancements to its validation support. + First, the JSR-303 Bean Validation API is now fully supported. Second, + when used programatically, Spring's DataBinder can now validate objects as + well as bind to them. Third, Spring MVC now has support for declaratively + validating @Controller inputs. + +
+ Overview of the JSR-303 Bean Validation API + + JSR-303 standardizes validation constraint declaration and metadata + for the Java platform. Using this API, you annotate domain model + properties with declarative validation constraints and the runtime + enforces them. There are a number of built-in constraints you can take + advantage of. You may also define your own custom constraints. + + To illustrate, consider a simple PersonForm model with two + properties: + + - - JSR-303 allows you to define declarative validation constraints against such properties: - - JSR-303 allows you to define declarative validation constraints + against such properties: + + - - When an instance of this class is validated by a JSR-303 Validator, these constraints will be enforced. - - - For general information on JSR-303, see the Bean Validation Specification. - For information on the specific capabilities of the default reference implementation, see the Hibernate Validator documentation. - To learn how to setup a JSR-303 implementation as a Spring bean, keep reading. - -
-
- Configuring a Bean Validation Implementation - - Spring provides full support for the JSR-303 Bean Validation API. - This includes convenient support for bootstrapping a JSR-303 implementation as a Spring bean. - This allows for a javax.validation.ValidatorFactory or javax.validation.Validator - to be injected wherever validation is needed in your application. - - - Use the LocalValidatorFactoryBean to configure a default JSR-303 Validator as a Spring bean: - - When an instance of this class is validated by a JSR-303 Validator, + these constraints will be enforced. + + For general information on JSR-303, see the Bean Validation + Specification. For information on the specific capabilities of + the default reference implementation, see the Hibernate Validator + documentation. To learn how to setup a JSR-303 implementation as a + Spring bean, keep reading. +
+ +
+ Configuring a Bean Validation Implementation + + Spring provides full support for the JSR-303 Bean Validation API. + This includes convenient support for bootstrapping a JSR-303 + implementation as a Spring bean. This allows for a + javax.validation.ValidatorFactory or + javax.validation.Validator to be injected wherever + validation is needed in your application. + + Use the LocalValidatorFactoryBean to + configure a default JSR-303 Validator as a Spring bean: + + ]]> - - - The basic configuration above will trigger JSR-303 to initialize using its default bootstrap mechanism. - A JSR-303 provider, such as Hibernate Validator, is expected to be present in the classpath and will be detected automatically. - -
- Injecting a Validator - - LocalValidatorFactoryBean implements both javax.validation.ValidatorFactory - and javax.validation.Validator, as well as Spring's org.springframework.validation.Validator. - You may inject a reference to either of these interfaces into beans that need to invoke validation logic. - - - Inject a reference to javax.validation.Validator if you prefer to work with the JSR-303 API directly: - - + + + The basic configuration above will trigger JSR-303 to initialize + using its default bootstrap mechanism. A JSR-303 provider, such as + Hibernate Validator, is expected to be present in the classpath and will + be detected automatically. + +
+ Injecting a Validator + + LocalValidatorFactoryBean implements both + javax.validation.ValidatorFactory and + javax.validation.Validator, as well as Spring's + org.springframework.validation.Validator. You may inject + a reference to either of these interfaces into beans that need to + invoke validation logic. + + Inject a reference to javax.validation.Validator if + you prefer to work with the JSR-303 API directly: + + import javax.validation.Validator; @Service @@ -1329,10 +1549,12 @@ public class MyService { @Autowired private Validator validator; - - Inject a reference to org.springframework.validation.Validator if your bean requires the Spring Validation API: - - Inject a reference to + org.springframework.validation.Validator if your bean + requires the Spring Validation API: + + -
-
- Configuring Custom Constraints - - Each JSR-303 validation constraint consists of two parts. - First, a @Constraint annotation that declares the constraint and its configurable properties. - Second, an implementation of the javax.validation.ConstraintValidator interface that implements the constraint's behavior. - To associate a declaration with an implementation, each @Constraint annotation references a corresponding ValidationConstraint implementation class. - At runtime, a ConstraintValidatorFactory instantiates the referenced implementation when the constraint annotation is encountered in your domain model. - - - By default, the LocalValidatorFactoryBean configures a SpringConstraintValidatorFactory that uses Spring to create ConstraintValidator instances. - This allows your custom ConstraintValidators to benefit from dependency injection like any other Spring bean. - - - Shown below is an example of a custom @Constraint declaration, followed by an associated ConstraintValidator implementation that uses Spring for dependency injection: - - + +
+ Configuring Custom Constraints + + Each JSR-303 validation constraint consists of two parts. First, + a @Constraint annotation that declares the constraint and its + configurable properties. Second, an implementation of the + javax.validation.ConstraintValidator interface that + implements the constraint's behavior. To associate a declaration with + an implementation, each @Constraint annotation references a + corresponding ValidationConstraint implementation class. At runtime, a + ConstraintValidatorFactory instantiates the referenced + implementation when the constraint annotation is encountered in your + domain model. + + By default, the LocalValidatorFactoryBean + configures a SpringConstraintValidatorFactory that uses + Spring to create ConstraintValidator instances. This allows your + custom ConstraintValidators to benefit from dependency injection like + any other Spring bean. + + Shown below is an example of a custom @Constraint declaration, + followed by an associated ConstraintValidator + implementation that uses Spring for dependency injection: + + - + + - - As you can see, a ConstraintValidator implementation may have its dependencies @Autowired like any other Spring bean. - -
-
- Additional Configuration Options - - The default LocalValidatorFactoryBean configuration should prove sufficient for most cases. - There are a number of other configuration options for various JSR-303 constructs, from message interpolation to traversal resolution. - See the JavaDocs of LocalValidatorFactoryBean for more information on these options. - -
-
-
- Configuring a DataBinder - - Since Spring 3, a DataBinder instance can be configured with a Validator. - Once configured, the Validator may be invoked by calling binder.validate(). - Any validation Errors are automatically added to the binder's BindingResult. - - - When working with the DataBinder programatically, this can be used to invoke validation logic after binding to a target object: - - Foo target = new Foo(); + + As you can see, a ConstraintValidator implementation may have its + dependencies @Autowired like any other Spring bean. +
+ +
+ Additional Configuration Options + + The default LocalValidatorFactoryBean + configuration should prove sufficient for most cases. There are a + number of other configuration options for various JSR-303 constructs, + from message interpolation to traversal resolution. See the JavaDocs + of LocalValidatorFactoryBean for more + information on these options. +
+
+ +
+ Configuring a DataBinder + + Since Spring 3, a DataBinder instance can be configured with a + Validator. Once configured, the Validator may be invoked by calling + binder.validate(). Any validation Errors are automatically + added to the binder's BindingResult. + + When working with the DataBinder programatically, this can be used + to invoke validation logic after binding to a target object: + + Foo target = new Foo(); DataBinder binder = new DataBinder(target); binder.setValidator(new FooValidator()); @@ -1411,41 +1648,46 @@ binder.validate(); // get BindingResult that includes any validation errors BindingResult results = binder.getBindingResult(); -
-
- Spring MVC 3 Validation - - Beginning with Spring 3, Spring MVC has the ability to automatically validate @Controller inputs. - In previous versions it was up to the developer to manually invoke validation logic. - -
- Triggering @Controller Input Validation - - To trigger validation of a @Controller input, simply annotate the input argument as @Valid: - - @Controller +
+ +
+ Spring MVC 3 Validation + + Beginning with Spring 3, Spring MVC has the ability to + automatically validate @Controller inputs. In previous versions it was + up to the developer to manually invoke validation logic. + +
+ Triggering @Controller Input Validation + + To trigger validation of a @Controller input, simply annotate the + input argument as @Valid: + + @Controller public class MyController { @RequestMapping("/foo", method=RequestMethod.POST) public void processFoo(@Valid Foo foo) { /* ... */ } - - Spring MVC will validate a @Valid object after binding so-long as an appropriate Validator has been configured. - - - - The @Valid annotation is part of the standard JSR-303 Bean Validation API, and is not a Spring-specific construct. - - -
-
- Configuring a Validator for use by Spring MVC - - The Validator instance invoked when a @Valid method argument is encountered may be configured in two ways. - First, you may call binder.setValidator(Validator) within a @Controller's @InitBinder callback. - This allows you to configure a Validator instance per @Controller class: - - Spring MVC will validate a @Valid object after binding so-long as + an appropriate Validator has been configured. + + The @Valid annotation is part of the standard JSR-303 Bean + Validation API, and is not a Spring-specific construct. + +
+ +
+ Configuring a Validator for use by Spring MVC + + The Validator instance invoked when a @Valid method argument is + encountered may be configured in two ways. First, you may call + binder.setValidator(Validator) within a @Controller's @InitBinder + callback. This allows you to configure a Validator instance per + @Controller class: + + - - Second, you may call setValidator(Validator) on the global WebBindingInitializer. - This allows you to configure a Validator instance across all @Controllers. - This can be achieved easily by using the Spring MVC namespace: - - Second, you may call setValidator(Validator) on the global + WebBindingInitializer. This allows you to configure a Validator + instance across all @Controllers. This can be achieved easily by using + the Spring MVC namespace: + + - + -]]> - -
-
- Configuring a JSR-303 Validator for use by Spring MVC - - With JSR-303, a single javax.validation.Validator instance typically validates all model objects that declare validation constraints. - To configure a JSR-303-backed Validator with Spring MVC, simply add a JSR-303 Provider, such as Hibernate Validator, to your classpath. - Spring MVC will detect it and automatically enable JSR-303 support across all Controllers. - - - The Spring MVC configuration required to enable JSR-303 support is shown below: - - +
+ +
+ Configuring a JSR-303 Validator for use by Spring MVC + + With JSR-303, a single javax.validation.Validator + instance typically validates all model objects + that declare validation constraints. To configure a JSR-303-backed + Validator with Spring MVC, simply add a JSR-303 Provider, such as + Hibernate Validator, to your classpath. Spring MVC will detect it and + automatically enable JSR-303 support across all Controllers. + + The Spring MVC configuration required to enable JSR-303 support + is shown below: + + - + -]]> - - - With this minimal configuration, anytime a @Valid @Controller input is encountered, it will be validated by the JSR-303 provider. - JSR-303, in turn, will enforce any constraints declared against the input. - Any ConstraintViolations will automatically be exposed as errors in the BindingResult renderable by standard Spring MVC form tags. - -
-
-
+]]> + + With this minimal configuration, anytime a @Valid @Controller + input is encountered, it will be validated by the JSR-303 provider. + JSR-303, in turn, will enforce any constraints declared against the + input. Any ConstraintViolations will automatically be exposed as + errors in the BindingResult renderable by standard Spring MVC form + tags. +
+
+