DATAREST-1260 - Tweaked DomainObjectReader to support immutable entities.
DomainObjectReader now aborts the recursive merges in case it encounters an entity that's described as @Immutable (just introduced in Spring Data Commons). Fixed some generics and removed DomainObjectMerger as it's unused. Related ticket: DATACMNS-1322.
This commit is contained in:
@@ -112,7 +112,7 @@ public class HttpHeadersPreparer {
|
||||
* @param source can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private Optional<AuditableBeanWrapper> getAuditableBeanWrapper(Object source) {
|
||||
private Optional<AuditableBeanWrapper<Object>> getAuditableBeanWrapper(Object source) {
|
||||
return auditableBeanWrapperFactory.getBeanWrapperFor(source);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,6 @@ import org.springframework.data.rest.core.mapping.RepositoryResourceMappings;
|
||||
import org.springframework.data.rest.core.mapping.ResourceDescription;
|
||||
import org.springframework.data.rest.core.mapping.ResourceMappings;
|
||||
import org.springframework.data.rest.core.support.DefaultSelfLinkProvider;
|
||||
import org.springframework.data.rest.core.support.DomainObjectMerger;
|
||||
import org.springframework.data.rest.core.support.EntityLookup;
|
||||
import org.springframework.data.rest.core.support.RepositoryRelProvider;
|
||||
import org.springframework.data.rest.core.support.SelfLinkProvider;
|
||||
@@ -346,17 +345,6 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
|
||||
return new AnnotatedEventHandlerInvoker();
|
||||
}
|
||||
|
||||
/**
|
||||
* For merging incoming objects materialized from JSON with existing domain objects loaded from the repository.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public DomainObjectMerger domainObjectMerger() throws Exception {
|
||||
return new DomainObjectMerger(repositories(), defaultConversionService());
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns an {@link javax.servlet.http.HttpServletRequest} into a
|
||||
* {@link org.springframework.http.server.ServerHttpRequest}.
|
||||
|
||||
@@ -138,20 +138,22 @@ public class DomainObjectReader {
|
||||
|
||||
Class<? extends Object> type = target.getClass();
|
||||
|
||||
return entities.getPersistentEntity(type).map(it -> {
|
||||
return entities.getPersistentEntity(type) //
|
||||
.filter(it -> !it.isImmutable()) //
|
||||
.map(it -> {
|
||||
|
||||
MergingPropertyHandler propertyHandler = new MergingPropertyHandler(source, target, it, mapper);
|
||||
MergingPropertyHandler propertyHandler = new MergingPropertyHandler(source, target, it, mapper);
|
||||
|
||||
it.doWithProperties(propertyHandler);
|
||||
it.doWithAssociations(new LinkedAssociationSkippingAssociationHandler(associationLinks, propertyHandler));
|
||||
it.doWithProperties(propertyHandler);
|
||||
it.doWithAssociations(new LinkedAssociationSkippingAssociationHandler(associationLinks, propertyHandler));
|
||||
|
||||
// Need to copy unmapped properties as the PersistentProperty model currently does not contain any transient
|
||||
// properties
|
||||
copyRemainingProperties(propertyHandler.getProperties(), source, target);
|
||||
// Need to copy unmapped properties as the PersistentProperty model currently does not contain any transient
|
||||
// properties
|
||||
copyRemainingProperties(propertyHandler.getProperties(), source, target);
|
||||
|
||||
return target;
|
||||
return target;
|
||||
|
||||
}).orElse(source);
|
||||
}).orElse(source);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,7 +231,7 @@ public class DomainObjectReader {
|
||||
}
|
||||
|
||||
PersistentProperty<?> property = mappedProperties.getPersistentProperty(fieldName);
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(target);
|
||||
PersistentPropertyAccessor<?> accessor = entity.getPropertyAccessor(target);
|
||||
Optional<Object> rawValue = Optional.ofNullable(accessor.getProperty(property));
|
||||
|
||||
if (!rawValue.isPresent() || associationLinks.isLinkableAssociation(property)) {
|
||||
@@ -596,8 +598,8 @@ public class DomainObjectReader {
|
||||
private class MergingPropertyHandler implements SimplePropertyHandler {
|
||||
|
||||
private final @Getter MappedProperties properties;
|
||||
private final PersistentPropertyAccessor targetAccessor;
|
||||
private final PersistentPropertyAccessor sourceAccessor;
|
||||
private final PersistentPropertyAccessor<?> targetAccessor;
|
||||
private final PersistentPropertyAccessor<?> sourceAccessor;
|
||||
private final ObjectMapper mapper;
|
||||
|
||||
/**
|
||||
@@ -617,7 +619,7 @@ public class DomainObjectReader {
|
||||
Assert.notNull(mapper, "ObjectMapper must not be null!");
|
||||
|
||||
this.properties = MappedProperties.fromJacksonProperties(entity, mapper);
|
||||
this.targetAccessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(target),
|
||||
this.targetAccessor = new ConvertingPropertyAccessor<>(entity.getPropertyAccessor(target),
|
||||
new DefaultConversionService());
|
||||
this.sourceAccessor = entity.getPropertyAccessor(source);
|
||||
this.mapper = mapper;
|
||||
@@ -639,6 +641,12 @@ public class DomainObjectReader {
|
||||
}
|
||||
|
||||
Optional<Object> sourceValue = Optional.ofNullable(sourceAccessor.getProperty(property));
|
||||
|
||||
if (property.isImmutable()) {
|
||||
targetAccessor.setProperty(property, sourceValue.orElse(null));
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<Object> targetValue = Optional.ofNullable(targetAccessor.getProperty(property));
|
||||
Optional<?> result = Optional.empty();
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Value;
|
||||
@@ -51,6 +52,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Immutable;
|
||||
import org.springframework.data.annotation.ReadOnlyProperty;
|
||||
import org.springframework.data.annotation.Reference;
|
||||
import org.springframework.data.annotation.Transient;
|
||||
@@ -734,11 +736,13 @@ public class DomainObjectReaderUnitTests {
|
||||
List<SampleEnum> enums = new ArrayList<SampleEnum>();
|
||||
}
|
||||
|
||||
@Value
|
||||
@EqualsAndHashCode
|
||||
@AllArgsConstructor
|
||||
static class SampleWithReference {
|
||||
@Reference List<Nested> nested;
|
||||
private @Getter @Reference List<Nested> nested;
|
||||
}
|
||||
|
||||
@Immutable
|
||||
@Value
|
||||
static class Nested {
|
||||
int x, y;
|
||||
|
||||
Reference in New Issue
Block a user