@ -752,7 +752,7 @@ public final class CustomPropertyEditorRegistrar implements PropertyEditorRegist
<title>Spring 3 Type Conversion</title>
<title>Spring 3 Type Conversion</title>
<para>
<para>
Spring 3 introduces a <filename>core.convert</filename> package that provides a general type conversion system.
Spring 3 introduces a <filename>core.convert</filename> package that provides a general type conversion system.
The system defines a SPI to implement type conversion logic, as well as a API to execute type conversions at runtime.
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, if configured, this system can be used as an alternative to PropertyEditors to convert externalized bean property value strings to required property types.
Within a Spring container, if configured, 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.
The public API may also be used anywhere in your application where type conversion is needed.
</para>
</para>
@ -768,53 +768,49 @@ public interface Converter<S, T> {
T convert(S source) throws Exception;
T convert(S source) throws Exception;
}]]>
}]]></programlisting>
</programlisting>
<para>
<para>
To create your own Converter, simply implement the interface above.
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.
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.
For each call to convert(S), the source argument is guaranteed to be NOT null.
Your Converter may throw any Exception if conversion fails.
Your Converter may throw any Exception if conversion fails.
An IllegalArgumentException is often thrown to report an invalid source value.
An IllegalArgumentException is often thrown to report an invalid source value.
Take care to ensure your Converter implementation is threadsafe.
Take care to ensure your Converter implementation is thread-safe.
</para>
</para>
<para>
<para>
Several converter implementations are provided in the <filename>core.convert.converters</filename> package as a convenience.
Several converter implementations are provided in the <filename>core.convert.converters</filename> package as a convenience.
These include converters to from String to Numbers and other common types.
These include converters from Strings to Numbers and other common types.
Note StringToInteger as an example Converter implementation:
Consider <classname>StringToInteger</classname> as an example Converter implementation:
public class StringToInteger implements Converter<String,Integer> {
public class StringToInteger implements Converter<String, Integer> {
public Integer convert(String source) {
public Integer convert(String source) {
return Integer.valueOf(source);
return Integer.valueOf(source);
}
}
}]]>
}</programlisting>
</programlisting>
</section>
</section>
<sectionid="core-convert-ConverterFactory-SPI">
<sectionid="core-convert-ConverterFactory-SPI">
<title>ConverterFactory</title>
<title>ConverterFactory</title>
<para>
<para>
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 a 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 a <interfacename>ConverterFactory</interfacename>ConverterFactory:
@ -889,13 +887,12 @@ public interface ConversionService {
<beanclass="example.MyCustomConverter"/>
<beanclass="example.MyCustomConverter"/>
</list>
</list>
</property>
</property>
</bean>]]>
</bean>]]></programlisting>
</programlisting>
</section>
</section>
<sectionid="core-convert-programmatic-usage">
<sectionid="core-convert-programmatic-usage">
<title>Using a ConversionService programatically</title>
<title>Using a ConversionService programatically</title>
<para>
<para>
To work with a ConversionService instance programatically, simply inject a reference to it like you would any other bean:
To work with a ConversionService instance programatically, simply inject a reference to it like you would for any other bean:
</para>
</para>
<programlistinglanguage="java"><![CDATA[
<programlistinglanguage="java"><![CDATA[
@Service
@Service
@ -909,8 +906,7 @@ public class MyService {
public void doIt() {
public void doIt() {
this.conversionService.convert(...)
this.conversionService.convert(...)
}
}
}]]>
}]]></programlisting>
</programlisting>
</section>
</section>
</section>
</section>
@ -919,9 +915,10 @@ public class MyService {
<para>
<para>
<linklinkend="core.convert"><filename>core.convert</filename></link> is a simple, general-purpose type conversion system.
<linklinkend="core.convert"><filename>core.convert</filename></link> is a simple, general-purpose type conversion system.
It addresses <emphasis>one-way</emphasis> conversion from one type to another and is not limited to just converting Strings.
It addresses <emphasis>one-way</emphasis> conversion from one type to another and is not limited to just converting Strings.
As discussed in the previous section, a Spring Container can be configured to use this system when binding bean property values.
As discussed in the previous section, a Spring Container can be configured to use this system to bind bean property values.
In addition, the Spring Expression Language (SpEL) uses this system to coerce Expression values.
In addition, the Spring Expression Language (SpEL) uses this system to coerce Expression values.
For example, when SpEL needs to coerse a Short to a Long to fullfill an expression.setValue attempt, the core.convert system performs the coersion.
For example, when SpEL needs to coerce a <classname>Short</classname> to a <classname>Long</classname> to fullfill an
<function>expression.setValue()</function> attempt, the core.convert system performs the coersion.
</para>
</para>
<para>
<para>
Now consider the type conversion requirements of a typical UI environment such as a web or desktop application.
Now consider the type conversion requirements of a typical UI environment such as a web or desktop application.
@ -930,11 +927,11 @@ public class MyService {
To directly address this, Spring 3 introduces a new <emphasis>ui.format</emphasis> system that provides a simple and robust alternative to PropertyEditors in a UI environment.
To directly address this, Spring 3 introduces a new <emphasis>ui.format</emphasis> system that provides a simple and robust alternative to PropertyEditors in a UI environment.
</para>
</para>
<para>
<para>
In general, use Converters when you need implement general-purpose type
In general, use Converters when you need to implement general-purpose type
conversion logic, logic that may be invoked by the Spring Container, SpEL,
conversion logic, logic that may be invoked by the Spring Container, SpEL,
or your own code as part of a <emphasis>one-way</emphasis> binding process.
or your own code as part of a <emphasis>one-way</emphasis> binding process.
Use Formatters when you're working in a UI environment, such as an HTML form
Use Formatters when you're working in a UI environment, such as an HTML form
of a web application, and need to apply <emphasis>two-way</emphasis> parsing,
of a web application and need to apply <emphasis>two-way</emphasis> parsing,
formatting, and localization logic to form field values.
formatting, and localization logic to form field values.
</para>
</para>
<sectionid="ui-format-Formatter-SPI">
<sectionid="ui-format-Formatter-SPI">
@ -953,15 +950,14 @@ public interface Formatter<T> {
T parse(String formatted, Locale locale) throws ParseException;
T parse(String formatted, Locale locale) throws ParseException;
}]]>
}]]></programlisting>
</programlisting>
<para>
<para>
To create your own Formatter, simply implement the interface above.
To create your own Formatter, simply implement the interface above.
Parameterize T to be the type of Object you are formatting; for example, <classname>java.lang.BigDecimal</classname>.
Parameterize T to be the type of object you are formatting, for example, <classname>java.lang.BigDecimal</classname>.
Implement the <methodname>format</methodname> operation to format an instance of T for display in the client locale.
Implement the <methodname>format</methodname> operation to format an instance of T for display in the client locale.
Implement the <methodname>parse</methodname> operation to parse an instance of T from the formatted representation returned from the client locale.
Implement the <methodname>parse</methodname> operation to parse an instance of T from the formatted representation returned from the client locale.
Your Formatter should throw a ParseException if a parse attempt fails.
Your Formatter should throw a ParseException if a parse attempt fails.
Take care to ensure your Formatter implementation is threadsafe.
Take care to ensure your Formatter implementation is thread-safe.
</para>
</para>
<para>
<para>
Several Formatter implementations are provided in subpackages of <filename>ui.format</filename> as a convenience.
Several Formatter implementations are provided in subpackages of <filename>ui.format</filename> as a convenience.
@ -969,7 +965,7 @@ public interface Formatter<T> {
The <filename>number</filename> package provides a DecimalFormatter, IntegerFormatter, CurrencyFormatter, and PercentFormatter to format java.lang.Number objects using a java.text.NumberFormat.
The <filename>number</filename> package provides a DecimalFormatter, IntegerFormatter, CurrencyFormatter, and PercentFormatter to format java.lang.Number objects using a java.text.NumberFormat.
</para>
</para>
<para>
<para>
Note DateFormatter as an example Formatter implementation:
Consider <classname>DateFormatter</classname> as an example <interfacename>Formatter</interfacename> implementation:
</para>
</para>
<programlistinglanguage="java"><![CDATA[
<programlistinglanguage="java"><![CDATA[
package org.springframework.ui.format.date;
package org.springframework.ui.format.date;
@ -1002,8 +998,7 @@ public final class DateFormatter implements Formatter<Date> {
return dateFormat;
return dateFormat;
}
}
}]]>
}]]></programlisting>
</programlisting>
<para>
<para>
The Spring team welcomes community-driven Formatter contributions; see <ulinkurl="http://jira.springframework.org">http://jira.springframework.org</ulink> to contribute.
The Spring team welcomes community-driven Formatter contributions; see <ulinkurl="http://jira.springframework.org">http://jira.springframework.org</ulink> to contribute.
In particular, the team hopes to integrate support for Joda Time and Money Formatters in the future.
In particular, the team hopes to integrate support for Joda Time and Money Formatters in the future.
@ -1019,9 +1014,7 @@ public final class DateFormatter implements Formatter<Date> {
@Formatted(MoneyFormatter.class)
@Formatted(MoneyFormatter.class)
public class Money {
public class Money {
...
...
}
}]]></programlisting>
]]>
</programlisting>
<para>
<para>
The example above says <emphasis>"Money objects should be formatted by a MoneyFormatter"</emphasis>.
The example above says <emphasis>"Money objects should be formatted by a MoneyFormatter"</emphasis>.
With this configuation, whenever a field is of type Money, MoneyFormatter will format the field value.
With this configuation, whenever a field is of type Money, MoneyFormatter will format the field value.
@ -1038,9 +1031,7 @@ public class Money {
@Retention(RetentionPolicy.RUNTIME)
@Retention(RetentionPolicy.RUNTIME)
@Formatted(CurrencyFormatter.class)
@Formatted(CurrencyFormatter.class)
public @interface Currency {
public @interface Currency {
}
}]]></programlisting>
]]>
</programlisting>
<para>
<para>
Then, to trigger formatting, simply annotate a model property with the annotation:
Then, to trigger formatting, simply annotate a model property with the annotation:
</para>
</para>
@ -1050,9 +1041,7 @@ public class MyModel {
@Currency
@Currency
private BigDecimal amount;
private BigDecimal amount;
}
}]]></programlisting>
]]>
</programlisting>
<para>
<para>
Custom annotations like @Currency can also be annotated with JSR-303 constraint annotations to specify declarative validation constraints.
Custom annotations like @Currency can also be annotated with JSR-303 constraint annotations to specify declarative validation constraints.