core-validation.adoc 61.1 KB
Newer Older
1 2 3 4 5
[[validation]]
= Validation, Data Binding, and Type Conversion

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.
6 7
Specifically, validation should not be tied to the web tier and should be easy to localize,
and it should be possible to plug in any available validator. Considering these concerns,
Y
youmoo 已提交
8
Spring has come up with a `Validator` interface that is both basic and eminently usable
9 10
in every layer of an application.

11
Data binding is useful for letting user input be dynamically bound to the domain
12
model of an application (or whatever objects you use to process user input). Spring
13
provides the aptly named `DataBinder` to do exactly that. The `Validator` and the
14 15 16 17
`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
18 19 20 21 22
of places. However, you probably do not need to use the `BeanWrapper`
directly. Because this is reference documentation, however, we felt that some explanation
might be in order. We explain the `BeanWrapper` in this chapter, since, if you are
going to use it at all, you are most likely do so when trying to bind data to objects.

23 24 25 26 27 28 29
Spring's `DataBinder` and the lower-level `BeanWrapper` both use `PropertyEditorSupport`
implementations to parse and format property values. The `PropertyEditor` and
`PropertyEditorSupport` types are part of the JavaBeans specification and are also
explained in this chapter. Spring 3 introduced a `core.convert` package that provides a
general type conversion facility, as well as a higher-level "`format`" package for
formatting UI field values. You can use these packages as simpler alternatives to
`PropertyEditorSupport` implementations. They are also discussed in this chapter.
30

31 32
.JSR-303/JSR-349 Bean Validation
****
33 34 35
As of version 4.0, Spring Framework supports Bean Validation 1.0 (JSR-303) and
Bean Validation 1.1 (JSR-349) for setup support and adapting them to Spring's
`Validator` interface.
36 37 38 39 40 41 42 43

An application can choose to enable Bean Validation once globally, as described in
<<validation-beanvalidation>>, and use it exclusively for all validation needs.

An application can also register additional Spring `Validator` instances for each
`DataBinder` instance, as described in <<validation-binder>>. This may be useful for
plugging in validation logic without the use of annotations.
****
44 45 46



47

48
[[validator]]
49
== Validation by Using Spring's Validator Interface
50 51

Spring features a `Validator` interface that you can use to validate objects. The
52
`Validator` interface works by using an `Errors` object so that, while validating,
53 54
validators can report validation failures to the `Errors` object.

55
Consider the following example of a small data object:
56 57 58 59 60 61 62 63 64 65 66 67 68

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	public class Person {

		private String name;
		private int age;

		// the usual getters and setters...
	}
----

69
The next example provides validation behavior for the `Person` class by implementing the
70 71
following two methods of the `org.springframework.validation.Validator` interface:

72 73 74
* `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.
75 76

Implementing a `Validator` is fairly straightforward, especially when you know of the
77 78
`ValidationUtils` helper class that the Spring Framework also provides. The following
example implements `Validator` for `Person` instances:
79 80 81 82 83 84 85

[source,java,indent=0]
[subs="verbatim"]
----
	public class PersonValidator implements Validator {

		/**
86
		 * This Validator validates *only* Person instances
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
		 */
		public boolean supports(Class clazz) {
			return Person.class.equals(clazz);
		}

		public void validate(Object obj, Errors e) {
			ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
			Person p = (Person) obj;
			if (p.getAge() < 0) {
				e.rejectValue("age", "negativevalue");
			} else if (p.getAge() > 110) {
				e.rejectValue("age", "too.darn.old");
			}
		}
	}
----

