From 3d33cf37649d6000c679ff2763c1e47a702c4365 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 16 Jan 2020 15:42:15 +0000 Subject: [PATCH] Updates to Validation section in reference Closes gh-24338 --- src/docs/asciidoc/core/core-validation.adoc | 157 ++++++++++++-------- 1 file changed, 94 insertions(+), 63 deletions(-) diff --git a/src/docs/asciidoc/core/core-validation.adoc b/src/docs/asciidoc/core/core-validation.adoc index 7b34fe64099a..ee2c5245c620 100644 --- a/src/docs/asciidoc/core/core-validation.adoc +++ b/src/docs/asciidoc/core/core-validation.adoc @@ -5,14 +5,14 @@ There are pros and cons for considering validation as business logic, and Spring a design for validation (and data binding) that does not exclude either one of them. Specifically, validation should not be tied to the web tier and should be easy to localize, and it should be possible to plug in any available validator. Considering these concerns, -Spring has come up with a `Validator` interface that is both basic and eminently usable +Spring provides a `Validator` contract that is both basic and eminently usable in every layer of an application. Data binding is useful for letting user input be dynamically bound to the domain model of an application (or whatever objects you use to process user input). Spring provides the aptly named `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. +limited to the web layer. The `BeanWrapper` is a fundamental concept in the Spring Framework and is used in a lot of places. However, you probably do not need to use the `BeanWrapper` @@ -28,19 +28,12 @@ general type conversion facility, as well as a higher-level "`format`" package f formatting UI field values. You can use these packages as simpler alternatives to `PropertyEditorSupport` implementations. They are also discussed in this chapter. -.JSR-303/JSR-349 Bean Validation -**** -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. - -An application can choose to enable Bean Validation once globally, as described in -<>, and use it exclusively for all validation needs. - -An application can also register additional Spring `Validator` instances for each -`DataBinder` instance, as described in <>. This may be useful for -plugging in validation logic without the use of annotations. -**** +Spring supports Java Bean Validation through setup infrastructure and an adaptor to +Spring's own `Validator` contract. Application can enable Bean Validation once globally, +as described in <>, and use it exclusively for all validation +needs. In the web layer, they can further register controller-local local Spring +`Validator` instances per `DataBinder`, as described in <>, which can +be useful for plugging in custom validation logic creating annotations. @@ -1811,22 +1804,20 @@ See <> for details. [[validation-beanvalidation]] -== Spring Validation +== Java Bean Validation -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 -support for declaratively validating `@Controller` inputs. +The Spring Framework provides support for the +https://beanvalidation.org/[Java Bean Validation] API. [[validation-beanvalidation-overview]] -=== Overview of the JSR-303 Bean Validation API +=== Overview of Bean Validation -JSR-303 standardizes validation constraint declaration and metadata for the Java -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. +Bean Validation provides a common way of validation through constraint declaration and +metadata for Java applications. To use it, you annotate domain model properties with +declarative validation constraints which are then enforced by the runtime. There are +built-in constraints, and you can also define your own custom constraints. Consider the following example, which shows a simple `PersonForm` model with two properties: @@ -1847,8 +1838,7 @@ Consider the following example, which shows a simple `PersonForm` model with two ) ---- -JSR-303 lets you define declarative validation constraints against such properties, as the -following example shows: +Bean Validation lets you declare constraints as the following example shows: [source,java,indent=0,subs="verbatim,quotes",role="primary"] .Java @@ -1874,13 +1864,10 @@ following example shows: ) ---- -When a JSR-303 Validator validates an instance of this class, these constraints -are enforced. - -For general information on JSR-303 and JSR-349, see the https://beanvalidation.org/[Bean -Validation website]. For information on the specific capabilities of the default -reference implementation, see the https://www.hibernate.org/412.html[Hibernate -Validator] documentation. To learn how to set up a bean validation provider as a Spring +A Bean Validation validator then validates instances of this class based on the declared +constraints. See https://beanvalidation.org/[Bean Validation] for general information about +the API. See the https://hibernate.org/validator/[Hibernate Validator] documentation for +specific constraints. To learn how to set up a bean validation provider as a Spring bean, keep reading. @@ -1888,32 +1875,48 @@ bean, keep reading. [[validation-beanvalidation-spring]] === Configuring a Bean Validation Provider -Spring provides full support for the Bean Validation API. This includes convenient -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. +Spring provides full support for the Bean Validation API including the bootstrapping of a +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. -You can use the `LocalValidatorFactoryBean` to configure a default Validator as a Spring bean, -as the following example shows: +You can use the `LocalValidatorFactoryBean` to configure a default Validator as a Spring +bean, as the following example shows: -[source,xml,indent=0,subs="verbatim,quotes"] +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +.Java +---- + import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; + + @Configuration + + public class AppConfig { + + @Bean + public LocalValidatorFactoryBean validator() { + return new LocalValidatorFactoryBean; + } + } +---- +[source,xml,indent=0,subs="verbatim,quotes",role="secondary"] +.XML ---- ---- -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. +The basic configuration in the preceding example triggers bean validation to initialize by +using its default bootstrap mechanism. A Bean Validation provider, such as the Hibernate +Validator, is expected to be present in the classpath and is automatically detected. [[validation-beanvalidation-spring-inject]] ==== Injecting a Validator `LocalValidatorFactoryBean` implements both `javax.validation.ValidatorFactory` and -`javax.validation.Validator`, as well as Spring's -`org.springframework.validation.Validator`. You can inject a reference to either of -these interfaces into beans that need to invoke validation logic. +`javax.validation.Validator`, as well as Spring's `org.springframework.validation.Validator`. +You can inject a reference to either of these interfaces into beans that need to invoke +validation logic. 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: @@ -1939,8 +1942,8 @@ Validation API directly, as the following example shows: class MyService(@Autowired private val validator: Validator) ---- -You can inject a reference to `org.springframework.validation.Validator` if your bean requires -the Spring Validation API, as the following example shows: +You can inject a reference to `org.springframework.validation.Validator` if your bean +requires the Spring Validation API, as the following example shows: [source,java,indent=0,subs="verbatim,quotes",role="primary"] .Java @@ -1968,11 +1971,9 @@ the Spring Validation API, as the following example shows: ==== Configuring Custom Constraints Each bean validation constraint consists of two parts: -* A `@Constraint` annotation -that declares the constraint and its configurable properties. -* An implementation -of the `javax.validation.ConstraintValidator` interface that implements the constraint's -behavior. +* A `@Constraint` annotation that declares the constraint and its configurable properties. +* An implementation of the `javax.validation.ConstraintValidator` interface that implements +the constraint's behavior. To associate a declaration with an implementation, each `@Constraint` annotation references a corresponding `ConstraintValidator` implementation class. At runtime, a @@ -2036,19 +2037,48 @@ As the preceding example shows, a `ConstraintValidator` implementation can have [[validation-beanvalidation-spring-method]] ==== Spring-driven Method Validation -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: +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: -[source,xml,indent=0,subs="verbatim,quotes"] +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +.Java +---- + import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; + + @Configuration + + public class AppConfig { + + @Bean + public MethodValidationPostProcessor validationPostProcessor() { + return new MethodValidationPostProcessor; + } + } + +---- +[source,xml,indent=0,subs="verbatim,quotes",role="secondary"] +.XML ---- ---- -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. +To be eligible for Spring-driven method validation, all target classes need to be annotated +with Spring's `@Validated` annotation, which can optionally also declare the validation +groups to use. See +{api-spring-framework}/validation/beanvalidation/MethodValidationPostProcessor.html[`MethodValidationPostProcessor`] +for setup details with the Hibernate Validator and Bean Validation 1.1 providers. + +[TIP] +==== +Method validation relies on <> around the +target classes, either JDK dynamic proxies for methods on interfaces or CGLIB proxies. +There are certain limitations with the use of proxies, some of which are described in +<>. In addition remember +to always use methods and accessors on proxied classes; direct field access will not work. +==== + + [[validation-beanvalidation-spring-other]] @@ -2108,7 +2138,8 @@ logic after binding to a target object: You can also configure a `DataBinder` with multiple `Validator` instances through `dataBinder.addValidators` and `dataBinder.replaceValidators`. This is useful when combining globally configured bean validation with a Spring `Validator` configured -locally on a DataBinder instance. See <>. +locally on a DataBinder instance. See +<>.