Skip to content

Commit 33edab4

Browse files
committed
DATAREST-837 - DomainObjectMerger doesn't nullify read-only properties on PUT.
PUT requests are supposed to replace the state of the resource with the request payload. However, Spring Data REST already handles a couple of domain object propoerties in a special way as theri values map to dedicated HTTP features: identifiers (URIs), last-modified dates (header) etc. For users, it might be worthwhile to exclude other properties from being set by applying the payload, like properties that are completely under the control of the server, e.g. creation user and date, last modifying user etc. So far, users didn't have any means to exclude those properties as the handling of PUT requests treated every missing property of the payload as null value. DomainObjectMerger now checks whether a property is actually writable before applying the implicit null value. The application can be disabled by annotation a property with @ReadOnlyProperty.
1 parent cc9d0f4 commit 33edab4

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public <T> T readPut(final ObjectNode source, T target, final ObjectMapper mappe
108108
@Override
109109
public void doWithPersistentProperty(PersistentProperty<?> property) {
110110

111-
if (property.isIdProperty() || property.isVersionProperty()) {
111+
if (property.isIdProperty() || property.isVersionProperty() || !property.isWritable()) {
112112
return;
113113
}
114114

spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/DomainObjectReaderUnitTests.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static org.mockito.Mockito.*;
2121

2222
import java.util.Collections;
23+
import java.util.Date;
2324
import java.util.HashMap;
2425
import java.util.Map;
2526

@@ -28,7 +29,9 @@
2829
import org.junit.runner.RunWith;
2930
import org.mockito.Mock;
3031
import org.mockito.runners.MockitoJUnitRunner;
32+
import org.springframework.data.annotation.CreatedDate;
3133
import org.springframework.data.annotation.Id;
34+
import org.springframework.data.annotation.ReadOnlyProperty;
3235
import org.springframework.data.annotation.Version;
3336
import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext;
3437
import org.springframework.data.mapping.context.PersistentEntities;
@@ -64,6 +67,7 @@ public void setUp() {
6467
mappingContext.getPersistentEntity(Person.class);
6568
mappingContext.getPersistentEntity(TypeWithGenericMap.class);
6669
mappingContext.getPersistentEntity(VersionedType.class);
70+
mappingContext.getPersistentEntity(SampleWithCreatedDate.class);
6771
mappingContext.afterPropertiesSet();
6872

6973
PersistentEntities entities = new PersistentEntities(Collections.singleton(mappingContext));
@@ -172,6 +176,23 @@ public void doesNotWipeIdAndVersionPropertyForPut() throws Exception {
172176
assertThat(result.version, is(1L));
173177
}
174178

179+
/**
180+
* @see DATAREST-873
181+
*/
182+
@Test
183+
public void doesNotApplyInputToReadOnlyFields() throws Exception {
184+
185+
ObjectMapper mapper = new ObjectMapper();
186+
ObjectNode node = (ObjectNode) mapper.readTree("{}");
187+
188+
Date reference = new Date();
189+
190+
SampleWithCreatedDate sample = new SampleWithCreatedDate();
191+
sample.createdDate = reference;
192+
193+
assertThat(reader.readPut(node, sample, mapper).createdDate, is(reference));
194+
}
195+
175196
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
176197
static class SampleUser {
177198

@@ -213,4 +234,12 @@ static class VersionedType {
213234

214235
String firstname, lastname;
215236
}
237+
238+
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
239+
static class SampleWithCreatedDate {
240+
241+
@CreatedDate //
242+
@ReadOnlyProperty //
243+
Date createdDate;
244+
}
216245
}

0 commit comments

Comments
 (0)