104 105 106 107
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
{api-spring-framework}/validation/ValidationUtils.html[`ValidationUtils`] javadoc
to see what functionality it provides besides the example shown previously.
108 109 110 111

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
112 113 114
example of a "`rich`" object would be a `Customer` that is composed of two `String`
properties (a first and a second name) and a complex `Address` object. `Address` objects
may be used independently of `Customer` objects, so a distinct `AddressValidator`
115 116 117
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`,
118
as the following example shows:
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	public class CustomerValidator implements Validator {

		private final Validator addressValidator;

		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 " +
K
Krzysztof Kosmatka 已提交
134
					"support the validation of [Address] instances.");
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
			}
			this.addressValidator = addressValidator;
		}

		/**
		 * This Validator validates Customer instances, and any subclasses of Customer too
		 */
		public boolean supports(Class clazz) {
			return Customer.class.isAssignableFrom(clazz);
		}

		public void validate(Object target, Errors errors) {
			ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required");
			ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required");
			Customer customer = (Customer) target;
			try {
				errors.pushNestedPath("address");
				ValidationUtils.invokeValidator(this.addressValidator, customer.getAddress(), errors);
			} finally {
				errors.popNestedPath();
			}
		}
	}
----

160 161 162
Validation errors are reported to the `Errors` object passed to the validator. In the case
of Spring Web MVC, you can use the `<spring:bind/>` tag to inspect the error messages, but
you can also inspect the `Errors` object yourself. More information about the
163 164
methods it offers can be found in the {api-spring-framework}validation/Errors.html[javadoc].

165 166 167 168



[[validation-conversion]]
169
== Resolving Codes to Error Messages
170

171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
We covered databinding and validation. This section covers outputting messages that correspond
to validation errors. In the example shown in the <<validator, preceding section>>,
we rejected the `name` and `age` fields. If we want to output the error messages by using a
`MessageSource`, we can do so using the error code we provide when rejecting the field
('name' and 'age' in this case). When you call (either directly, or indirectly, by using,
for example, the `ValidationUtils` class) `rejectValue` or one of the other `reject` methods
from the `Errors` interface, the underlying implementation not only registers the code you
passed in but also registers a number of additional error codes. The `MessageCodesResolver`
determines which error codes the `Errors` interface registers. By default, the
`DefaultMessageCodesResolver` is used, which (for example) not only registers a message
with the code you gave but also registers messages that include the field name you passed
to the reject method. So, if you reject a field by using `rejectValue("age", "too.darn.old")`,
apart from the `too.darn.old` code, Spring also registers `too.darn.old.age` and
`too.darn.old.age.int` (the first includes the field name and the second includes the type
of the field). This is done as a convenience to aid developers when targeting error messages.
186 187

More information on the `MessageCodesResolver` and the default strategy can be found
188 189
in the javadoc of
{api-spring-framework}/validation/MessageCodesResolver.html[`MessageCodesResolver`] and
190
{api-spring-framework}/validation/DefaultMessageCodesResolver.html[`DefaultMessageCodesResolver`],
191 192 193 194
respectively.



195

196
[[beans-beans]]
197
== Bean Manipulation and the `BeanWrapper`
198

199 200 201
The `org.springframework.beans` package adheres to the JavaBeans standard.
A JavaBean is a class with a default no-argument constructor and that follows
a naming convention where (for example) a property named `bingoMadness` would
202
have a setter method `setBingoMadness(..)` and a getter method `getBingoMadness()`. For
203
more information about JavaBeans and the specification, see
S
Spring Operator 已提交
204
https://docs.oracle.com/javase/8/docs/api/java/beans/package-summary.html[javabeans].
205 206

One quite important class in the beans package is the `BeanWrapper` interface and its
207
corresponding implementation (`BeanWrapperImpl`). As quoted from the javadoc, the
208
`BeanWrapper` offers functionality to set and get property values (individually or in
209
bulk), get property descriptors, and query properties to determine if they are
210
readable or writable. Also, the `BeanWrapper` offers support for nested properties,
211 212
enabling the setting of properties on sub-properties to an unlimited depth. The
`BeanWrapper` also supports the ability to add standard JavaBeans `PropertyChangeListeners`
213
and `VetoableChangeListeners`, without the need for supporting code in the target class.
214 215 216
Last but not least, the `BeanWrapper` provides support for setting indexed properties.
The `BeanWrapper` usually is not used by application code directly but is used by the
`DataBinder` and the `BeanFactory`.
217

218 219
The way the `BeanWrapper` works is partly indicated by its name: it wraps a bean to
perform actions on that bean, such as setting and retrieving properties.
220 221 222 223



[[beans-beans-conventions]]
224
=== Setting and Getting Basic and Nested Properties
225

226 227 228
Setting and getting properties is done by using the `setPropertyValue`,
`setPropertyValues`, `getPropertyValue`, and `getPropertyValues` methods which come
with a couple of overloaded variants. Springs javadoc describes them in more detail.
229 230
The JavaBeans specification has conventions for indicating properties of an
object. The following table shows some examples of these conventions:
231 232 233 234 235 236 237

[[beans-beans-conventions-properties-tbl]]
.Examples of properties
|===
| Expression| Explanation

| `name`
238 239
| Indicates the property `name` that corresponds to the `getName()` or `isName()`
  and `setName(..)` methods.
240 241

| `account.name`
242 243
| Indicates the nested property `name` of the property `account` that corresponds to
  (for example) the `getAccount().setName()` or `getAccount().getName()` methods.
244 245

| `account[2]`
246 247
| Indicates the _third_ element of the indexed property `account`. Indexed properties
  can be of type `array`, `list`, or other naturally ordered collection.
248 249

| `account[COMPANYNAME]`
250 251
| Indicates the value of the map entry indexed by the `COMPANYNAME` key of the `account` `Map`
  property.
252 253
|===

254 255
(This next section is not vitally important to you if you do not plan to work with
the `BeanWrapper` directly. If you use only the `DataBinder` and the `BeanFactory`
256 257
and their default implementations, you should skip ahead to the
<<beans-beans-conversion, section on `PropertyEditors`>>.)
258

H
HeemangHan 已提交
259
The following two example classes use the `BeanWrapper` to get and set
260
properties:
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	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;
		}
	}
----

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	public class Employee {

		private String name;

		private float salary;

		public String getName() {
			return this.name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public float getSalary() {
			return salary;
		}

		public void setSalary(float salary) {
			this.salary = salary;
		}
	}
----

The following code snippets show some examples of how to retrieve and manipulate some of
the properties of instantiated `Companies` and `Employees`:

[source,java,indent=0]
[subs="verbatim,quotes"]
----
321
	BeanWrapper company = new BeanWrapperImpl(new Company());
322 323 324 325 326 327 328
	// setting the company name..
	company.setPropertyValue("name", "Some Company Inc.");
	// ... can also be done like this:
	PropertyValue value = new PropertyValue("name", "Some Company Inc.");
	company.setPropertyValue(value);

	// ok, let's create the director and tie it to the company:
329
	BeanWrapper jim = new BeanWrapperImpl(new Employee());
330 331 332 333 334 335 336 337 338 339
	jim.setPropertyValue("name", "Jim Stravinsky");
	company.setPropertyValue("managingDirector", jim.getWrappedInstance());

	// retrieving the salary of the managingDirector through the company
	Float salary = (Float) company.getPropertyValue("managingDirector.salary");
----



[[beans-beans-conversion]]
340
=== Built-in `PropertyEditor` Implementations
341

342 343
Spring uses the concept of a `PropertyEditor` to effect the conversion between an
`Object` and a `String`. It can be handy
344
to represent properties in a different way than the object itself. For example, a `Date`
345 346 347 348 349 350 351
can be represented in a human readable way (as the `String`: `'2007-14-09'`), while
we can still 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,
alternatively, in a specific IoC container (as mentioned in the previous chapter), gives it
the knowledge of how to convert properties to the desired type. For more about
352
`PropertyEditor`, see https://docs.oracle.com/javase/8/docs/api/java/beans/package-summary.html[the javadoc of the `java.beans` package from Oracle].
353 354 355

A couple of examples where property editing is used in Spring:

J
Juergen Hoeller 已提交
356 357 358 359
* Setting properties on beans is done by using `PropertyEditor` implementations.
  When you use `String` as the value of a property of some bean that you declare
  in an XML file, Spring (if the setter of the corresponding property has a `Class`
  parameter) uses `ClassEditor` to try to resolve the parameter to a `Class` object.
360 361
* Parsing HTTP request parameters in Spring's MVC framework is done by using all kinds
  of `PropertyEditor` implementations that you can manually bind in all subclasses of the
362 363
  `CommandController`.

364 365 366 367 368 369
Spring has a number of built-in `PropertyEditor` implementations to make life easy.
They are all located in the `org.springframework.beans.propertyeditors`
package. Most, (but not all, as indicated in the following table) are, by default, registered by
`BeanWrapperImpl`. Where the property editor is configurable in some fashion, you can
still register your own variant to override the default one. The following table describes
the various `PropertyEditor` implementations that Spring provides:
370 371

[[beans-beans-property-editors-tbl]]
372 373
.Built-in `PropertyEditor` Implementations
[cols="30%,70%"]
374 375 376 377
|===
| Class| Explanation

| `ByteArrayPropertyEditor`
378
| Editor for byte arrays. Converts strings to their corresponding byte
379 380 381
  representations. Registered by default by `BeanWrapperImpl`.

| `ClassEditor`
382 383
| Parses Strings that represent classes to actual classes and vice-versa. When a
  class is not found, an `IllegalArgumentException` is thrown. By default, registered by
384 385 386
  `BeanWrapperImpl`.

| `CustomBooleanEditor`
387 388
| Customizable property editor for `Boolean` properties. By default, registered by
  `BeanWrapperImpl` but can be overridden by registering a custom instance of it as a
389 390 391
  custom editor.

| `CustomCollectionEditor`
392
| Property editor for collections, converting any source `Collection` to a given target
393 394 395
  `Collection` type.

| `CustomDateEditor`
396 397
| Customizable property editor for `java.util.Date`, supporting a custom `DateFormat`. NOT
  registered by default. Must be user-registered with the appropriate format as needed.
398 399

| `CustomNumberEditor`
400 401 402
| Customizable property editor for any `Number` subclass, such as `Integer`, `Long`, `Float`, or
  `Double`. By default, registered by `BeanWrapperImpl` but can be overridden by
  registering a custom instance of it as a custom editor.
403 404

| `FileEditor`
405
| Resolves strings to `java.io.File` objects. By default, registered by
406 407 408
  `BeanWrapperImpl`.

| `InputStreamEditor`
409 410 411 412
| One-way property editor that can take a string and produce (through an
  intermediate `ResourceEditor` and `Resource`) an `InputStream` so that `InputStream`
  properties may be directly set as strings. Note that the default usage does not close
  the `InputStream` for you. By default, registered by `BeanWrapperImpl`.
413 414

| `LocaleEditor`
415 416 417
| Can resolve strings to `Locale` objects and vice-versa (the string format is
  `[language]_[country]_[variant]`, same as the `toString()` method of
  `Locale`). By default, registered by `BeanWrapperImpl`.
418 419

| `PatternEditor`
420
| Can resolve strings to `java.util.regex.Pattern` objects and vice-versa.
421 422

| `PropertiesEditor`
423 424
| Can convert strings (formatted with the format defined in the javadoc of the
  `java.util.Properties` class) to `Properties` objects. By default, registered
425 426 427
  by `BeanWrapperImpl`.

| `StringTrimmerEditor`
428 429
| Property editor that trims strings. Optionally allows transforming an empty string
  into a `null` value. NOT registered by default -- must be user-registered.
430 431

| `URLEditor`
432 433
| Can resolve a string representation of a URL to an actual `URL` object.
  By default, registered by `BeanWrapperImpl`.
434 435 436 437 438
|===

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
439 440 441 442 443 444
the primitive types. Note also that the standard JavaBeans infrastructure
automatically discovers `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 `SomethingEditor` class to be
recognized and used as the `PropertyEditor` for `Something`-typed properties.
445 446 447 448 449 450 451

