Skip to content

Commit f910c06

Browse files
committed
Create avaje-validator.adoc
1 parent d099beb commit f910c06

1 file changed

Lines changed: 274 additions & 0 deletions

File tree

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
== Avaje Validator
2+
3+
Bean validation via https://avaje.io/validator/[Avaje Validator].
4+
5+
=== Usage
6+
7+
1) Add the dependency:
8+
9+
[dependency, artifactId="jooby-avaje-validator"]
10+
.
11+
12+
2) Install
13+
14+
.Java
15+
[source, java, role="primary"]
16+
----
17+
import io.jooby.avaje.validator.AvajeValidatorModule;
18+
19+
{
20+
install(new AvajeValidatorModule());
21+
}
22+
----
23+
24+
.Kotlin
25+
[source, kt, role="secondary"]
26+
----
27+
import io.jooby.avaje.validator.AvajeValidatorModule
28+
29+
{
30+
install(new AvajeValidatorModule())
31+
}
32+
----
33+
34+
3) Usage in MVC routes
35+
36+
.Java
37+
[source,java,role="primary"]
38+
----
39+
import io.jooby.annotation.*;
40+
import jakarta.validation.Valid;
41+
42+
@Path("/mvc")
43+
public class Controller {
44+
45+
@POST("/validate-body")
46+
public void validateBody(@Valid Bean bean) { // <1>
47+
...
48+
}
49+
50+
@POST("/validate-query")
51+
public void validateQuery(@Valid @QueryParam Bean bean) { // <2>
52+
...
53+
}
54+
55+
@POST("/validate-list")
56+
public void validateList(@Valid List<Bean> beans) { // <3>
57+
...
58+
}
59+
60+
@POST("/validate-map")
61+
public void validateMap(@Valid Map<String, Bean> beans) { // <4>
62+
...
63+
}
64+
}
65+
----
66+
67+
.Kotlin
68+
[source, kt, role="secondary"]
69+
----
70+
import io.jooby.annotation.*;
71+
import jakarta.validation.Valid
72+
73+
@Path("/mvc")
74+
class Controller {
75+
76+
@POST("/validate-body")
77+
fun validateBody(@Valid bean: Bean) : Unit { // <1>
78+
...
79+
}
80+
81+
@POST("/validate-query")
82+
fun validateQuery(@Valid @QueryParam bean: Bean) : Unit { // <2>
83+
...
84+
}
85+
86+
@POST("/validate-list")
87+
fun validateList(@Valid beans: List<Bean>) : Unit { // <3>
88+
...
89+
}
90+
91+
@POST("/validate-map")
92+
fun validateMap(@Valid beans: Map<String, Bean>) : Unit { // <4>
93+
...
94+
}
95+
}
96+
----
97+
98+
<1> Validate a bean decoded from the request body
99+
<2> Validate a bean parsed from query parameters. This works the same for `@FormParam` or `@BindParam`
100+
<3> Validate a list of beans. This also applies to arrays `@Valid Bean[] beans`
101+
<4> Validate a map of beans
102+
103+
4) Usage in in script/lambda routes
104+
105+
Jooby doesn't provide fully native bean validation in script/lambda at the moment,
106+
but you can use a helper that we utilize under the hood in MVC routes:
107+
108+
.Java
109+
[source, java, role="primary"]
110+
----
111+
import io.jooby.validation.BeanValidator;
112+
113+
{
114+
post("/validate", ctx -> {
115+
Bean bean = BeanValidator.validate(ctx, ctx.body(Bean.class));
116+
...
117+
});
118+
}
119+
----
120+
121+
.Kotlin
122+
[source, kt, role="secondary"]
123+
----
124+
import io.jooby.validation.BeanValidator
125+
126+
{
127+
post("/validate") {
128+
val bean = BeanValidator.validate(ctx, ctx.body(Bean.class))
129+
...
130+
}
131+
}
132+
----
133+
134+
`BeanValidator.validate()` behaves identically to validation in MVC routes.
135+
It also supports validating list, array, and map of beans
136+
137+
=== Constraint Violations Rendering
138+
139+
`AvajeValidatorModule` provides default built-in error handler that
140+
catches `ConstraintViolationException` and transforms it into the following response:
141+
142+
.JSON:
143+
----
144+
{
145+
"title": "Validation failed",
146+
"status": 422,
147+
"errors": [
148+
{
149+
"field": "firstName",
150+
"messages": [
151+
"must not be empty",
152+
"must not be null"
153+
],
154+
"type": "FIELD"
155+
},
156+
{
157+
"field": null,
158+
"messages": [
159+
"passwords are not the same"
160+
],
161+
"type": "GLOBAL"
162+
}
163+
]
164+
}
165+
----
166+
167+
It is possible to override the `title` and `status` code of the response above:
168+
169+
[source, java]
170+
----
171+
172+
{
173+
install(new AvajeJsonbModule());
174+
install(new AvajeValidatorModule()
175+
.statusCode(StatusCode.BAD_REQUEST)
176+
.validationTitle("Incorrect input data")
177+
);
178+
}
179+
----
180+
181+
If the default error handler doesn't fully meet your needs, you can always disable it and provide your own:
182+
183+
[source, java]
184+
----
185+
186+
{
187+
install(new AvajeJsonbModule());
188+
install(new AvajeValidatorModule().disableViolationHandler());
189+
190+
error(ConstraintViolationException.class, new MyConstraintViolationHandler());
191+
}
192+
----
193+
194+
=== Manual Validation
195+
196+
The module exposes `Validator` as a service, allowing you to run validation manually at any time.
197+
198+
==== Script/lambda:
199+
200+
[source, java]
201+
----
202+
import io.avaje.validation.Validator;
203+
204+
{
205+
post("/validate", ctx -> {
206+
Validator validator = require(Validator.class);
207+
validator.validate(ctx.body(Bean.class));
208+
...
209+
});
210+
}
211+
----
212+
213+
==== MVC routes with dependency injection:
214+
215+
1) Install DI framework at first.
216+
217+
[source, java]
218+
----
219+
import io.jooby.avaje.validator.AvajeValidatorModule;
220+
221+
{
222+
install(AvajeInjectModule.of()); // <1>
223+
install(new AvajeValidatorModule());
224+
}
225+
----
226+
227+
<1> `Avaje` is just an example, you can achieve the same with `Dagger` or `Guice`
228+
229+
2) Inject `Validator` in controller, service etc.
230+
231+
[source, java]
232+
----
233+
import io.avaje.validation.Validator;
234+
import jakarta.inject.Inject;
235+
236+
@Path("/mvc")
237+
public class Controller {
238+
239+
private final Validator validator;
240+
241+
@Inject
242+
public Controller(Validator validator) {
243+
this.validator = validator;
244+
}
245+
246+
@POST("/validate")
247+
public void validate(Bean bean) {
248+
Set<ConstraintViolation<Bean>> violations = validator.validate(bean);
249+
...
250+
}
251+
}
252+
----
253+
254+
=== Configuration
255+
Any property defined at `validation` will be added automatically:
256+
257+
.application.conf
258+
[source, properties]
259+
----
260+
validation.fail_fast = true
261+
----
262+
263+
Or programmatically:
264+
265+
[source, java]
266+
----
267+
import io.jooby.avaje.validator.AvajeValidatorModule;
268+
269+
{
270+
install(new AvajeValidatorModule().doWith(cfg -> {
271+
cfg.failFast(true);
272+
}));
273+
}
274+
----

0 commit comments

Comments
 (0)