Skip to content

Commit 8036045

Browse files
committed
Add another example for a constraint validator with an injected bean
1 parent 8b6a34f commit 8036045

File tree

9 files changed

+137
-1
lines changed

9 files changed

+137
-1
lines changed

docs/src/main/asciidoc/validation.adoc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,42 @@ The scope you choose for your `ConstraintValidator` bean is important:
411411
- If the `ConstraintValidator` bean implements the `initialize(A constraintAnnotation)` method and depends on the state of the constraint annotation, use the `@Dependent` scope to make sure each annotation context has a separate and properly configured instance of the `ConstraintValidator` bean.
412412
====
413413

414+
When injecting beans relying on the runtime configuration, use `@Inject Instance<..>`. In this case it also won't be possible to
415+
preconfigure the constraint in the `initialize(..)` method, as the injected instance will not be in the required state.
416+
Hence, it is recommended that any heavy configuration work happens as part of the injected bean initialisation
417+
and methods used in the `ConstraintValidator#isValid(..)` implementation are as fast as possible:
418+
419+
[source,java]
420+
----
421+
@ApplicationScoped
422+
public class MyConstraintValidator implements ConstraintValidator<MyConstraint, String> {
423+
424+
@Inject
425+
Instance<MyService> service;
426+
427+
@Override
428+
public boolean isValid(String value, ConstraintValidatorContext context) {
429+
if (value == null) {
430+
return true;
431+
}
432+
433+
return service.get().validate(value);
434+
}
435+
}
436+
437+
@ApplicationScoped
438+
public class MyService {
439+
440+
public MyService(..) {
441+
// perform all possible "initialisation" work
442+
}
443+
444+
public boolean validate(String value) {
445+
// perform the validation
446+
}
447+
}
448+
----
449+
414450
=== Validation and localization
415451

416452
By default, constraint violation messages will be returned in the build system locale.

integration-tests/hibernate-validator/src/main/java/io/quarkus/it/hibernate/validator/HibernateValidatorTestResource.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import io.quarkus.it.hibernate.validator.groups.MyBeanWithGroups;
4646
import io.quarkus.it.hibernate.validator.groups.ValidationGroups;
4747
import io.quarkus.it.hibernate.validator.injection.InjectedConstraintValidatorConstraint;
48+
import io.quarkus.it.hibernate.validator.injection.InjectedRuntimeConstraintValidatorConstraint;
4849
import io.quarkus.it.hibernate.validator.injection.MyService;
4950
import io.quarkus.it.hibernate.validator.orm.TestEntity;
5051
import io.quarkus.runtime.StartupEvent;
@@ -199,6 +200,12 @@ public String testInjection() {
199200

200201
result.append(formatViolations(validator.validate(new BeanWithInjectedConstraintValidatorConstraint("Invalid value"))));
201202

203+
result.append(formatViolations(
204+
validator.validate(new BeanWithInjectedRuntimeConstraintValidatorConstraint("any text is valid"))));
205+
206+
result.append(formatViolations(
207+
validator.validate(new BeanWithInjectedRuntimeConstraintValidatorConstraint("numbers 12345 don't work"))));
208+
202209
return result.build();
203210
}
204211

@@ -432,6 +439,20 @@ public String getValue() {
432439
}
433440
}
434441

442+
public static class BeanWithInjectedRuntimeConstraintValidatorConstraint {
443+
444+
@InjectedRuntimeConstraintValidatorConstraint
445+
private String value;
446+
447+
public BeanWithInjectedRuntimeConstraintValidatorConstraint(String value) {
448+
this.value = value;
449+
}
450+
451+
public String getValue() {
452+
return value;
453+
}
454+
}
455+
435456
@Target(ElementType.METHOD)
436457
@Retention(RetentionPolicy.RUNTIME)
437458
@InterceptorBinding
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.quarkus.it.hibernate.validator.injection;
2+
3+
import jakarta.enterprise.context.ApplicationScoped;
4+
import jakarta.enterprise.inject.Instance;
5+
import jakarta.inject.Inject;
6+
import jakarta.validation.ConstraintValidator;
7+
import jakarta.validation.ConstraintValidatorContext;
8+
9+
@ApplicationScoped
10+
public class InjectedRuntimeConstraintValidator
11+
implements ConstraintValidator<InjectedRuntimeConstraintValidatorConstraint, String> {
12+
13+
@Inject
14+
Instance<MyRuntimeService> service;
15+
16+
@Override
17+
public boolean isValid(String value, ConstraintValidatorContext context) {
18+
if (value == null) {
19+
return true;
20+
}
21+
22+
return service.get().validate(value);
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package io.quarkus.it.hibernate.validator.injection;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
import jakarta.validation.Constraint;
9+
import jakarta.validation.Payload;
10+
11+
@Target({ ElementType.TYPE_USE, ElementType.FIELD })
12+
@Retention(RetentionPolicy.RUNTIME)
13+
@Constraint(validatedBy = { InjectedRuntimeConstraintValidator.class })
14+
public @interface InjectedRuntimeConstraintValidatorConstraint {
15+
16+
String message() default "{InjectedRuntimeConstraintValidatorConstraint.message}";
17+
18+
Class<?>[] groups() default {};
19+
20+
Class<? extends Payload>[] payload() default {};
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package io.quarkus.it.hibernate.validator.injection;
2+
3+
import io.smallrye.config.ConfigMapping;
4+
5+
@ConfigMapping(prefix = "io.quarkus.it.hibernate.validator.injection")
6+
public interface MyRuntimeConfiguration {
7+
8+
String pattern();
9+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package io.quarkus.it.hibernate.validator.injection;
2+
3+
import java.util.regex.Pattern;
4+
5+
import jakarta.enterprise.context.ApplicationScoped;
6+
import jakarta.inject.Inject;
7+
8+
@ApplicationScoped
9+
public class MyRuntimeService {
10+
11+
private final Pattern pattern;
12+
13+
@Inject
14+
public MyRuntimeService(MyRuntimeConfiguration configuration) {
15+
this.pattern = Pattern.compile(configuration.pattern());
16+
}
17+
18+
public boolean validate(String value) {
19+
return pattern.matcher(value).matches();
20+
}
21+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
MyCustomConstraint.message = invalid MyOtherBean
22
InjectedConstraintValidatorConstraint.message = InjectedConstraintValidatorConstraint violation
3+
InjectedRuntimeConstraintValidatorConstraint.message = InjectedRuntimeConstraintValidatorConstraint violation
34
pattern.message=Value is not in line with the pattern

integration-tests/hibernate-validator/src/main/resources/application.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ quarkus.datasource.db-kind=h2
44
quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test
55
quarkus.hibernate-orm.database.generation = drop-and-create
66

7+
io.quarkus.it.hibernate.validator.injection.pattern=[^0-9]++

integration-tests/hibernate-validator/src/test/java/io/quarkus/it/hibernate/validator/HibernateValidatorFunctionalityTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,9 @@ public void testNoProduces() {
325325
public void testInjection() throws Exception {
326326
StringBuilder expected = new StringBuilder();
327327
expected.append("passed").append("\n");
328-
expected.append("failed: value (InjectedConstraintValidatorConstraint violation)");
328+
expected.append("failed: value (InjectedConstraintValidatorConstraint violation)\n");
329+
expected.append("passed").append("\n");
330+
expected.append("failed: value (InjectedRuntimeConstraintValidatorConstraint violation)");
329331

330332
RestAssured.when()
331333
.get("/hibernate-validator/test/injection")

0 commit comments

Comments
 (0)