[literal]
[subs="verbatim,quotes"]
----
com
  chank
    pop
452 453
      Something
      SomethingEditor // the PropertyEditor for the Something class
454 455 456
----

Note that you can also use the standard `BeanInfo` JavaBeans mechanism here as well
457
(described to some extent
S
Spring Operator 已提交
458
https://docs.oracle.com/javase/tutorial/javabeans/advanced/customization.html[
459 460 461
here]). The following example use the `BeanInfo` mechanism to
explicitly register one or more `PropertyEditor` instances with the properties of an
associated class:
462 463 464 465 466 467 468

[literal]
[subs="verbatim,quotes"]
----
com
  chank
    pop
469 470
      Something
      SomethingBeanInfo // the BeanInfo for the Something class
471 472
----

473 474
The following Java source code for the referenced `SomethingBeanInfo` class
associates a `CustomNumberEditor` with the `age` property of the `Something` class:
475 476 477 478

[source,java,indent=0]
[subs="verbatim,quotes"]
----
479
	public class SomethingBeanInfo extends SimpleBeanInfo {
480 481 482 483

		public PropertyDescriptor[] getPropertyDescriptors() {
			try {
				final PropertyEditor numberPE = new CustomNumberEditor(Integer.class, true);
484
				PropertyDescriptor ageDescriptor = new PropertyDescriptor("age", Something.class) {
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
					public PropertyEditor createPropertyEditor(Object bean) {
						return numberPE;
					};
				};
				return new PropertyDescriptor[] { ageDescriptor };
			}
			catch (IntrospectionException ex) {
				throw new Error(ex.toString());
			}
		}
	}
----


[[beans-beans-conversion-customeditor-registration]]
500 501 502 503 504 505 506 507 508 509 510 511 512
==== Registering Additional Custom `PropertyEditor` Implementations

When setting bean properties as string values, a Spring IoC container ultimately uses
standard JavaBeans `PropertyEditor` implementations to convert these strings to the complex type of the
property. Spring pre-registers a number of custom `PropertyEditor` implementations (for example, to
convert a class name expressed as a string into a `Class` object). Additionally,
Java's standard JavaBeans `PropertyEditor` lookup mechanism lets a `PropertyEditor`
for a class be named appropriately and placed in the same package as the class
for which it provides support, so that it can be found automatically.

If there is a need to register other custom `PropertyEditors`, several mechanisms are
available. The most manual approach, which is not normally convenient or
recommended, is to use the `registerCustomEditor()` method of the
513
`ConfigurableBeanFactory` interface, assuming you have a `BeanFactory` reference.
514 515 516 517 518 519
Another (slightly more convenient) mechanism is to use a special bean factory
post-processor called `CustomEditorConfigurer`. Although you can use bean factory post-processors
with `BeanFactory` implementations, the `CustomEditorConfigurer` has a
nested property setup, so we strongly recommend that you use it with the
`ApplicationContext`, where you can deploy it in similar fashion to any other bean and
where it can be automatically detected and applied.
520 521

Note that all bean factories and application contexts automatically use a number of
522
built-in property editors, through their use a `BeanWrapper` to
523
handle property conversions. The standard property editors that the `BeanWrapper`
524 525
registers are listed in the <<beans-beans-conversion, previous section>>.
Additionally, `ApplicationContexts` also override or add additional editors to handle
526 527 528
resource lookups in a manner appropriate to the specific application context type.

Standard JavaBeans `PropertyEditor` instances are used to convert property values
529 530
expressed as strings to the actual complex type of the property. You can use
`CustomEditorConfigurer`, a bean factory post-processor, to conveniently add
531 532
support for additional `PropertyEditor` instances to an `ApplicationContext`.

533 534
Consider the following example, which defines a user class called `ExoticType` and
another class called `DependsOnExoticType`, which needs `ExoticType` set as a property:
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package example;

	public class ExoticType {

		private String name;

		public ExoticType(String name) {
			this.name = name;
		}
	}

	public class DependsOnExoticType {

		private ExoticType type;

		public void setType(ExoticType type) {
			this.type = type;
		}
	}
----

When things are properly set up, we want to be able to assign the type property as a
561 562
string, which a `PropertyEditor` converts into an actual
`ExoticType` instance. The following bean definition shows how to set up this relationship:
563 564 565 566 567 568 569 570 571

[source,xml,indent=0]
[subs="verbatim,quotes"]
----
	<bean id="sample" class="example.DependsOnExoticType">
		<property name="type" value="aNameForExoticType"/>
	</bean>
----

572
The `PropertyEditor` implementation could look similar to the following:
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	// converts string representation to ExoticType object
	package example;

	public class ExoticTypeEditor extends PropertyEditorSupport {

		public void setAsText(String text) {
			setValue(new ExoticType(text.toUpperCase()));
		}
	}
----

588
Finally, the following example shows how to use `CustomEditorConfigurer` to register the new `PropertyEditor` with the
589 590 591 592 593 594 595 596 597 598 599 600 601
`ApplicationContext`, which will then be able to use it as needed:

