| | + title | Ref. /chapter[1]/title[1] |
| Original | Traduction | PropertyEditors, data binding, validation and the BeanWrapper |
| sect1
| | + title | Ref. /chapter[1]/sect1[1]/title[1] |
| Original | Traduction | Introduction |
|
| + para | Ref. /chapter[1]/sect1[1]/para[1] |
| Original | Traduction | The big question is whether or not validation should be considered
business logic. There are pros and cons for both
answers, and Spring offers a design for validation (and data binding) that
does not exclude either one of them. Validation should specifically 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's both
basic and usable in every layer of an application. |
|
| + para | Ref. /chapter[1]/sect1[1]/para[2] |
| Original | Traduction | 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. |
|
| + para | Ref. /chapter[1]/sect1[1]/para[3] |
| Original | Traduction | The BeanWrapper is a fundamental concept in the
Spring Framework and is used in a lot of places. However, you probably
will not ever have the need to use the BeanWrapper directly. Because this
is reference documentation however, we felt that some explanation might be
right. We're explaining the BeanWrapper in this chapter since if you were
going to use it at all, you would probably do that when trying to bind
data to objects, which is strongly related to the BeanWrapper. |
|
| + para | Ref. /chapter[1]/sect1[1]/para[4] |
| Original | Traduction | Spring uses PropertyEditors all over the place. The concept of a
PropertyEditor is part of the JavaBeans specification. Just as the
BeanWrapper, it's best to explain the use of PropertyEditors in this
chapter as well, since it's closely related to the BeanWrapper and the
DataBinder. |
|
| | sect1
| | + title | Ref. /chapter[1]/sect1[2]/title[1] |
| Original | Traduction | Binding data using the DataBinder |
|
| + para | Ref. /chapter[1]/sect1[2]/para[1] |
| Original | Traduction | The DataBinder builds on top of the BeanWrapper
| + para | Ref. /chapter[1]/sect1[2]/para[1]/footnote[1]/para[1] |
| Original | Traduction | See the beans chapter for more
information |
|
. |
|
| | sect1
| | + title | Ref. /chapter[1]/sect1[3]/title[1] |
| Original | Traduction | Bean manipulation and the BeanWrapper |
|
| + para | Ref. /chapter[1]/sect1[3]/para[1] |
| Original | Traduction | 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 conventions
where a property named prop has a setter
setProp(...) and a getter getProp().
For more information about JavaBeans and the specification, please refer
to Sun's website (java.sun.com/products/javabeans). |
|
| + para | Ref. /chapter[1]/sect1[3]/para[2] |
| Original | Traduction | One quite important concept of 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
support 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. |
|
| + para | Ref. /chapter[1]/sect1[3]/para[3] |
| Original | Traduction | 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. |
| sect2
| | + title | Ref. /chapter[1]/sect1[3]/sect2[1]/title[1] |
| Original | Traduction | Setting and getting basic and nested properties |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[1]/para[1] |
| Original | Traduction | 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:
| + title | Ref. /chapter[1]/sect1[3]/sect2[1]/para[1]/table[1]/title[1] |
| Original | Traduction | Examples of properties |
|
| + entry | Ref. /chapter[1]/sect1[3]/sect2[1]/para[1]/table[1]/tgroup[1]/thead[1]/row[1]/entry[1] |
| Original | Traduction | Expression |
|
| + entry | Ref. /chapter[1]/sect1[3]/sect2[1]/para[1]/table[1]/tgroup[1]/thead[1]/row[1]/entry[2] |
| Original | Traduction | Explanation |
|
name
| + entry | Ref. /chapter[1]/sect1[3]/sect2[1]/para[1]/table[1]/tgroup[1]/tbody[1]/row[1]/entry[2] |
| Original | Traduction | Indicates the property name
corresponding to the methods getName() or
isName() and
setName() |
|
account.name
| + entry | Ref. /chapter[1]/sect1[3]/sect2[1]/para[1]/table[1]/tgroup[1]/tbody[1]/row[2]/entry[2] |
| Original | Traduction | Indicates the nested property name
of the property account corresponding e.g.
to the methods getAccount().setName() or
getAccount().getName() |
|
account[2]
| + entry | Ref. /chapter[1]/sect1[3]/sect2[1]/para[1]/table[1]/tgroup[1]/tbody[1]/row[3]/entry[2] |
| Original | Traduction | Indicates the third element of the
indexed property account. Indexed
properties can be of type array,
list or other naturally
ordered collection |
|
account[COMPANYNAME]
| + entry | Ref. /chapter[1]/sect1[3]/sect2[1]/para[1]/table[1]/tgroup[1]/tbody[1]/row[4]/entry[2] |
| Original | Traduction | Indicates the value of the map entry indexed by the key
COMPANYNAME of the Map property
account |
|
|
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[1]/para[2] |
| Original | Traduction | Below you'll find some examples of working with the BeanWrapper to
get and set properties. |
| Note: this part is not 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. | + para | Ref. /chapter[1]/sect1[3]/sect2[1]/para[4] |
| Original | Traduction | Consider the following two classes: | + programlisting | Ref. /chapter[1]/sect1[3]/sect2[1]/para[4]/programlisting[1] |
| Original | Traduction | public class Company {
private String name;
private Employee managingDirector;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Employee getManagingDirector() {
return this.managingDirector;
}
public void setManagingDirector(Employee managingDirector) {
this.managingDirector = managingDirector;
}
} |
| | + programlisting | Ref. /chapter[1]/sect1[3]/sect2[1]/para[4]/programlisting[2] |
| Original | Traduction | public class Employee {
private float salary;
public float getSalary() {
return salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
} |
|
|
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[1]/para[5] |
| Original | Traduction | The following code snippets show some examples of how to retrieve
and manipulate some of the properties of instantiated:
Companies and Employees
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[1]/para[5]/programlisting[1] |
| Original | Traduction | Company c = new Company();
BeanWrapper bwComp = BeanWrapperImpl(c);
// setting the company name...
bwComp.setPropertyValue("name", "Some Company Inc.");
// ... can also be done like this:
PropertyValue v = new PropertyValue("name", "Some Company Inc.");
bwComp.setPropertyValue(v);
// ok, let's create the director and tie it to the company:
Employee jim = new Employee();
BeanWrapper bwJim = BeanWrapperImpl(jim);
bwJim.setPropertyValue("name", "Jim Stravinsky");
bwComp.setPropertyValue("managingDirector", jim);
// retrieving the salary of the managingDirector through the company
Float salary = (Float)bwComp.getPropertyValue("managingDirector.salary"); |
|
|
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[3]/sect2[2]/title[1] |
| Original | Traduction | Built-in PropertyEditors, converting
types |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/para[1] |
| Original | Traduction | Spring heavily uses the concept of
PropertyEditors. Sometimes it 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, 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 Application Context 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. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/para[2] |
| Original | Traduction | A couple of examples where property editing is used in Spring
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/para[2]/itemizedlist[1]/listitem[1]/para[1] |
| Original | Traduction | 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 |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/para[2]/itemizedlist[1]/listitem[2]/para[1] |
| Original | Traduction | 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 |
|
|
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3] |
| Original | Traduction | 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:
| + title | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/title[1] |
| Original | Traduction | Built-in PropertyEditors |
|
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/thead[1]/row[1]/entry[1] |
| Original | Traduction | Class |
|
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/thead[1]/row[1]/entry[2] |
| Original | Traduction | Explanation |
|
ByteArrayPropertyEditor
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/tbody[1]/row[1]/entry[2] |
| Original | Traduction | Editor for byte arrays. Strings will simply be
converted to their corresponding byte representations.
Registered by default by BeanWrapperImpl. |
|
ClassEditor
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/tbody[1]/row[2]/entry[2] |
| Original | Traduction | 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
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/tbody[1]/row[3]/entry[2] |
| Original | Traduction | Customizable property editor for Boolean properties.
Registered by default by BeanWrapperImpl, but, can be
overridden by registering custom instance of it as custom
editor. |
|
CustomDateEditor
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/tbody[1]/row[4]/entry[2] |
| Original | Traduction | 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
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/tbody[1]/row[5]/entry[2] |
| Original | Traduction | 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 custom editor. |
|
FileEditor
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/tbody[1]/row[6]/entry[2] |
| Original | Traduction | Capable of resolving Strings to
File-objects. Registered by default by
BeanWrapperImpl. |
|
InputStreamEditor
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/tbody[1]/row[7]/entry[2] |
| Original | Traduction | 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 setCapable of resolving Strings to
File-objects. Note that the default usage
will not close the InputStream for you!. Registered by default
by BeanWrapperImpl. |
|
LocaleEditor
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/tbody[1]/row[8]/entry[2] |
| Original | Traduction | 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. |
|
PropertiesEditor
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/tbody[1]/row[9]/entry[2] |
| Original | Traduction | 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. |
|
StringArrayPropertyEditor
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/tbody[1]/row[10]/entry[2] |
| Original | Traduction | Capable of resolving a comma-delimited list of String
to a String-array and vice versa. Registered by default by
BeanWrapperImpl. |
|
StringTrimmerEditor
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/tbody[1]/row[11]/entry[2] |
| Original | Traduction | 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
| + entry | Ref. /chapter[1]/sect1[3]/sect2[2]/para[3]/table[1]/tgroup[1]/tbody[1]/row[12]/entry[2] |
| Original | Traduction | Capable of resolving a String representation of a URL
to an actual URL-object. Registered by
default by BeanWrapperImpl. |
|
|
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/para[4] |
| Original | Traduction | 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
PropertyEditors for Font, Color and all the primitive types. Note also
that the standard JavaBeans infrastructure will automatically discover
PropertyEditors (without you having to register them) if they are in the
same package as the class they handle, and have the same name as that
class, with 'Editor' appended. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[3]/sect2[3]/title[1] |
| Original | Traduction | Other features worth mentioning |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[3]/para[1] |
| Original | Traduction | Besides the features you've seen in the previous sections there a
couple of features that might be interesting to you, though not worth an
entire section.
| + para | Ref. /chapter[1]/sect1[3]/sect2[3]/para[1]/itemizedlist[1]/listitem[1]/para[1] |
| Original | Traduction | determining readability and
writability: using the isReadable()
and isWritable() methods, you can determine
whether or not a property is readable or writable |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[3]/para[1]/itemizedlist[1]/listitem[2]/para[1] |
| Original | Traduction | retrieving PropertyDescriptors: using
getPropertyDescriptor(String) and
getPropertyDescriptors() you can retrieve
objects of type java.beans.PropertyDescriptor,
that might come in handy sometimes |
|
|
|
| |
| |
|