diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/ValidationErrors.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/ValidationErrors.java index 5a6814056..0fafbe2e7 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/ValidationErrors.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/ValidationErrors.java @@ -86,7 +86,7 @@ public class ValidationErrors extends AbstractPropertyBindingResult { String segment = iterator.next(); Optional> property = entities.getPersistentEntity(value.getClass())// - .flatMap(it -> it.getPersistentProperty(PropertyAccessorUtils.getPropertyName(segment))); + .map(it -> it.getPersistentProperty(PropertyAccessorUtils.getPropertyName(segment))); value = getValue(value, property, segment, propertyName); diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/MappingResourceMetadata.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/MappingResourceMetadata.java index a1eeb2c02..0e601a0b0 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/MappingResourceMetadata.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/MappingResourceMetadata.java @@ -56,8 +56,9 @@ class MappingResourceMetadata extends TypeBasedCollectionResourceMapping impleme this.entity.doWithAssociations(propertyMappings); this.entity.doWithProperties(propertyMappings); - Optional annotation = entity.findAnnotation(RestResource.class); - this.explicitlyExported = annotation.map(it -> it.exported()).orElse(false); + this.explicitlyExported = Optional.ofNullable(entity.findAnnotation(RestResource.class))// + .map(it -> it.exported())// + .orElse(false); } /* diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/PersistentPropertyResourceMapping.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/PersistentPropertyResourceMapping.java index 8bf279f7a..96a777dfe 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/PersistentPropertyResourceMapping.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/PersistentPropertyResourceMapping.java @@ -49,8 +49,9 @@ class PersistentPropertyResourceMapping implements PropertyAwareResourceMapping this.property = property; this.mappings = mappings; - this.annotation = property.isAssociation() ? property.findAnnotation(RestResource.class) : Optional.empty(); - this.description = property.findAnnotation(Description.class); + this.annotation = Optional + .ofNullable(property.isAssociation() ? property.findAnnotation(RestResource.class) : null); + this.description = Optional.ofNullable(property.findAnnotation(Description.class)); } /* @@ -111,10 +112,9 @@ class PersistentPropertyResourceMapping implements PropertyAwareResourceMapping CollectionResourceMapping ownerTypeMapping = mappings.getMetadataFor(property.getOwner().getType()); ResourceDescription fallback = TypedResourceDescription.defaultFor(ownerTypeMapping.getItemResourceRel(), property); - return Optionals - . firstNonEmpty(// - () -> description.map(it -> new AnnotationBasedResourceDescription(it, fallback)), // - () -> annotation.map(it -> new AnnotationBasedResourceDescription(it.description(), fallback))) + return Optionals. firstNonEmpty(// + () -> description.map(it -> new AnnotationBasedResourceDescription(it, fallback)), // + () -> annotation.map(it -> new AnnotationBasedResourceDescription(it.description(), fallback))) .orElse(fallback); } diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/DefaultSelfLinkProvider.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/DefaultSelfLinkProvider.java index a29eb6afe..3961bb3fd 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/DefaultSelfLinkProvider.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/DefaultSelfLinkProvider.java @@ -88,7 +88,6 @@ public class DefaultSelfLinkProvider implements SelfLinkProvider { private Object identifierOrNull(Object instance) { return entities.getRequiredPersistentEntity(instance.getClass())// - .getIdentifierAccessor(instance).getIdentifier()// - .orElse(null); + .getIdentifierAccessor(instance).getIdentifier(); } } diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/DomainObjectMerger.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/DomainObjectMerger.java index 86acb036e..3ccf07f28 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/DomainObjectMerger.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/DomainObjectMerger.java @@ -17,8 +17,6 @@ package org.springframework.data.rest.core.support; import static org.springframework.data.rest.core.support.DomainObjectMerger.NullHandlingPolicy.*; -import java.util.Optional; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.convert.ConversionService; import org.springframework.data.mapping.Association; @@ -89,18 +87,18 @@ public class DomainObjectMerger { @Override public void doWithPersistentProperty(PersistentProperty persistentProperty) { - Optional sourceValue = sourceWrapper.getProperty(persistentProperty); - Optional targetValue = targetWrapper.getProperty(persistentProperty); + Object sourceValue = sourceWrapper.getProperty(persistentProperty); + Object targetValue = targetWrapper.getProperty(persistentProperty); if (targetEntity.isIdProperty(persistentProperty)) { return; } - if (sourceValue.equals(targetValue)) { + if (sourceValue != null && sourceValue.equals(targetValue)) { return; } - if (nullPolicy == APPLY_NULLS || sourceValue.isPresent()) { + if (nullPolicy == APPLY_NULLS || sourceValue != null) { targetWrapper.setProperty(persistentProperty, sourceValue); } } @@ -116,7 +114,7 @@ public class DomainObjectMerger { public void doWithAssociation(Association> association) { PersistentProperty persistentProperty = association.getInverse(); - Optional fromVal = sourceWrapper.getProperty(persistentProperty); + Object fromVal = sourceWrapper.getProperty(persistentProperty); if (!isNullOrEmpty(fromVal) && !fromVal.equals(targetWrapper.getProperty(persistentProperty))) { targetWrapper.setProperty(persistentProperty, fromVal); @@ -132,21 +130,21 @@ public class DomainObjectMerger { * @param source can be {@literal null}. * @return */ - static boolean isNullOrEmpty(Optional source) { + static boolean isNullOrEmpty(Object source) { - return source.map(it -> { + if (source == null) { + return true; + } - if (it instanceof Iterable) { - return !((Iterable) it).iterator().hasNext(); - } + if (source instanceof Iterable) { + return !((Iterable) source).iterator().hasNext(); + } - if (ObjectUtils.isArray(it)) { - return ObjectUtils.isEmpty((Object[]) it); - } + if (ObjectUtils.isArray(source)) { + return ObjectUtils.isEmpty((Object[]) source); + } - return false; - - }).orElse(true); + return false; } /** diff --git a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/DomainObjectMergerUnitTests.java b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/DomainObjectMergerUnitTests.java index e83f613b5..b28e2dc09 100755 --- a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/DomainObjectMergerUnitTests.java +++ b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/DomainObjectMergerUnitTests.java @@ -20,7 +20,6 @@ import static org.springframework.data.rest.core.support.DomainObjectMerger.*; import java.util.Collections; import java.util.Iterator; -import java.util.Optional; import org.junit.Test; @@ -34,16 +33,16 @@ public class DomainObjectMergerUnitTests { @Test // DATAREST-327 public void considersEmptyObjectsEmpty() { - assertThat(isNullOrEmpty(Optional.empty())).isTrue(); - assertThat(isNullOrEmpty(Optional.of(Collections.emptyList()))).isTrue(); - assertThat(isNullOrEmpty(Optional.of(new Object[0]))).isTrue(); - assertThat(isNullOrEmpty(Optional.of(new String[0]))).isTrue(); - assertThat(isNullOrEmpty(Optional.of(new MyIterable()))).isTrue(); + assertThat(isNullOrEmpty(null)).isTrue(); + assertThat(isNullOrEmpty(Collections.emptyList())).isTrue(); + assertThat(isNullOrEmpty(new Object[0])).isTrue(); + assertThat(isNullOrEmpty(new String[0])).isTrue(); + assertThat(isNullOrEmpty(new MyIterable())).isTrue(); - assertThat(isNullOrEmpty(Optional.of(new Object()))).isFalse(); - assertThat(isNullOrEmpty(Optional.of(Collections.singleton(new Object())))).isFalse(); - assertThat(isNullOrEmpty(Optional.of(new Object[] { "1" }))).isFalse(); - assertThat(isNullOrEmpty(Optional.of(new String[] { "1" }))).isFalse(); + assertThat(isNullOrEmpty(new Object())).isFalse(); + assertThat(isNullOrEmpty(Collections.singleton(new Object()))).isFalse(); + assertThat(isNullOrEmpty(new Object[] { "1" })).isFalse(); + assertThat(isNullOrEmpty(new String[] { "1" })).isFalse(); } class MyIterable implements Iterable { diff --git a/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/jpa/JpaWebTests.java b/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/jpa/JpaWebTests.java index 0fcda0a64..06690e534 100755 --- a/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/jpa/JpaWebTests.java +++ b/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/jpa/JpaWebTests.java @@ -526,7 +526,7 @@ public class JpaWebTests extends CommonWebTests { String concurrencyTag = createdReceipt.getHeader("ETag"); mvc.perform(patch(builder.build().toUriString()).content("{ \"saleItem\" : \"SpringyBurritos\" }") - .contentType(MediaType.APPLICATION_JSON).header(IF_MATCH, concurrencyTag)) + .contentType(MediaType.APPLICATION_JSON).header(IF_MATCH, concurrencyTag)) // .andExpect(status().is2xxSuccessful()); mvc.perform(patch(builder.build().toUriString()).content("{ \"saleItem\" : \"SpringyTequila\" }") diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/EmbeddedResourcesAssembler.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/EmbeddedResourcesAssembler.java index 72413300f..621922d55 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/EmbeddedResourcesAssembler.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/EmbeddedResourcesAssembler.java @@ -74,32 +74,35 @@ public class EmbeddedResourcesAssembler { return; } - accessor.getProperty(association.getInverse()).ifPresent(it -> { + Object value = accessor.getProperty(association.getInverse()); - String rel = metadata.getMappingFor(property).getRel(); + if (value == null) { + return; + } - if (it instanceof Collection) { + String rel = metadata.getMappingFor(property).getRel(); - Collection collection = (Collection) it; + if (value instanceof Collection) { - if (collection.isEmpty()) { - return; - } + Collection collection = (Collection) value; - List nestedCollection = new ArrayList(); - - for (Object element : collection) { - if (element != null) { - nestedCollection.add(projector.projectExcerpt(element)); - } - } - - associationProjections.add(wrappers.wrap(nestedCollection, rel)); - - } else { - associationProjections.add(wrappers.wrap(projector.projectExcerpt(it), rel)); + if (collection.isEmpty()) { + return; } - }); + + List nestedCollection = new ArrayList(); + + for (Object element : collection) { + if (element != null) { + nestedCollection.add(projector.projectExcerpt(element)); + } + } + + associationProjections.add(wrappers.wrap(nestedCollection, rel)); + + } else { + associationProjections.add(wrappers.wrap(projector.projectExcerpt(value), rel)); + } }); return associationProjections; diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryEntityController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryEntityController.java index 1c62ec8d9..12a66811c 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryEntityController.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryEntityController.java @@ -425,7 +425,7 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem eTag.verify(entity, it); publisher.publishEvent(new BeforeDeleteEvent(it)); - invoker.invokeDeleteById((Serializable) entity.getIdentifierAccessor(it).getIdentifier().orElse(null)); + invoker.invokeDeleteById(entity.getIdentifierAccessor(it).getIdentifier()); publisher.publishEvent(new AfterDeleteEvent(it)); return new ResponseEntity(HttpStatus.NO_CONTENT); diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java index 26d46c7a6..d8d552500 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java @@ -113,9 +113,9 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro @BackendId Serializable id, final @PathVariable String property, final PersistentEntityResourceAssembler assembler) throws Exception { - final HttpHeaders headers = new HttpHeaders(); + HttpHeaders headers = new HttpHeaders(); - Function handler = prop -> prop.propertyValue.map(it -> { + Function handler = prop -> prop.mapValue(it -> { if (prop.property.isCollectionLike()) { @@ -145,10 +145,10 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro } @RequestMapping(value = BASE_MAPPING, method = DELETE) - public ResponseEntity deletePropertyReference(final RootResourceInformation repoRequest, + public ResponseEntity deletePropertyReference(RootResourceInformation repoRequest, @BackendId Serializable id, @PathVariable String property) throws Exception { - Function handler = prop -> prop.propertyValue.map(it -> { + Function handler = prop -> prop.mapValue(it -> { if (prop.property.isCollectionLike() || prop.property.isMap()) { throw HttpRequestMethodNotSupportedException.forRejectedMethod(HttpMethod.DELETE) @@ -171,13 +171,13 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro } @RequestMapping(value = BASE_MAPPING + "/{propertyId}", method = GET) - public ResponseEntity followPropertyReference(final RootResourceInformation repoRequest, - @BackendId Serializable id, @PathVariable String property, final @PathVariable String propertyId, - final PersistentEntityResourceAssembler assembler) throws Exception { + public ResponseEntity followPropertyReference(RootResourceInformation repoRequest, + @BackendId Serializable id, @PathVariable String property, @PathVariable String propertyId, + PersistentEntityResourceAssembler assembler) throws Exception { - final HttpHeaders headers = new HttpHeaders(); + HttpHeaders headers = new HttpHeaders(); - Function handler = prop -> prop.propertyValue.map(it -> { + Function handler = prop -> prop.mapValue(it -> { if (prop.property.isCollectionLike()) { @@ -268,13 +268,12 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro @RequestMapping(value = BASE_MAPPING, method = { PATCH, PUT, POST }, // consumes = { MediaType.APPLICATION_JSON_VALUE, SPRING_DATA_COMPACT_JSON_VALUE, TEXT_URI_LIST_VALUE }) - public ResponseEntity createPropertyReference( - final RootResourceInformation resourceInformation, final HttpMethod requestMethod, - final @RequestBody(required = false) Resources incoming, @BackendId Serializable id, + public ResponseEntity createPropertyReference(RootResourceInformation resourceInformation, + HttpMethod requestMethod, @RequestBody(required = false) Resources incoming, @BackendId Serializable id, @PathVariable String property) throws Exception { - final Resources source = incoming == null ? new Resources(Collections.emptyList()) : incoming; - final RepositoryInvoker invoker = resourceInformation.getInvoker(); + Resources source = incoming == null ? new Resources(Collections.emptyList()) : incoming; + RepositoryInvoker invoker = resourceInformation.getInvoker(); Function handler = prop -> { @@ -282,29 +281,29 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro if (prop.property.isCollectionLike()) { - Collection collection = AUGMENTING_METHODS.contains(requestMethod) - ? (Collection) prop.propertyValue.orElse(null) + Collection collection = AUGMENTING_METHODS.contains(requestMethod) // + ? (Collection) prop.propertyValue // : CollectionFactory.createCollection(propertyType, 0); // Add to the existing collection for (Link l1 : source.getLinks()) { - collection.add(loadPropertyValue(prop.propertyType, l1).orElse(null)); + collection.add(loadPropertyValue(prop.propertyType, l1)); } - prop.accessor.setProperty(prop.property, Optional.of(collection)); + prop.accessor.setProperty(prop.property, collection); } else if (prop.property.isMap()) { - Map map = AUGMENTING_METHODS.contains(requestMethod) - ? (Map) prop.propertyValue.orElse(null) + Map map = AUGMENTING_METHODS.contains(requestMethod) // + ? (Map) prop.propertyValue // : CollectionFactory. createMap(propertyType, 0); // Add to the existing collection for (Link l2 : source.getLinks()) { - map.put(l2.getRel(), loadPropertyValue(prop.propertyType, l2).orElse(null)); + map.put(l2.getRel(), loadPropertyValue(prop.propertyType, l2)); } - prop.accessor.setProperty(prop.property, Optional.of(map)); + prop.accessor.setProperty(prop.property, map); } else { @@ -320,8 +319,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro "Must send only 1 link to update a property reference that isn't a List or a Map."); } - Optional propVal = loadPropertyValue(prop.propertyType, source.getLinks().get(0)); - prop.accessor.setProperty(prop.property, propVal); + prop.accessor.setProperty(prop.property, loadPropertyValue(prop.propertyType, source.getLinks().get(0))); } publisher.publishEvent(new BeforeLinkSaveEvent(prop.accessor.getBean(), prop.propertyValue)); @@ -337,11 +335,11 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro } @RequestMapping(value = BASE_MAPPING + "/{propertyId}", method = DELETE) - public ResponseEntity deletePropertyReferenceId(final RootResourceInformation repoRequest, - @BackendId Serializable backendId, @PathVariable String property, final @PathVariable String propertyId) + public ResponseEntity deletePropertyReferenceId(RootResourceInformation repoRequest, + @BackendId Serializable backendId, @PathVariable String property, @PathVariable String propertyId) throws Exception { - Function handler = prop -> prop.propertyValue.map(it -> { + Function handler = prop -> prop.mapValue(it -> { if (prop.property.isCollectionLike()) { @@ -352,7 +350,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro Object obj = iterator.next(); - prop.entity.getIdentifierAccessor(obj).getIdentifier()// + Optional.ofNullable(prop.entity.getIdentifierAccessor(obj).getIdentifier())// .map(Object::toString)// .filter(id -> propertyId.equals(id))// .ifPresent(__ -> iterator.remove()); @@ -367,7 +365,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro Object key = iterator.next().getKey(); - prop.entity.getIdentifierAccessor(m.get(key)).getIdentifier()// + Optional.ofNullable(prop.entity.getIdentifierAccessor(m.get(key)).getIdentifier())// .map(Object::toString)// .filter(id -> propertyId.equals(id))// .ifPresent(__ -> iterator.remove()); @@ -390,14 +388,14 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT); } - private Optional loadPropertyValue(Class type, Link link) { + private Object loadPropertyValue(Class type, Link link) { String href = link.expand().getHref(); String id = href.substring(href.lastIndexOf('/') + 1); RepositoryInvoker invoker = repositoryInvokerFactory.getInvokerFor(type); - return invoker.invokeFindById(id); + return invoker.invokeFindById(id).orElse(null); } private Optional doWithReferencedProperty(RootResourceInformation resourceInformation, @@ -431,10 +429,10 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro final PersistentEntity entity; final PersistentProperty property; final Class propertyType; - final Optional propertyValue; + final Object propertyValue; final PersistentPropertyAccessor accessor; - private ReferencedProperty(PersistentProperty property, Optional propertyValue, + private ReferencedProperty(PersistentProperty property, Object propertyValue, PersistentPropertyAccessor wrapper) { this.property = property; @@ -444,12 +442,12 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro this.entity = repositories.getPersistentEntity(propertyType); } - public void writeValue() { - accessor.setProperty(property, propertyValue); + public void wipeValue() { + accessor.setProperty(property, null); } - public void wipeValue() { - accessor.setProperty(property, Optional.empty()); + public Optional mapValue(Function function) { + return Optional.ofNullable(propertyValue).map(function); } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceHandlerMethodArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceHandlerMethodArgumentResolver.java index 04615bc08..16be0ae2f 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceHandlerMethodArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceHandlerMethodArgumentResolver.java @@ -138,16 +138,15 @@ public class PersistentEntityResourceHandlerMethodArgumentResolver implements Ha PersistentEntity entity = resourceInformation.getPersistentEntity(); boolean forUpdate = objectToUpdate.isPresent(); - Optional entityIdentifier = objectToUpdate - .flatMap(it -> entity.getIdentifierAccessor(it).getIdentifier()); + Optional entityIdentifier = objectToUpdate.map(it -> entity.getIdentifierAccessor(it).getIdentifier()); - entityIdentifier.ifPresent( - it -> entity.getPropertyAccessor(obj).setProperty(entity.getRequiredIdProperty(), entityIdentifier)); + entityIdentifier.ifPresent(it -> entity.getPropertyAccessor(obj).setProperty(entity.getRequiredIdProperty(), + entityIdentifier.orElse(null))); id.ifPresent(it -> { ConvertingPropertyAccessor accessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(obj), conversionService); - accessor.setProperty(entity.getRequiredIdProperty(), id); + accessor.setProperty(entity.getRequiredIdProperty(), it); }); Builder build = PersistentEntityResource.build(obj, entity); diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java index 2a60b0e1c..1070e8aaa 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java @@ -230,7 +230,7 @@ public class DomainObjectReader { PersistentProperty property = mappedProperties.getPersistentProperty(fieldName); PersistentPropertyAccessor accessor = entity.getPropertyAccessor(target); - Optional rawValue = accessor.getProperty(property); + Optional rawValue = Optional.ofNullable(accessor.getProperty(property)); if (!rawValue.isPresent() || associationLinks.isLinkableAssociation(property)) { continue; @@ -315,7 +315,7 @@ public class DomainObjectReader { * @return whether an object merge has been applied to the {@link ArrayNode}. */ private boolean handleArrayNode(ArrayNode array, Collection collection, ObjectMapper mapper, - Optional> componentType) throws Exception { + TypeInformation componentType) throws Exception { Assert.notNull(array, "ArrayNode must not be null!"); Assert.notNull(collection, "Source collection must not be null!"); @@ -373,7 +373,7 @@ public class DomainObjectReader { Iterator> fields = node.fields(); Class keyType = typeOrObject(type.getComponentType()); - Optional> valueType = type.getMapValueType(); + TypeInformation valueType = type.getMapValueType(); while (fields.hasNext()) { @@ -391,7 +391,7 @@ public class DomainObjectReader { } else if (value instanceof ArrayNode && sourceValue != null) { - handleArray(value, sourceValue, mapper, getTypeToMap(sourceValue, Optional.of(typeToMap))); + handleArray(value, sourceValue, mapper, getTypeToMap(sourceValue, typeToMap)); } else { @@ -528,9 +528,8 @@ public class DomainObjectReader { * @param type can be {@literal null}. * @return */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - private static Class typeOrObject(Optional> type) { - return type.map(it -> it.getType()).orElse((Class) Object.class); + private static Class typeOrObject(TypeInformation type) { + return type == null ? Object.class : type.getType(); } /** @@ -542,21 +541,22 @@ public class DomainObjectReader { * @param type can be {@literal null}. * @return */ - private static TypeInformation getTypeToMap(Object value, Optional> type) { + private static TypeInformation getTypeToMap(Object value, TypeInformation type) { - return type.map(it -> { + if (type == null) { + return ClassTypeInformation.OBJECT; + } - if (value == null) { - return it; - } + if (value == null) { + return type; + } - if (Enum.class.isInstance(value)) { - return ClassTypeInformation.from(((Enum) value).getDeclaringClass()); - } + if (Enum.class.isInstance(value)) { + return ClassTypeInformation.from(((Enum) value).getDeclaringClass()); + } - return value.getClass().equals(it.getType()) ? it : ClassTypeInformation.from(value.getClass()); + return value.getClass().equals(type.getType()) ? type : ClassTypeInformation.from(value.getClass()); - }).orElse(ClassTypeInformation.OBJECT); } /** @@ -636,8 +636,8 @@ public class DomainObjectReader { return; } - Optional sourceValue = sourceAccessor.getProperty(property); - Optional targetValue = targetAccessor.getProperty(property); + Optional sourceValue = Optional.ofNullable(sourceAccessor.getProperty(property)); + Optional targetValue = Optional.ofNullable(targetAccessor.getProperty(property)); Optional result = Optional.empty(); if (property.isMap()) { @@ -650,7 +650,7 @@ public class DomainObjectReader { result = sourceValue; } - targetAccessor.setProperty(property, result); + targetAccessor.setProperty(property, result.orElse(null)); } } 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 a53ab6a11..a323e5b0b 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 @@ -69,8 +69,8 @@ class MappedProperties { for (BeanPropertyDefinition property : description.findProperties()) { - Optional> persistentProperty = entity - .getPersistentProperty(property.getInternalName()); + Optional> persistentProperty = // + Optional.ofNullable(entity.getPersistentProperty(property.getInternalName())); persistentProperty.ifPresent(it -> { propertyToFieldName.put(it, property); 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 f4c1cd8f5..b8e6ae389 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 @@ -309,7 +309,7 @@ public class PersistentEntityJackson2Module extends SimpleModule { return description.findProperties().stream()// .filter(it -> it.getName().equals(finalName))// - .findFirst().flatMap(it -> entity.getPersistentProperty(it.getInternalName())); + .findFirst().map(it -> entity.getPersistentProperty(it.getInternalName())); } } @@ -422,28 +422,31 @@ public class PersistentEntityJackson2Module extends SimpleModule { SettableBeanProperty property = properties.next(); - entity.getPersistentProperty(property.getName()).ifPresent(persistentProperty -> { + PersistentProperty persistentProperty = entity.getPersistentProperty(property.getName()); - if (associationLinks.isLookupType(persistentProperty)) { + if (persistentProperty == null) { + continue; + } - RepositoryInvokingDeserializer repositoryInvokingDeserializer = new RepositoryInvokingDeserializer( - factory, persistentProperty); - JsonDeserializer deserializer = wrapIfCollection(persistentProperty, repositoryInvokingDeserializer, - config); + if (associationLinks.isLookupType(persistentProperty)) { - builder.addOrReplaceProperty(property.withValueDeserializer(deserializer), false); - return; - } - - if (!associationLinks.isLinkableAssociation(persistentProperty)) { - return; - } - - UriStringDeserializer uriStringDeserializer = new UriStringDeserializer(persistentProperty, converter); - JsonDeserializer deserializer = wrapIfCollection(persistentProperty, uriStringDeserializer, config); + RepositoryInvokingDeserializer repositoryInvokingDeserializer = new RepositoryInvokingDeserializer(factory, + persistentProperty); + JsonDeserializer deserializer = wrapIfCollection(persistentProperty, repositoryInvokingDeserializer, + config); builder.addOrReplaceProperty(property.withValueDeserializer(deserializer), false); - }); + continue; + } + + if (!associationLinks.isLinkableAssociation(persistentProperty)) { + continue; + } + + UriStringDeserializer uriStringDeserializer = new UriStringDeserializer(persistentProperty, converter); + JsonDeserializer deserializer = wrapIfCollection(persistentProperty, uriStringDeserializer, config); + + builder.addOrReplaceProperty(property.withValueDeserializer(deserializer), false); } }); diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverter.java index b414991d2..fff97d335 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverter.java @@ -175,10 +175,10 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric for (BeanPropertyDefinition definition : jackson) { - JacksonProperty jacksonProperty = new JacksonProperty(jackson, - entity.getPersistentProperty(definition.getInternalName()), definition); + Optional> prop = Optional + .ofNullable(entity.getPersistentProperty(definition.getInternalName())); - Optional> prop = entity.getPersistentProperty(definition.getInternalName()); + JacksonProperty jacksonProperty = new JacksonProperty(jackson, prop, definition); // First pass, early drops to avoid unnecessary calculation if (prop.isPresent()) { diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/WrappedProperties.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/WrappedProperties.java index 1e348c001..6569a73aa 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/WrappedProperties.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/WrappedProperties.java @@ -144,7 +144,7 @@ class WrappedProperties { for (BeanPropertyDefinition property : getMappedProperties(entity)) { - Optionals.ifAllPresent(entity.getPersistentProperty(property.getInternalName()), // + Optionals.ifAllPresent(Optional.ofNullable(entity.getPersistentProperty(property.getInternalName())), // findAnnotatedMember(property), // (prop, member) -> { @@ -194,7 +194,7 @@ class WrappedProperties { for (BeanPropertyDefinition property : properties) { Optionals.ifAllPresent(findAnnotatedMember(property), // - entity.getPersistentProperty(property.getInternalName()), // + Optional.ofNullable(entity.getPersistentProperty(property.getInternalName())), // (member, prop) -> withInternalName.add(property)); } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollectingAssociationHandler.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollectingAssociationHandler.java index 8d8b4be27..f2bcc4ad7 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollectingAssociationHandler.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollectingAssociationHandler.java @@ -19,10 +19,10 @@ import java.util.ArrayList; import java.util.List; import org.springframework.data.mapping.Association; +import org.springframework.data.mapping.MappingException; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.SimpleAssociationHandler; import org.springframework.data.mapping.context.PersistentEntities; -import org.springframework.data.mapping.model.MappingException; import org.springframework.data.rest.core.Path; import org.springframework.hateoas.Link; import org.springframework.hateoas.Links; diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollector.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollector.java index e41396dcf..e9ffc26f4 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollector.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollector.java @@ -25,12 +25,12 @@ import java.util.Collections; import java.util.List; import org.springframework.data.mapping.Association; +import org.springframework.data.mapping.MappingException; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.SimpleAssociationHandler; import org.springframework.data.mapping.context.PersistentEntities; -import org.springframework.data.mapping.model.MappingException; import org.springframework.data.rest.core.Path; import org.springframework.data.rest.core.mapping.ResourceMapping; import org.springframework.data.rest.core.mapping.ResourceMetadata; @@ -216,16 +216,20 @@ public class LinkCollector { PersistentProperty property = association.getInverse(); - accessor.getProperty(property).ifPresent(it -> { + Object value = accessor.getProperty(property); - ResourceMetadata metadata = associations.getMappings().getMetadataFor(property.getOwner().getType()); - ResourceMapping propertyMapping = metadata.getMappingFor(property); + if (value == null) { + return; + } - for (Object element : asCollection(it)) { - if (element != null) - links.add(getLinkFor(element, propertyMapping)); + ResourceMetadata metadata = associations.getMappings().getMetadataFor(property.getOwner().getType()); + ResourceMapping propertyMapping = metadata.getMappingFor(property); + + for (Object element : asCollection(value)) { + if (element != null) { + links.add(getLinkFor(element, propertyMapping)); } - }); + } } /** diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/ETag.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/ETag.java index 29ce1735c..5b5929bc9 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/ETag.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/ETag.java @@ -169,8 +169,8 @@ public final class ETag { PersistentPropertyAccessor accessor = entity.getPropertyAccessor(bean); - return entity.getVersionProperty()// - .flatMap(it -> accessor.getProperty(it))// + return Optional.ofNullable(entity.getVersionProperty())// + .map(it -> accessor.getProperty(it))// .map(Object::toString); } }