[source,xml,indent=0]
[subs="verbatim,quotes"]
----
	<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
		<property name="customEditors">
			<map>
				<entry key="example.ExoticType" value="example.ExoticTypeEditor"/>
			</map>
		</property>
	</bean>
----
602

603
[[beans-beans-conversion-customeditor-registration-per]]
604
===== Using `PropertyEditorRegistrar`
605 606 607

Another mechanism for registering property editors with the Spring container is to
create and use a `PropertyEditorRegistrar`. This interface is particularly useful when
608 609 610 611 612 613 614 615 616
you need to use the same set of property editors in several different situations.
You can write a corresponding registrar and reuse it in each case.
`PropertyEditorRegistrar` instances work in conjunction with an interface called
`PropertyEditorRegistry`, an interface that is implemented by the Spring `BeanWrapper`
(and `DataBinder`). `PropertyEditorRegistrar` instances are particularly convenient
when used in conjunction with `CustomEditorConfigurer` (described
<<beans-beans-conversion-customeditor-registration, here>>), which exposes a property
called `setPropertyEditorRegistrars(..)`. `PropertyEditorRegistrar` instances added
to a `CustomEditorConfigurer` in this fashion can easily be shared with `DataBinder` and
617 618
Spring MVC controllers. Furthermore, it avoids the need for synchronization on custom
editors: A `PropertyEditorRegistrar` is expected to create fresh `PropertyEditor`
619 620
instances for each bean creation attempt.

621
The following example shows how to create your own `PropertyEditorRegistrar` implementation:
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package com.foo.editors.spring;

	public final class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {

		public void registerCustomEditors(PropertyEditorRegistry registry) {

			// it is expected that new PropertyEditor instances are created
			registry.registerCustomEditor(ExoticType.class, new ExoticTypeEditor());

			// 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
642
`registerCustomEditors(..)` method ,it creates new instances of each property editor.
643

644
The next example shows how to configure a `CustomEditorConfigurer` and inject an instance of our
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
`CustomPropertyEditorRegistrar` into it:

[source,xml,indent=0]
[subs="verbatim,quotes"]
----
	<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
		<property name="propertyEditorRegistrars">
			<list>
				<ref bean="customPropertyEditorRegistrar"/>
			</list>
		</property>
	</bean>

	<bean id="customPropertyEditorRegistrar"
		class="com.foo.editors.spring.CustomPropertyEditorRegistrar"/>
----

662
Finally (and in a bit of a departure from the focus of this chapter for those of you
663
using <<web.adoc#mvc, Spring's MVC web framework>>), using `PropertyEditorRegistrars` in
664
conjunction with data-binding `Controllers` (such as `SimpleFormController`) can be very
665
convenient. The following example uses a `PropertyEditorRegistrar` in the
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
implementation of an `initBinder(..)` method:

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	public final class RegisterUserController extends SimpleFormController {

		private final PropertyEditorRegistrar customPropertyEditorRegistrar;

		public RegisterUserController(PropertyEditorRegistrar propertyEditorRegistrar) {
			this.customPropertyEditorRegistrar = propertyEditorRegistrar;
		}

		protected void initBinder(HttpServletRequest request,
				ServletRequestDataBinder binder) throws Exception {
681
			this.customPropertyEditorRegistrar.registerCustomEditors(binder);
682 683 684 685 686 687 688
		}

		// other methods to do with registering a User
	}
----

This style of `PropertyEditor` registration can lead to concise code (the implementation
689 690
of `initBinder(..)` is only one line long) and lets common `PropertyEditor`
registration code be encapsulated in a class and then shared amongst as many
691 692 693 694
`Controllers` as needed.



695

696 697
[[core-convert]]
== Spring Type Conversion
698

699 700 701 702 703
Spring 3 introduced a `core.convert` package that provides a general type conversion
system. The system defines an SPI to implement type conversion logic and an API
to perform type conversions at runtime. Within a Spring container, you can use this system
as an alternative to `PropertyEditor` implementations to convert externalized bean property value
strings to the required property types. You can also use the public API anywhere in your
704 705 706 707 708 709
application where type conversion is needed.



[[core-convert-Converter-API]]
=== Converter SPI
710

711 712
The SPI to implement type conversion logic is simple and strongly typed, as the following
interface definition shows:
713 714 715 716 717 718 719 720 721 722 723 724

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package org.springframework.core.convert.converter;

	public interface Converter<S, T> {

		T convert(S source);
	}
----

725 726 727 728
To create your own converter, implement the `Converter` interface and parameterize `S`
as the type you are converting from and `T` as the type you are converting to. You can also transparently apply such a
converter if a collection or array of `S` needs to be
converted to an array or collection of `T`, provided that a delegating array or collection
729 730
converter has been registered as well (which `DefaultConversionService` does by default).

731 732 733
For each call to `convert(S)`, the source argument is guaranteed to not be null. Your
`Converter` may throw any unchecked exception if conversion fails. Specifically, it should throw an
`IllegalArgumentException` to report an invalid source value.
734 735 736
Take care to ensure that your `Converter` implementation is thread-safe.

Several converter implementations are provided in the `core.convert.support` package as
737 738
a convenience. These include converters from strings to numbers and other common types.
The following listing shows the `StringToInteger` class, which is a typical `Converter` implementation:
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package org.springframework.core.convert.support;

	final class StringToInteger implements Converter<String, Integer> {

		public Integer convert(String source) {
			return Integer.valueOf(source);
		}
	}
----



[[core-convert-ConverterFactory-SPI]]
756
=== Using `ConverterFactory`
757

J
Juergen Hoeller 已提交
758 759
When you need to centralize the conversion logic for an entire class hierarchy
(for example, when converting from `String` to `Enum` objects), you can implement
760
`ConverterFactory`, as the following example shows:
761 762 763 764 765 766 767 768 769 770 771 772 773

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package org.springframework.core.convert.converter;

	public interface ConverterFactory<S, R> {

		<T extends R> Converter<S, T> getConverter(Class<T> targetType);
	}
----

Parameterize S to be the type you are converting from and R to be the base type defining
J
Juergen Hoeller 已提交
774
the __range__ of classes you can convert to. Then implement `getConverter(Class<T>)`,
775 776
where T is a subclass of R.

J
Juergen Hoeller 已提交
777
Consider the `StringToEnumConverterFactory` as an example:
778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package org.springframework.core.convert.support;

	final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {

		public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
			return new StringToEnumConverter(targetType);
		}

		private final class StringToEnumConverter<T extends Enum> implements Converter<String, T> {

			private Class<T> enumType;

			public StringToEnumConverter(Class<T> enumType) {
				this.enumType = enumType;
			}

			public T convert(String source) {
				return (T) Enum.valueOf(this.enumType, source.trim());
			}
		}
	}
----



[[core-convert-GenericConverter-SPI]]
808
=== Using `GenericConverter`
809

J
Juergen Hoeller 已提交
810 811 812 813 814 815 816
When you require a sophisticated `Converter` implementation, consider using the
`GenericConverter` interface. With a more flexible but less strongly typed signature
than `Converter`, a `GenericConverter` supports converting between multiple source and
target types. In addition, a `GenericConverter` makes available source and target field
context that you can use when you implement your conversion logic. Such context lets a
type conversion be driven by a field annotation or by generic information declared on a
field signature. The following listing shows the interface definition of `GenericConverter`:
817 818 819 820 821 822 823 824 825 826 827 828 829 830

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package org.springframework.core.convert.converter;

	public interface GenericConverter {

		public Set<ConvertiblePair> getConvertibleTypes();

		Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
	}
----

831 832 833 834 835
To implement a `GenericConverter`, have `getConvertibleTypes()` return the supported
source->target type pairs. Then implement `convert(Object, TypeDescriptor,
TypeDescriptor)` to contain your conversion logic. The source `TypeDescriptor` provides
access to the source field that holds the value being converted. The target `TypeDescriptor`
provides access to the target field where the converted value is to be set.
836

837 838 839 840 841 842
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 lets each
element in the source array be converted to the collection element type before the
collection is set on the target field.

843 844 845
NOTE: Because `GenericConverter` is a more complex SPI interface, you should use
it only when you need it. Favor `Converter` or `ConverterFactory` for basic type
conversion needs.
846 847 848


[[core-convert-ConditionalGenericConverter-SPI]]
849
==== Using `ConditionalGenericConverter`
850

851 852 853 854
Sometimes, you want a `Converter` to run only if a specific condition holds true. For
example, you might want to run a `Converter` only if a specific annotation is present
on the target field, or you might want to run a `Converter` only if a specific method
(such as a `static valueOf` method) is defined on the target class.
855
`ConditionalGenericConverter` is the union of the `GenericConverter` and
856
`ConditionalConverter` interfaces that lets you define such custom matching criteria:
857 858 859 860

[source,java,indent=0]
[subs="verbatim,quotes"]
----
A
Aviskar Basnet 已提交
861
	public interface ConditionalConverter {
862 863 864

		boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
	}
S
Stephane Nicoll 已提交
865

J
Juergen Hoeller 已提交
866
	public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter {
A
Aviskar Basnet 已提交
867
	}
868 869
----

870 871 872 873
A good example of a `ConditionalGenericConverter` is an `EntityConverter` that converts
between a persistent entity identifier and an entity reference. Such an `EntityConverter`
might match only if the target entity type declares a static finder method (for example,
`findAccount(Long)`). You might perform such a finder method check in the implementation of
874
`matches(TypeDescriptor, TypeDescriptor)`.
875 876 877 878



[[core-convert-ConversionService-API]]
879
=== The `ConversionService` API
880

881 882
`ConversionService` defines a unified API for executing type conversion logic at
runtime. Converters are often executed behind the following facade interface:
883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package org.springframework.core.convert;

	public interface ConversionService {

		boolean canConvert(Class<?> sourceType, Class<?> targetType);

		<T> T convert(Object source, Class<T> targetType);

		boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);

		Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);

	}
