From 26c6ac2fe0a2effdb0b9ba3ea3bfb9ae0ff0b1c6 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Thu, 9 Sep 2021 13:00:32 +0200 Subject: [PATCH] #1600 - Properly create Property instances in PropertyUtils. We now hand the already known property name (from the PropertyDescriptor) to the Property instance we create when inspecting classes for metadata. This avoids ambiguities stemming from the fact that Property assumes Java Bean style properties but Spring's BeanUtils also supporting Java Records style accessors. In special naming contexts like the one used in the test case, this can lead to properties considered "the same" as their accessor methods imply their name is the same. --- .../hateoas/mediatype/PropertyUtils.java | 2 +- .../hateoas/mediatype/PropertyUtilsTest.java | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/springframework/hateoas/mediatype/PropertyUtils.java b/src/main/java/org/springframework/hateoas/mediatype/PropertyUtils.java index d528b940..fcda4f31 100644 --- a/src/main/java/org/springframework/hateoas/mediatype/PropertyUtils.java +++ b/src/main/java/org/springframework/hateoas/mediatype/PropertyUtils.java @@ -226,7 +226,7 @@ public class PropertyUtils { return type == null // ? Stream.empty() // : getPropertyDescriptors(type) // - .map(it -> new AnnotatedProperty(new Property(type, it.getReadMethod(), it.getWriteMethod()))) + .map(it -> new AnnotatedProperty(new Property(type, it.getReadMethod(), it.getWriteMethod(), it.getName()))) .map(it -> JSR_303_PRESENT ? new Jsr303AwarePropertyMetadata(it) : new DefaultPropertyMetadata(it)); } diff --git a/src/test/java/org/springframework/hateoas/mediatype/PropertyUtilsTest.java b/src/test/java/org/springframework/hateoas/mediatype/PropertyUtilsTest.java index 895d2b65..416e1d0f 100644 --- a/src/test/java/org/springframework/hateoas/mediatype/PropertyUtilsTest.java +++ b/src/test/java/org/springframework/hateoas/mediatype/PropertyUtilsTest.java @@ -201,6 +201,13 @@ class PropertyUtilsTest { assertThat(getProperty(metadata, "renamed")).isPresent(); } + @Test // #1402 + void detectesPropertiesWithRecordStyleAccessorsCorrectly() { + + assertThatNoException() + .isThrownBy(() -> PropertyUtils.getExposedProperties(TypeWithRecordStyleAccessors.class)); + } + @Data @AllArgsConstructor @JsonIgnoreProperties({ "ignoreThisProperty" }) @@ -322,4 +329,18 @@ class PropertyUtilsTest { private static Optional getProperty(PayloadMetadata metadata, String name) { return metadata.stream().filter(it -> it.hasName(name)).findFirst(); } + + // #1402 + static class TypeWithRecordStyleAccessors { + + private Boolean isActive; + + public Boolean isActive() { + return isActive; + } + + public void setActive(Boolean active) { + isActive = active; + } + } }