diff --git a/src/main/java/org/springframework/hateoas/mediatype/PropertyUtils.java b/src/main/java/org/springframework/hateoas/mediatype/PropertyUtils.java index 78f65a60..f2767b82 100644 --- a/src/main/java/org/springframework/hateoas/mediatype/PropertyUtils.java +++ b/src/main/java/org/springframework/hateoas/mediatype/PropertyUtils.java @@ -69,8 +69,6 @@ import com.fasterxml.jackson.annotation.JsonUnwrapped; */ public class PropertyUtils { - static final String NOT_BLANK_REGEX = "^\\s*(\\S+\\s*)+$"; - private static final Map DOMAIN_TYPE_CACHE = new ConcurrentReferenceHashMap<>(); private static final Map METADATA_CACHE = new ConcurrentReferenceHashMap<>(); private static final Set FIELDS_TO_IGNORE = new HashSet<>(Arrays.asList("class", "links")); @@ -80,6 +78,8 @@ public class PropertyUtils { Arrays.asList(EntityModel.class, CollectionModel.class, HttpEntity.class)); private static final ResolvableType OBJECT_TYPE = ResolvableType.forClass(Object.class); + static final String NOT_BLANK_REGEX = "^(?=\\s*\\S).*$"; + static { if (ClassUtils.isPresent("org.reactivestreams.Publisher", PropertyUtils.class.getClassLoader())) { TYPES_TO_UNWRAP.addAll(ReactiveWrappers.getTypesToUnwrap()); @@ -600,7 +600,7 @@ public class PropertyUtils { /* * (non-Javadoc) - * @see org.springframework.hateoas.mediatype.PropertyUtils.PropertyMetadata#isRequired() + * @see org.springframework.hateoas.mediatype.PropertyUtils.DefaultPropertyMetadata#isRequired() */ @Override public boolean isRequired() { @@ -612,18 +612,23 @@ public class PropertyUtils { /* * (non-Javadoc) - * @see org.springframework.hateoas.mediatype.PropertyUtils.PropertyMetadata#getRegex() + * @see org.springframework.hateoas.mediatype.PropertyUtils.DefaultPropertyMetadata#getPattern() */ @Override public Optional getPattern() { Optional attribute = getAnnotationAttribute(Pattern.class, "regexp", String.class); - if (!attribute.isPresent() && property.getAnnotation(NotBlank.class).isPresent()) { - attribute = Optional.of(NOT_BLANK_REGEX); + if (attribute.isPresent()) { + return attribute; } - return attribute; + // Default pattern if @NonBlank is present + if (property.getAnnotation(NotBlank.class).isPresent()) { + return Optional.of(NOT_BLANK_REGEX); + } + + return Optional.empty(); } /* diff --git a/src/test/java/org/springframework/hateoas/mediatype/PropertyUtilsTest.java b/src/test/java/org/springframework/hateoas/mediatype/PropertyUtilsTest.java index d0c15942..011dd40b 100644 --- a/src/test/java/org/springframework/hateoas/mediatype/PropertyUtilsTest.java +++ b/src/test/java/org/springframework/hateoas/mediatype/PropertyUtilsTest.java @@ -151,7 +151,7 @@ class PropertyUtilsTest { } @Test - void considersJsr303Annotations() { + void considersBasicJsr303Annotations() { InputPayloadMetadata metadata = PropertyUtils.getExposedProperties(Jsr303SamplePayload.class); @@ -159,20 +159,10 @@ class PropertyUtilsTest { assertThat(it.isRequired()).isTrue(); }); - assertThat(getProperty(metadata, "nonBlank")).hasValueSatisfying(it -> { - assertThat(it.isRequired()).isTrue(); - assertThat(it.getPattern()).hasValue(PropertyUtils.NOT_BLANK_REGEX); - }); - assertThat(getProperty(metadata, "pattern")).hasValueSatisfying(it -> { assertThat(it.getPattern()).hasValue("\\w"); }); - assertThat(getProperty(metadata, "nonBlankPattern")).hasValueSatisfying(it -> { - assertThat(it.isRequired()).isTrue(); - assertThat(it.getPattern()).hasValue("\\w"); - }); - assertThat(getProperty(metadata, "annotated")).hasValueSatisfying(it -> { assertThat(it.getPattern()).hasValue("regex"); }); @@ -219,6 +209,22 @@ class PropertyUtilsTest { .isThrownBy(() -> PropertyUtils.getExposedProperties(TypeWithRecordStyleAccessors.class)); } + @Test // #1753 + void considersJsr303NotBlankAnnotation() { + + InputPayloadMetadata metadata = PropertyUtils.getExposedProperties(Jsr303SamplePayload.class); + + assertThat(getProperty(metadata, "nonBlank")).hasValueSatisfying(it -> { + assertThat(it.isRequired()).isTrue(); + assertThat(it.getPattern()).hasValue(PropertyUtils.NOT_BLANK_REGEX); + }); + + assertThat(getProperty(metadata, "nonBlankPattern")).hasValueSatisfying(it -> { + assertThat(it.isRequired()).isTrue(); + assertThat(it.getPattern()).hasValue("\\w"); + }); + } + @Data @AllArgsConstructor @JsonIgnoreProperties({ "ignoreThisProperty" }) @@ -263,7 +269,7 @@ class PropertyUtilsTest { @NotNull String nonNull; @NotBlank String nonBlank; @Pattern(regexp = "\\w") String pattern; - @NotBlank @Pattern(regexp = "\\w") String nonBlankPattern; + @NotBlank @Pattern(regexp = "\\w") String nonBlankPattern; TypeAnnotated annotated; }