Skip to content

Commit cb2fd92

Browse files
Improve validation errors docs
1 parent ffe2e95 commit cb2fd92

1 file changed

Lines changed: 52 additions & 6 deletions

File tree

docs/04-problem4j-spring/04-validation-errors.md

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ Library overrides default responses for `jakarta.validation` exceptions for both
2424
}
2525
```
2626

27+
## Adapted Constraint Violations
28+
2729
More notably, for `@RequestParam`, `@RequestHeader` etc., there's a tweak that comes from settings configuration
2830
property `spring.validation.method.adapt-constraint-violations` to `true`. Enabling it, switches default validation to
2931
not rely on raw `ConstraintViolationException`, but rather on `MethodValidationException`, which contains more details
@@ -36,9 +38,10 @@ knowledge about internal technologies used by backend.
3638
```java
3739
@Validated
3840
@RestController
39-
static class RequestParamController {
40-
@GetMapping("/orders")
41-
String endpoint(@RequestParam("customerId") @Size(min = 5, max = 30) String customerIdParam) {
41+
public class RequestParamController {
42+
43+
@GetMapping("/endpoint") // note that query param in annotation different name from method param
44+
public String endpoint(@Size(min = 5, max = 30) @RequestParam("customerId") String customerIdParam) {
4245
return "OK";
4346
}
4447
}
@@ -76,15 +79,14 @@ same goes for `@PathVariable`, `@RequestHeader`, `@CookieValue` etc.).
7679
[`MethodValidationProblemResolver`][MethodValidationProblemResolver] contains implementation of retrieving configured
7780
values from parameter annotations.
7881

79-
---
80-
8182
> For Spring Boot versions lower than `3.5`, the above-mentioned property is not available and one must configure it
8283
> programmatically. Consider checking up `org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration`
8384
> and [Method Validation Exceptions][method-validation-exceptions] chapter of Spring Framework documentation.
8485
>
8586
> ```java
8687
> @Configuration
8788
> public class ExampleConfiguration {
89+
>
8890
> @Bean
8991
> public MethodValidationPostProcessor methodValidationPostProcessor() {
9092
> MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
@@ -96,11 +98,55 @@ values from parameter annotations.
9698
9799
Method `setAdaptConstraintViolations` is available since Spring Framework `6.1` (therefore since Spring Boot `3.2`).
98100
99-
---
101+
## Supporting `@ModelAttribute` and `@BindParam`
100102
101103
Similarly, for `@ModelAttribute` method arguments (object that groups query or form params), violation field names are
102104
resolved from `@BindParam` annotation if present on canonical constructor parameters.
103105
106+
Let's see the following example.
107+
108+
```java
109+
public class QueryBindObject {
110+
111+
@Size(min = 1, max = 5)
112+
private final String text;
113+
114+
@Positive
115+
private final Integer number;
116+
117+
public QueryBindObject(String text, @BindParam("num") Integer number) {
118+
this.text = text;
119+
this.number = number;
120+
}
121+
122+
// ...
123+
}
124+
```
125+
126+
Given `QueryBindObject`, declares, that a `num` query parameter will be resolved into `number` constructor argument.
127+
Therefore, for violation of that field name, we would like error to point to `num` field as being invalid instead of
128+
`number`.
129+
130+
```java
131+
@Validated
132+
@RestController
133+
public class RequestParamController {
134+
135+
@GetMapping(path = "/endpoint")
136+
public String endpoint(@ModelAttribute @Valid QueryBindObject query) {
137+
return "OK";
138+
}
139+
}
140+
```
141+
142+
While resolving constraint violation error, Problem4J will resolve `@BindParam` annotations present on canonical
143+
constructor of `@ModelAttribute`-annotated request argument. Node that if there's no annotation on controller method,
144+
Spring automatically assumes it to be a `@ModelAttribute`.
145+
146+
**Note** that given object must have exactly one, full-args constructor if it is an ordinary `class`. If multiple
147+
constructors are present, Problem4J will skip evaluation of `@BindParam`. If it is a `record`, then actual arguments
148+
will be taken from **record's canonical constructor**, and additional constructors are ignored.
149+
104150
[MethodValidationProblemResolver]: https://github.com/problem4j/problem4j-spring/blob/v2.1.0/problem4j-spring-web/src/main/java/io/github/problem4j/spring/web/resolver/MethodValidationProblemResolver.java
105151
106152
[method-validation-exceptions]: https://docs.spring.io/spring-framework/reference/core/validation/beanvalidation.html#validation-beanvalidation-spring-method-exceptions

0 commit comments

Comments
 (0)