From a027727a468e35339b6f949390f951aadc116a0a Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Tue, 21 Feb 2023 13:24:39 +0100 Subject: [PATCH] Adapt to renamed properties by using MappedProperties in association deserialization. Revert the changes that employed manual annotation lookup as that would cause invalid associations of fields and accessor methods for properties shadow renamed. Instead, we now use MappedProperties that already contains a mapping between the Jackson field names and Spring Data property names. Fixes: #2165 $ Conflicts: $ spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java $ spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java --- .../rest/webmvc/json/MappedProperties.java | 4 ++ .../json/PersistentEntityJackson2Module.java | 4 +- ...rsistentEntityJackson2ModuleUnitTests.java | 38 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java index 5da84cf21..5f5e30f64 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java @@ -151,6 +151,10 @@ class MappedProperties { return new MappedProperties(entity, description); } + public static MappedProperties forDescription(PersistentEntity entity, BeanDescription description) { + return new MappedProperties(entity, description); + } + public static MappedProperties none() { return new MappedProperties(Collections.emptyMap(), Collections.emptyMap(), Collections.emptySet(), Collections.emptySet(), false); diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java index a82353405..a30628ba9 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java @@ -461,10 +461,12 @@ public class PersistentEntityJackson2Module extends SimpleModule { entities.getPersistentEntity(beanDesc.getBeanClass()).ifPresent(entity -> { + MappedProperties mapped = MappedProperties.forDescription(entity, beanDesc); + while (properties.hasNext()) { SettableBeanProperty property = properties.next(); - PersistentProperty persistentProperty = entity.getPersistentProperty(property.getName()); + PersistentProperty persistentProperty = mapped.getPersistentProperty(property.getName()); if (persistentProperty == null) { continue; diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java index d496c6273..0606dd747 100755 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java @@ -157,6 +157,40 @@ class PersistentEntityJackson2ModuleUnitTests { assertThat(petOwner.getPet()).isNotNull(); } + @Test + void allowsUrlsForLinkableAssociation() throws Exception { + + when(converter.convert(UriTemplate.of("/homes/1").expand(), TypeDescriptor.valueOf(URI.class), + TypeDescriptor.valueOf(Home.class))).thenReturn(new Home()); + + PersistentProperty property = persistentEntities.getRequiredPersistentEntity(PetOwner.class) + .getRequiredPersistentProperty("home"); + + when(associations.isLinkableAssociation(property)).thenReturn(true); + + PetOwner petOwner = mapper.readValue("{\"home\": \"/homes/1\" }", PetOwner.class); + + assertThat(petOwner).isNotNull(); + assertThat(petOwner.getHome()).isInstanceOf(Home.class); + } + + @Test + void allowsUrlsForRenamedLinkableAssociation() throws IOException { + + when(converter.convert(UriTemplate.of("/packages/1").expand(), TypeDescriptor.valueOf(URI.class), + TypeDescriptor.valueOf(Package.class))).thenReturn(new Package()); + + PersistentProperty property = persistentEntities.getRequiredPersistentEntity(PetOwner.class) + .getRequiredPersistentProperty("_package"); + + when(associations.isLinkableAssociation(property)).thenReturn(true); + + PetOwner petOwner = mapper.readValue("{\"package\":\"/packages/1\"}", PetOwner.class); + + assertThat(petOwner).isNotNull(); + assertThat(petOwner._package).isNotNull(); + } + @Test // DATAREST-1321 void allowsNumericIdsForLookupTypes() throws Exception { @@ -260,8 +294,12 @@ class PersistentEntityJackson2ModuleUnitTests { Pet pet; Home home; + + @JsonProperty("package") Package _package; } + static class Package {} + @JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.MINIMAL_CLASS) static class Pet {}