----

902 903
Most `ConversionService` implementations also implement `ConverterRegistry`, which
provides an SPI for registering converters. Internally, a `ConversionService`
904 905
implementation delegates to its registered converters to carry out type conversion logic.

906
A robust `ConversionService` implementation is provided in the `core.convert.support`
907 908
package. `GenericConversionService` is the general-purpose implementation suitable for
use in most environments. `ConversionServiceFactory` provides a convenient factory for
909
creating common `ConversionService` configurations.
910 911 912 913



[[core-convert-Spring-config]]
914
=== Configuring a `ConversionService`
915

916 917 918 919 920 921
A `ConversionService` is a stateless object designed to be instantiated at application
startup and then shared between multiple threads. In a Spring application, you typically
configure a `ConversionService` instance for each Spring container (or `ApplicationContext`).
Spring picks up that `ConversionService` and uses it whenever a type
conversion needs to be performed by the framework. You can also inject this
`ConversionService` into any of your beans and invoke it directly.
922

923
NOTE: If no `ConversionService` is registered with Spring, the original `PropertyEditor`-based
924 925
system is used.

926 927
To register a default `ConversionService` with Spring, add the following bean definition
with an `id` of `conversionService`:
928 929 930 931 932 933 934 935

[source,xml,indent=0]
[subs="verbatim,quotes"]
----
	<bean id="conversionService"
		class="org.springframework.context.support.ConversionServiceFactoryBean"/>
----

936
A default `ConversionService` can convert between strings, numbers, enums, collections,
937
maps, and other common types. To supplement or override the default converters with your
938 939
own custom converters, set the `converters` property. Property values can implement
any of the `Converter`, `ConverterFactory`, or `GenericConverter` interfaces.
940 941 942 943 944 945 946 947 948 949 950 951 952 953

[source,xml,indent=0]
[subs="verbatim,quotes"]
----
	<bean id="conversionService"
			class="org.springframework.context.support.ConversionServiceFactoryBean">
		<property name="converters">
			<set>
				<bean class="example.MyCustomConverter"/>
			</set>
		</property>
	</bean>
----

954
It is also common to use a `ConversionService` within a Spring MVC application. See
955
<<web.adoc#mvc-config-conversion, Conversion and Formatting>> in the Spring MVC chapter.
956

957
In certain situations, you may wish to apply formatting during conversion. See
958
<<format-FormatterRegistry-SPI>> for details on using `FormattingConversionServiceFactoryBean`.
959 960 961 962



[[core-convert-programmatic-usage]]
963
=== Using a `ConversionService` Programmatically
964

965 966
To work with a `ConversionService` instance programmatically, you can inject a reference to
it like you would for any other bean. The following example shows how to do so:
967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	@Service
	public class MyService {

		@Autowired
		public MyService(ConversionService conversionService) {
			this.conversionService = conversionService;
		}

		public void doIt() {
			this.conversionService.convert(...)
		}
	}
----

985 986 987 988
For most use cases, you can use the `convert` method that specifies the `targetType`, but it
does not work with more complex types, such as a collection of a parameterized element.
For example, if you want to convert a `List` of `Integer` to a `List` of `String` programmatically,
you need to provide a formal definition of the source and target types.
989

990 991
Fortunately, `TypeDescriptor` provides various options to make doing so straightforward,
as the following example shows:
992 993 994 995 996 997 998 999 1000 1001 1002 1003

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	DefaultConversionService cs = new DefaultConversionService();

	List<Integer> input = ....
	cs.convert(input,
		TypeDescriptor.forObject(input), // List<Integer> type descriptor
		TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class)));
----

1004
Note that `DefaultConversionService` automatically registers converters that are
1005
appropriate for most environments. This includes collection converters, scalar
1006 1007
converters, and basic `Object`-to-`String` converters. You can register the same converters
with any `ConverterRegistry` by using the static `addDefaultConverters`
1008 1009
method on the `DefaultConversionService` class.

