Skip to content

Commit b03b810

Browse files
authored
Merge pull request quarkusio#49990 from marko-bekhta/fix/i49987-traversable-resolver-for-validatevalue
Account for the null root bean when performing value validation
2 parents 6db69c8 + 9751ce1 commit b03b810

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package io.quarkus.hibernate.orm.validation;
2+
3+
import java.util.Set;
4+
5+
import jakarta.enterprise.context.ApplicationScoped;
6+
import jakarta.inject.Inject;
7+
import jakarta.validation.ConstraintViolation;
8+
import jakarta.validation.Validator;
9+
import jakarta.validation.constraints.NotNull;
10+
import jakarta.ws.rs.GET;
11+
import jakarta.ws.rs.Path;
12+
13+
@Path("/validation/nonentity")
14+
@ApplicationScoped
15+
public class JPATestValidationOfNonEntitiesResource {
16+
17+
@Inject
18+
Validator validator;
19+
20+
@Path("/bean")
21+
@GET
22+
public String bean() {
23+
Set<ConstraintViolation<MyNonEntity>> constraintViolations = validator.validate(new MyNonEntity());
24+
if (constraintViolations.size() != 1) {
25+
return "ko";
26+
}
27+
if (!constraintViolations.iterator().next().getPropertyPath().toString().equals("name")) {
28+
return "ko";
29+
}
30+
return "ok";
31+
}
32+
33+
@Path("/value")
34+
@GET
35+
public String value() {
36+
Set<ConstraintViolation<MyNonEntity>> constraintViolations = validator.validateValue(MyNonEntity.class, "name", null);
37+
if (constraintViolations.size() != 1) {
38+
return "ko";
39+
}
40+
if (!constraintViolations.iterator().next().getPropertyPath().toString().equals("name")) {
41+
return "ko";
42+
}
43+
return "ok";
44+
}
45+
46+
public static class MyNonEntity {
47+
@NotNull
48+
public String name;
49+
}
50+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package io.quarkus.hibernate.orm.validation;
2+
3+
import static org.hamcrest.Matchers.is;
4+
5+
import org.jboss.shrinkwrap.api.asset.StringAsset;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.extension.RegisterExtension;
8+
9+
import io.quarkus.hibernate.orm.MyEntity;
10+
import io.quarkus.test.QuarkusUnitTest;
11+
import io.restassured.RestAssured;
12+
13+
public class JPATestValidationOfNonEntitiesTestCase {
14+
15+
@RegisterExtension
16+
static QuarkusUnitTest runner = new QuarkusUnitTest()
17+
.withApplicationRoot((jar) -> jar
18+
.addClasses(MyEntity.class, JPATestValidationOfNonEntitiesResource.class)
19+
.addAsResource("application.properties")
20+
.addAsResource(new StringAsset(""), "import.sql")); // define an empty import.sql file
21+
22+
@Test
23+
public void testValueValidation() {
24+
RestAssured.given().when().get("validation/nonentity/value").then()
25+
.body(is("ok"));
26+
}
27+
28+
@Test
29+
public void testBeanValidation() {
30+
RestAssured.given().when().get("validation/nonentity/bean").then()
31+
.body(is("ok"));
32+
}
33+
}

extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/HibernateValidatorRecorder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,11 @@ static final class DelegatingTraversableResolver implements TraversableResolver
306306
@Override
307307
public boolean isReachable(Object entity, Path.Node traversableProperty, Class<?> rootBeanType,
308308
Path pathToTraversableObject, ElementType elementType) {
309+
if (entity == null) {
310+
// The entity can be null if we are validating values, as that's when the validation context does not have the root object,
311+
// In other cases we shouldn't even reach the traversable resolver when the validated bean/entity is null.
312+
return true;
313+
}
309314
return attributeLoadedPredicate.test(entity, traversableProperty.getName());
310315
}
311316

0 commit comments

Comments
 (0)