Skip to content

Commit 487c2ac

Browse files
f-cramerodrotbohm
authored andcommitted
Support validation for fields that are not a PersistentEntity.
For entity types that use transient fields, the validation integration needs to treat those as normal bean types an must not reject the values right away. Fixes GH-2252.
1 parent 2c31327 commit 487c2ac

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

spring-data-rest-core/src/main/java/org/springframework/data/rest/core/ValidationErrors.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.Arrays;
1919
import java.util.Collection;
2020
import java.util.Iterator;
21+
import java.util.Optional;
2122

2223
import org.springframework.beans.BeansException;
2324
import org.springframework.beans.ConfigurablePropertyAccessor;
@@ -39,6 +40,7 @@
3940
*
4041
* @author Jon Brisbin
4142
* @author Oliver Gierke
43+
* @author Florian Cramer
4244
*/
4345
public class ValidationErrors extends AbstractPropertyBindingResult {
4446

@@ -92,7 +94,12 @@ public Object getPropertyValue(String propertyName) throws BeansException {
9294
*/
9395
private Object lookupValueOn(Object value, String segment) {
9496

95-
PersistentProperty<?> property = entities.getPersistentEntity(value.getClass()) //
97+
Optional<PersistentEntity<?, ? extends PersistentProperty<?>>> entity = entities.getPersistentEntity(value.getClass());
98+
if (!entity.isPresent()) {
99+
return new DirectFieldAccessor(value).getPropertyValue(segment);
100+
}
101+
102+
PersistentProperty<?> property = entity //
96103
.map(it -> it.getPersistentProperty(PropertyAccessorUtils.getPropertyName(segment))) //
97104
.orElseThrow(() -> new NotReadablePropertyException(value.getClass(), segment));
98105

spring-data-rest-core/src/test/java/org/springframework/data/rest/core/ValidationErrorsUnitTests.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2022 original author or authors.
2+
* Copyright 2016-2023 original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,14 +24,18 @@
2424
import org.junit.jupiter.api.BeforeEach;
2525
import org.junit.jupiter.api.Test;
2626
import org.springframework.beans.NotReadablePropertyException;
27+
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity;
28+
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
2729
import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext;
2830
import org.springframework.data.mapping.context.PersistentEntities;
31+
import org.springframework.data.util.TypeInformation;
2932
import org.springframework.validation.Errors;
3033

3134
/**
3235
* Unit tests for {@link ValidationErrors}.
3336
*
3437
* @author Oliver Gierke
38+
* @author Florian Cramer
3539
*/
3640
class ValidationErrorsUnitTests {
3741

@@ -40,7 +44,7 @@ class ValidationErrorsUnitTests {
4044
@BeforeEach
4145
void setUp() {
4246

43-
KeyValueMappingContext<?, ?> context = new KeyValueMappingContext<>();
47+
KeyValueMappingContext<?, ?> context = new TestKeyValueMappingContext<>();
4448
context.getPersistentEntity(Foo.class);
4549

4650
this.entities = new PersistentEntities(Arrays.asList(context));
@@ -71,6 +75,14 @@ void returnsNullForPropertyValue() {
7175
assertThat(errors.getFieldValue("bar")).isNull();
7276
}
7377

78+
@Test // GH-2252
79+
void getsTheNestedFieldsValueForNonPersistentEntity() {
80+
81+
ValidationErrors errors = new ValidationErrors(new Foo(), entities);
82+
83+
assertThat(errors.getFieldValue("qux.field")).isEqualTo("World");
84+
}
85+
7486
private static void expectedErrorBehavior(Errors errors) {
7587

7688
assertThat(errors.getFieldValue("bars")).isNotNull();
@@ -88,9 +100,22 @@ private static void expectedErrorBehavior(Errors errors) {
88100
static class Foo {
89101
List<Bar> bars = Collections.singletonList(new Bar());
90102
Bar bar = null;
103+
Qux qux = new Qux();
91104
}
92105

93106
static class Bar {
94107
String field = "Hello";
95108
}
109+
110+
static class Qux {
111+
String field = "World";
112+
}
113+
114+
static class TestKeyValueMappingContext<E extends KeyValuePersistentEntity<?, P>, P extends KeyValuePersistentProperty<P>> extends KeyValueMappingContext<E, P> {
115+
116+
@Override
117+
protected boolean shouldCreatePersistentEntityFor(TypeInformation<?> type) {
118+
return Qux.class != type.getType() && super.shouldCreatePersistentEntityFor(type);
119+
}
120+
}
96121
}

0 commit comments

Comments
 (0)