1010
Converters for value types are reused for arrays and collections, so there is
1011 1012 1013 1014 1015
no need to create a specific converter to convert from a `Collection` of `S` to a
`Collection` of `T`, assuming that standard collection handling is appropriate.



1016

1017 1018
[[format]]
== Spring Field Formatting
1019

1020
As discussed in the previous section, <<core-convert, `core.convert`>> is a
1021 1022 1023 1024
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
1025
bind field values. For example, when SpEL needs to coerce a `Short` to a `Long` to
1026
complete an `expression.setValue(Object bean, Object value)` attempt, the `core.convert`
1027 1028
system performs the coercion.

1029 1030 1031 1032 1033 1034 1035
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 introduced a convenient `Formatter` SPI that
provides a simple and robust alternative to `PropertyEditor` implementations for client environments.
1036

1037
In general, you can use the `Converter` SPI when you need to implement general-purpose type
J
Juergen Hoeller 已提交
1038 1039 1040 1041
conversion logic -- for example, for converting between a `java.util.Date` and a `Long`.
You can use the `Formatter` SPI when you work 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.
1042 1043 1044 1045



[[format-Formatter-SPI]]
1046
=== The `Formatter` SPI
1047

1048 1049
The `Formatter` SPI to implement field formatting logic is simple and strongly typed. The
following listing shows the `Formatter` interface definition:
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package org.springframework.format;

	public interface Formatter<T> extends Printer<T>, Parser<T> {
	}
----

1060 1061
`Formatter` extends from the `Printer` and `Parser` building-block interfaces. The
following listing shows the definitions of those two interfaces:
1062 1063 1064 1065 1066

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	public interface Printer<T> {
J
Juergen Hoeller 已提交
1067

1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
		String print(T fieldValue, Locale locale);
	}
----

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	import java.text.ParseException;

	public interface Parser<T> {
J
Juergen Hoeller 已提交
1078

1079 1080 1081 1082
		T parse(String clientValue, Locale locale) throws ParseException;
	}
----

1083 1084 1085
To create your own `Formatter`, implement the `Formatter` interface shown earlier.
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
1086
display in the client locale. Implement the `parse()` operation to parse an instance of
1087 1088 1089
`T` from the formatted representation returned from the client locale. Your `Formatter`
should throw a `ParseException` or an `IllegalArgumentException` if a parse attempt fails. Take
care to ensure that your `Formatter` implementation is thread-safe.
1090

1091 1092
The `format` subpackages provide several `Formatter` implementations as a convenience.
The `number` package provides `NumberStyleFormatter`, `CurrencyStyleFormatter`, and
J
Juergen Hoeller 已提交
1093
`PercentStyleFormatter` to format `Number` objects that use a `java.text.NumberFormat`.
1094 1095
The `datetime` package provides a `DateFormatter` to format `java.util.Date` objects with
a `java.text.DateFormat`. The `datetime.joda` package provides comprehensive datetime
J
Juergen Hoeller 已提交
1096
formatting support based on the http://joda-time.sourceforge.net[Joda-Time library].
1097

1098
The following `DateFormatter` is an example `Formatter` implementation:
1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package org.springframework.format.datetime;

	public final class DateFormatter implements Formatter<Date> {

		private String pattern;

		public DateFormatter(String pattern) {
			this.pattern = pattern;
		}

		public String print(Date date, Locale locale) {
			if (date == null) {
				return "";
			}
			return getDateFormat(locale).format(date);
		}

		public Date parse(String formatted, Locale locale) throws ParseException {
			if (formatted.length() == 0) {
				return null;
			}
			return getDateFormat(locale).parse(formatted);
		}

		protected DateFormat getDateFormat(Locale locale) {
			DateFormat dateFormat = new SimpleDateFormat(this.pattern, locale);
			dateFormat.setLenient(false);
			return dateFormat;
		}
	}
----

1135 1136
The Spring team welcomes community-driven `Formatter` contributions. See
https://github.com/spring-projects/spring-framework/issues[GitHub Issues] to contribute.
1137 1138 1139 1140 1141



[[format-CustomFormatAnnotations]]
=== Annotation-driven Formatting
1142

1143 1144 1145
Field formatting can be configured by field type or annotation. To bind
an annotation to a `Formatter`, implement `AnnotationFormatterFactory`. The following
listing shows the definition of the `AnnotationFormatterFactory` interface:
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package org.springframework.format;

	public interface AnnotationFormatterFactory<A extends Annotation> {

		Set<Class<?>> getFieldTypes();

		Printer<?> getPrinter(A annotation, Class<?> fieldType);

		Parser<?> getParser(A annotation, Class<?> fieldType);
	}
----

1162 1163 1164 1165 1166 1167
To create an implementation:
. Parameterize A to be the field `annotationType` with which you wish to associate
formatting  logic -- for example `org.springframework.format.annotation.DateTimeFormat`.
. Have `getFieldTypes()` return the types of fields on which the annotation can be used.
. 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.
1168

1169 1170
The following example `AnnotationFormatterFactory` implementation binds the `@NumberFormat`
annotation to a formatter to let a number style or pattern be
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
specified:

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	public final class NumberFormatAnnotationFormatterFactory
			implements AnnotationFormatterFactory<NumberFormat> {

		public Set<Class<?>> getFieldTypes() {
			return new HashSet<Class<?>>(asList(new Class<?>[] {
				Short.class, Integer.class, Long.class, Float.class,
				Double.class, BigDecimal.class, BigInteger.class }));
		}

		public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
			return configureFormatterFrom(annotation, fieldType);
		}

		public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
			return configureFormatterFrom(annotation, fieldType);
		}

1193
		private Formatter<Number> configureFormatterFrom(NumberFormat annotation, Class<?> fieldType) {
1194
			if (!annotation.pattern().isEmpty()) {
1195
				return new NumberStyleFormatter(annotation.pattern());
1196 1197 1198
			} else {
				Style style = annotation.style();
				if (style == Style.PERCENT) {
1199
					return new PercentStyleFormatter();
1200
				} else if (style == Style.CURRENCY) {
1201
					return new CurrencyStyleFormatter();
1202
				} else {
1203
					return new NumberStyleFormatter();
1204 1205 1206 1207 1208 1209
				}
			}
		}
	}
----

1210 1211
To trigger formatting, you can annotate fields with @NumberFormat, as the following
example shows:
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	public class MyModel {

		@NumberFormat(style=Style.CURRENCY)
		private BigDecimal decimal;
	}
----
1222

1223 1224 1225 1226


[[format-annotations-api]]
==== Format Annotation API
1227

1228
A portable format annotation API exists in the `org.springframework.format.annotation`
J
Juergen Hoeller 已提交
1229 1230 1231
package. You can use `@NumberFormat` to format `Number` fields such as `Double` and
`Long`, and `@DateTimeFormat` to format `java.util.Date`, `java.util.Calendar`, `Long`
(for millisecond timestamps) as well as JSR-310 `java.time` and Joda-Time value types.
1232

