Skip to content

Commit 9a033e1

Browse files
FrogDevelopperLe Gall, Benoit
authored andcommitted
fix: avoid adding unnamed Bean node in constraint validation message path (#298) (#300)
Co-authored-by: Le Gall, Benoit <benoit.legall@rakuten.com>
1 parent b6a182f commit 9a033e1

File tree

6 files changed

+77
-2
lines changed

6 files changed

+77
-2
lines changed

validation/src/main/java/io/micronaut/validation/exceptions/ConstraintExceptionHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ protected String buildMessage(ConstraintViolation<?> violation) {
106106
}
107107
message.append(']');
108108
}
109-
if (node.getKind() != ElementKind.CONTAINER_ELEMENT) {
109+
if (node.getKind() != ElementKind.CONTAINER_ELEMENT && node.getName() != null) {
110110
if (!firstNode) {
111111
message.append('.');
112112
}

validation/src/test/groovy/io/micronaut/validation/Pojo.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import jakarta.validation.constraints.Email;
2121
import jakarta.validation.constraints.NotBlank;
2222

23+
@ValidPojo
2324
@Introspected
2425
public class Pojo {
2526

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.micronaut.validation;
2+
3+
import java.util.Objects;
4+
import jakarta.inject.Singleton;
5+
6+
import io.micronaut.core.annotation.AnnotationValue;
7+
import io.micronaut.core.annotation.Introspected;
8+
import io.micronaut.validation.validator.constraints.ConstraintValidator;
9+
import io.micronaut.validation.validator.constraints.ConstraintValidatorContext;
10+
11+
@Singleton
12+
@Introspected
13+
public class PojoValidator implements ConstraintValidator<ValidPojo, Pojo> {
14+
15+
@Override
16+
public boolean isValid(Pojo pojo, AnnotationValue<ValidPojo> annotationMetadata,
17+
ConstraintValidatorContext context) {
18+
if (Objects.equals(pojo.getEmail(), pojo.getName())) {
19+
context.messageTemplate("Email and Name can not be identical");
20+
return false;
21+
}
22+
23+
return true;
24+
}
25+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package io.micronaut.validation;
2+
3+
import static java.lang.annotation.ElementType.TYPE;
4+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
5+
6+
import java.lang.annotation.Documented;
7+
import java.lang.annotation.Retention;
8+
import java.lang.annotation.Target;
9+
import jakarta.validation.Constraint;
10+
11+
/**
12+
* Simple annotation to validate behavior when adding validation annotation at class level
13+
*/
14+
@Documented
15+
@Target(TYPE)
16+
@Retention(RUNTIME)
17+
@Constraint(validatedBy = {PojoValidator.class})
18+
public @interface ValidPojo {
19+
}

validation/src/test/groovy/io/micronaut/validation/ValidatedSpec.groovy

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,36 @@ class ValidatedSpec extends Specification {
212212
server.close()
213213
}
214214

215+
def "test validated controller validates @Valid classes with validation annotation set on class"() {
216+
given:
217+
ApplicationContext context = ApplicationContext.run([
218+
'spec.name': getClass().simpleName
219+
])
220+
EmbeddedServer embeddedServer = context.getBean(EmbeddedServer).start()
221+
HttpClient client = context.createBean(HttpClient, embeddedServer.getURL())
222+
EmbeddedServer server = ApplicationContext.run(EmbeddedServer)
223+
224+
when:
225+
HttpResponse<String> response = client.toBlocking().exchange(
226+
HttpRequest.POST("/validated/pojo", '{"email":"test@example.com","name":"test@example.com"}')
227+
.contentType(MediaType.APPLICATION_JSON_TYPE),
228+
String
229+
)
230+
231+
then:
232+
def e = thrown(HttpClientResponseException)
233+
e.response.code() == HttpStatus.BAD_REQUEST.code
234+
235+
when:
236+
def result = new JsonSlurper().parseText((String) e.response.getBody().get())
237+
238+
then:
239+
result._embedded.errors[0].message == 'pojo: Email and Name can not be identical'
240+
241+
cleanup:
242+
server.close()
243+
}
244+
215245
def "test validated controller validates @Valid classes with standard embedded errors"() {
216246
given:
217247
ApplicationContext context = ApplicationContext.run([

validation/src/test/groovy/io/micronaut/validation/validator/pojo/PojoValidatorSpec.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class PojoValidatorSpec extends Specification {
108108

109109
then:
110110
ex = thrown(ConstraintViolationException)
111-
ex.constraintViolations.size() == 1
111+
ex.constraintViolations.size() == 2
112112
}
113113

114114
void "test don't cascade to iterable without @Valid"() {

0 commit comments

Comments
 (0)