1233
The following example uses `@DateTimeFormat` to format a `java.util.Date` as an ISO Date
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248
(yyyy-MM-dd):

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	public class MyModel {

		@DateTimeFormat(iso=ISO.DATE)
		private Date date;
	}
----



[[format-FormatterRegistry-SPI]]
1249
=== The `FormatterRegistry` SPI
1250

1251 1252
The `FormatterRegistry` is an SPI for registering formatters and converters.
`FormattingConversionService` is an implementation of `FormatterRegistry` suitable for
J
Juergen Hoeller 已提交
1253 1254 1255
most environments. You can programmatically or declaratively configure this variant
as a Spring bean, e.g. by using `FormattingConversionServiceFactoryBean`. Because this
implementation also implements `ConversionService`, you can directly configure it
1256
for use with Spring's `DataBinder` and the Spring Expression Language (SpEL).
1257

1258
The following listing shows the `FormatterRegistry` SPI:
1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package org.springframework.format;

	public interface FormatterRegistry extends ConverterRegistry {

		void addFormatterForFieldType(Class<?> fieldType, Printer<?> printer, Parser<?> parser);

		void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter);

		void addFormatterForFieldType(Formatter<?> formatter);

		void addFormatterForAnnotation(AnnotationFormatterFactory<?, ?> factory);
	}
----

1277
As shown in the preceding listing, you can register formatters by field type or by annotation.
1278

1279 1280 1281 1282 1283
The `FormatterRegistry` SPI lets you 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 that 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.
1284 1285 1286 1287



[[format-FormatterRegistrar-SPI]]
1288
=== The `FormatterRegistrar` SPI
1289

1290 1291
`FormatterRegistrar` is an SPI for registering formatters and converters through the
FormatterRegistry. The following listing shows its interface definition:
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	package org.springframework.format;

	public interface FormatterRegistrar {

		void registerFormatters(FormatterRegistry registry);
	}
----

1304 1305 1306 1307 1308
A `FormatterRegistrar` is useful when registering multiple related converters and
formatters for a given formatting category, such as date formatting. It can also be
useful where declarative registration is insufficient -- for example, when a formatter
needs to be indexed under a specific field type different from its own `<T>` or when
registering a `Printer`/`Parser` pair. The next section provides more information on
1309 1310 1311 1312 1313 1314 1315
converter and formatter registration.



[[format-configuring-formatting-mvc]]
=== Configuring Formatting in Spring MVC

1316
See <<web.adoc#mvc-config-conversion, Conversion and Formatting>> in the Spring MVC chapter.
1317 1318 1319



1320

1321
[[format-configuring-formatting-globaldatetimeformat]]
1322
== Configuring a Global Date and Time Format
1323

1324
By default, date and time fields that are not annotated with `@DateTimeFormat` are
1325
converted from strings by using the `DateFormat.SHORT` style. If you prefer, you can
1326 1327
change this by defining your own global format.

1328
To do so, you need to ensure that Spring does not register default formatters. Instead,
1329 1330
you should register all formatters manually. Use the
`org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar` or
1331
`org.springframework.format.datetime.DateFormatterRegistrar` class, depending on whether
J
Juergen Hoeller 已提交
1332
you use the Joda-Time library.
1333

1334 1335
For example, the following Java configuration registers a global `yyyyMMdd`
format (this example does not depend on the Joda-Time library):
1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	@Configuration
	public class AppConfig {

		@Bean
		public FormattingConversionService conversionService() {

			// Use the DefaultFormattingConversionService but do not register defaults
			DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false);

			// Ensure @NumberFormat is still supported
			conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());

			// Register date conversion with a specific global format
			DateFormatterRegistrar registrar = new DateFormatterRegistrar();
			registrar.setFormatter(new DateFormatter("yyyyMMdd"));
			registrar.registerFormatters(conversionService);

			return conversionService;
		}
	}
----

1362 1363 1364
If you prefer XML-based configuration, you can use a
`FormattingConversionServiceFactoryBean`. The following example shows how to do so (this time using Joda
Time):
1365 1366 1367 1368 1369 1370 1371 1372 1373

[source,xml,indent=0]
[subs="verbatim,quotes"]
----
	<?xml version="1.0" encoding="UTF-8"?>
	<beans xmlns="http://www.springframework.org/schema/beans"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:schemaLocation="
			http://www.springframework.org/schema/beans
S
Spring Operator 已提交
1374
			https://www.springframework.org/schema/beans/spring-beans.xsd>
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396

		<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
			<property name="registerDefaultFormatters" value="false" />
			<property name="formatters">
				<set>
					<bean class="org.springframework.format.number.NumberFormatAnnotationFormatterFactory" />
				</set>
			</property>
			<property name="formatterRegistrars">
				<set>
					<bean class="org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar">
						<property name="dateFormatter">
							<bean class="org.springframework.format.datetime.joda.DateTimeFormatterFactoryBean">
								<property name="pattern" value="yyyyMMdd"/>
							</bean>
						</property>
					</bean>
				</set>
			</property>
		</bean>
	</beans>
----
1397 1398 1399

NOTE: Joda-Time provides separate distinct types to represent `date`, `time`, and `date-time`
values. The `dateFormatter`, `timeFormatter`, and `dateTimeFormatter` properties of the
1400 1401 1402
`JodaTimeFormatterRegistrar` should be used to configure the different formats for each
type. The `DateTimeFormatterFactoryBean` provides a convenient way to create formatters.

1403 1404
NOTE: If you use Spring MVC, remember to explicitly configure the conversion service that
is used. For Java-based `@Configuration`, this means extending the
1405
`WebMvcConfigurationSupport` class and overriding the `mvcConversionService()` method.
1406
For XML, you should use the `conversion-service` attribute of the
1407 1408
`mvc:annotation-driven` element.
See <<web.adoc#mvc-config-conversion, Conversion and Formatting>> for details.
1409 1410 1411 1412 1413 1414




[[validation-beanvalidation]]
== Spring Validation
1415

1416 1417 1418
Spring 3 introduced several enhancements to its validation support. First, the JSR-303
Bean Validation API is fully supported. Second, when used programmatically, Spring's
`DataBinder` can validate objects as well as bind to them. Third, Spring MVC has
1419 1420 1421 1422 1423 1424
support for declaratively validating `@Controller` inputs.



[[validation-beanvalidation-overview]]
=== Overview of the JSR-303 Bean Validation API
1425

1426
JSR-303 standardizes validation constraint declaration and metadata for the Java
1427 1428 1429
platform. By using this API, you annotate domain model properties with declarative
validation constraints and the runtime enforces them. You can use a number of built-in
constraints. You can also define your own custom constraints.
1430

1431
Consider the following example, which shows a simple `PersonForm` model with two properties:
1432 1433 1434 1435 1436 1437 1438 1439 1440 1441

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	public class PersonForm {
		private String name;
		private int age;
	}
----

1442 1443
JSR-303 lets you define declarative validation constraints against such properties, as the
following example shows:
1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	public class PersonForm {

		@NotNull
		@Size(max=64)
		private String name;

		@Min(0)
		private int age;
	}
----

1459 1460
When a JSR-303 Validator validates an instance of this class, these constraints
are enforced.
1461

S
Spring Operator 已提交
1462
For general information on JSR-303 and JSR-349, see the https://beanvalidation.org/[Bean
1463 1464
Validation website]. For information on the specific capabilities of the default
reference implementation, see the https://www.hibernate.org/412.html[Hibernate
1465
Validator] documentation. To learn how to set up a bean validation provider as a Spring
1466 1467 1468 1469 1470 1471
bean, keep reading.



[[validation-beanvalidation-spring]]
=== Configuring a Bean Validation Provider
1472

1473
Spring provides full support for the Bean Validation API. This includes convenient
1474 1475 1476
support for bootstrapping a JSR-303 or JSR-349 Bean Validation provider as a Spring bean.
This lets you inject a `javax.validation.ValidatorFactory` or `javax.validation.Validator`
wherever validation is needed in your application.
1477

1478 1479
You can use the `LocalValidatorFactoryBean` to configure a default Validator as a Spring bean,
as the following example shows:
1480 1481 1482 1483 1484 1485 1486 1487

[source,xml,indent=0]
[subs="verbatim,quotes"]
----
	<bean id="validator"
		class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
----

1488 1489 1490
The basic configuration in the preceding example triggers bean validation to initialize by using its
default bootstrap mechanism. A JSR-303 or JSR-349 provider, such as the Hibernate Validator,
is expected to be present in the classpath and is automatically detected.
1491 1492 1493 1494


[[validation-beanvalidation-spring-inject]]
==== Injecting a Validator
1495

1496 1497
`LocalValidatorFactoryBean` implements both `javax.validation.ValidatorFactory` and
`javax.validation.Validator`, as well as Spring's
1498
`org.springframework.validation.Validator`. You can inject a reference to either of
1499 1500
these interfaces into beans that need to invoke validation logic.

1501 1502
You can inject a reference to `javax.validation.Validator` if you prefer to work with the Bean
Validation API directly, as the following example shows:
1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	import javax.validation.Validator;

	@Service
	public class MyService {

		@Autowired
		private Validator validator;
----

1516 1517
You can inject a reference to `org.springframework.validation.Validator` if your bean requires
the Spring Validation API, as the following example shows:
1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	import org.springframework.validation.Validator;

	@Service
	public class MyService {

		@Autowired
		private Validator validator;
	}
----
1531

1532 1533 1534

[[validation-beanvalidation-spring-constraints]]
==== Configuring Custom Constraints
1535

1536 1537 1538 1539
Each bean validation constraint consists of two parts:
* A `@Constraint` annotation
that declares the constraint and its configurable properties.
* An implementation
1540
of the `javax.validation.ConstraintValidator` interface that implements the constraint's
1541 1542 1543
behavior.

To associate a declaration with an implementation, each `@Constraint` annotation
S
Stephane Nicoll 已提交
1544
references a corresponding `ConstraintValidator` implementation class. At runtime, a
1545 1546 1547 1548
`ConstraintValidatorFactory` instantiates the referenced implementation when the
constraint annotation is encountered in your domain model.

By default, the `LocalValidatorFactoryBean` configures a `SpringConstraintValidatorFactory`
1549 1550
that uses Spring to create `ConstraintValidator` instances. This lets your custom
`ConstraintValidators` benefit from dependency injection like any other Spring bean.
1551

1552
The following example shows a custom `@Constraint` declaration followed by an associated
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578
`ConstraintValidator` implementation that uses Spring for dependency injection:

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	@Target({ElementType.METHOD, ElementType.FIELD})
	@Retention(RetentionPolicy.RUNTIME)
	@Constraint(validatedBy=MyConstraintValidator.class)
	public @interface MyConstraint {
	}
----

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	import javax.validation.ConstraintValidator;

	public class MyConstraintValidator implements ConstraintValidator {

		@Autowired;
		private Foo aDependency;

		...
	}
----

1579 1580
As the preceding example shows, a `ConstraintValidator` implementation can have its dependencies
`@Autowired` as any other Spring bean.
1581 1582 1583 1584


[[validation-beanvalidation-spring-method]]
==== Spring-driven Method Validation
1585

1586 1587 1588
You can integrate the method validation feature supported by Bean Validation 1.1 (and, as a custom
extension, also by Hibernate Validator 4.3) into a Spring context
through a `MethodValidationPostProcessor` bean definition, as follows:
1589 1590 1591 1592 1593 1594 1595

[source,xml,indent=0]
[subs="verbatim,quotes"]
----
	<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
----

1596 1597 1598 1599
To be eligible for Spring-driven method validation, all target classes need to be annotated with
Spring's `@Validated` annotation. (Optionally, you can also declare the validation groups to use.)
See the {api-spring-framework}/validation/beanvalidation/MethodValidationPostProcessor.html[`MethodValidationPostProcessor`]
javadoc for setup details with the Hibernate Validator and Bean Validation 1.1 providers.
1600 1601 1602 1603


[[validation-beanvalidation-spring-other]]
==== Additional Configuration Options
1604

1605
The default `LocalValidatorFactoryBean` configuration suffices for most
1606 1607
cases. There are a number of configuration options for various Bean Validation
constructs, from message interpolation to traversal resolution. See the
1608 1609
{api-spring-framework}/validation/beanvalidation/LocalValidatorFactoryBean.html[`LocalValidatorFactoryBean`]
javadoc for more information on these options.
1610 1611 1612 1613



[[validation-binder]]
1614
=== Configuring a `DataBinder`
1615

1616 1617 1618
Since Spring 3, you can configure a `DataBinder` instance with a `Validator`. Once
configured, you can invoke the `Validator` by calling `binder.validate()`. Any validation
`Errors` are automatically added to the binder's `BindingResult`.
1619

1620
The following example shows how to use a `DataBinder` programmatically to invoke validation
1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639
logic after binding to a target object:

[source,java,indent=0]
[subs="verbatim,quotes"]
----
	Foo target = new Foo();
	DataBinder binder = new DataBinder(target);
	binder.setValidator(new FooValidator());

	// bind to the target object
	binder.bind(propertyValues);

	// validate the target object
	binder.validate();

	// get BindingResult that includes any validation errors
	BindingResult results = binder.getBindingResult();
----

1640
You can also configure a `DataBinder` with multiple `Validator` instances through
1641
`dataBinder.addValidators` and `dataBinder.replaceValidators`. This is useful when
1642
combining globally configured bean validation with a Spring `Validator` configured
1643 1644 1645 1646 1647 1648 1649
locally on a DataBinder instance. See <<validation-mvc-configuring>>.



[[validation-mvc]]
=== Spring MVC 3 Validation

1650
See <<web.adoc#mvc-config-validation, Validation>> in the Spring MVC chapter.