DATAREST-1248 - SortTranslator now considers read-only properties sortable.
MappedProperties now exposes a factory method that uses the Jackson introspector for serialization (instead of deserialization) which now also includes read-only properties. Previously, read-only ones were not considered as they are excluded from the metadata if it is looked up for deserialization.
This commit is contained in:
@@ -219,7 +219,7 @@ public class DomainObjectReader {
|
||||
return mapper.readerForUpdating(target).readValue(root);
|
||||
}
|
||||
|
||||
MappedProperties mappedProperties = MappedProperties.fromJacksonProperties(entity, mapper);
|
||||
MappedProperties mappedProperties = MappedProperties.forDeserialization(entity, mapper);
|
||||
|
||||
for (Iterator<Entry<String, JsonNode>> i = root.fields(); i.hasNext();) {
|
||||
|
||||
@@ -616,7 +616,7 @@ public class DomainObjectReader {
|
||||
Assert.notNull(entity, "PersistentEntity must not be null!");
|
||||
Assert.notNull(mapper, "ObjectMapper must not be null!");
|
||||
|
||||
this.properties = MappedProperties.fromJacksonProperties(entity, mapper);
|
||||
this.properties = MappedProperties.forDeserialization(entity, mapper);
|
||||
this.targetAccessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(target),
|
||||
new DefaultConversionService());
|
||||
this.sourceAccessor = entity.getPropertyAccessor(source);
|
||||
|
||||
@@ -226,7 +226,7 @@ public class JacksonMappingAwareSortTranslator {
|
||||
|
||||
if (persistentEntity != null) {
|
||||
|
||||
this.currentProperties = MappedProperties.fromJacksonProperties(currentType, objectMapper);
|
||||
this.currentProperties = MappedProperties.forSerialization(currentType, objectMapper);
|
||||
this.currentWrappedProperties = WrappedProperties.fromJacksonProperties(persistentEntities, currentType,
|
||||
objectMapper);
|
||||
|
||||
|
||||
@@ -28,7 +28,9 @@ import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.fasterxml.jackson.databind.BeanDescription;
|
||||
import com.fasterxml.jackson.databind.DeserializationConfig;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.introspect.BasicClassIntrospector;
|
||||
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
|
||||
import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
|
||||
@@ -81,16 +83,34 @@ class MappedProperties {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates {@link MappedProperties} for the given {@link PersistentEntity}.
|
||||
* Creates {@link MappedProperties} for the given {@link PersistentEntity} for deserialization purposes. Will not
|
||||
* include Jackson-read-only properties.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param mapper must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static MappedProperties fromJacksonProperties(PersistentEntity<?, ?> entity, ObjectMapper mapper) {
|
||||
public static MappedProperties forDeserialization(PersistentEntity<?, ?> entity, ObjectMapper mapper) {
|
||||
|
||||
BeanDescription description = INTROSPECTOR.forDeserialization(mapper.getDeserializationConfig(),
|
||||
mapper.constructType(entity.getType()), mapper.getDeserializationConfig());
|
||||
DeserializationConfig config = mapper.getDeserializationConfig();
|
||||
BeanDescription description = INTROSPECTOR.forDeserialization(config, mapper.constructType(entity.getType()),
|
||||
config);
|
||||
|
||||
return new MappedProperties(entity, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates {@link MappedProperties} for the given {@link PersistentEntity} for serialization purposes. Includes
|
||||
* Jackson-read-only properties.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param mapper must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static MappedProperties forSerialization(PersistentEntity<?, ?> entity, ObjectMapper mapper) {
|
||||
|
||||
SerializationConfig config = mapper.getSerializationConfig();
|
||||
BeanDescription description = INTROSPECTOR.forSerialization(config, mapper.constructType(entity.getType()), config);
|
||||
|
||||
return new MappedProperties(entity, description);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
||||
import com.fasterxml.jackson.databind.AnnotationIntrospector;
|
||||
import com.fasterxml.jackson.databind.BeanDescription;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
|
||||
import com.fasterxml.jackson.databind.introspect.BasicClassIntrospector;
|
||||
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
|
||||
@@ -200,8 +201,10 @@ class WrappedProperties {
|
||||
}
|
||||
|
||||
private BeanDescription getBeanDescription(Class<?> type) {
|
||||
return INTROSPECTOR.forDeserialization(mapper.getDeserializationConfig(), mapper.constructType(type),
|
||||
mapper.getDeserializationConfig());
|
||||
|
||||
SerializationConfig config = mapper.getSerializationConfig();
|
||||
|
||||
return INTROSPECTOR.forSerialization(config, mapper.constructType(type), config);
|
||||
}
|
||||
|
||||
private static AnnotatedMember findAnnotatedMember(BeanPropertyDefinition property) {
|
||||
|
||||
@@ -38,7 +38,7 @@ public class MappedPropertiesUnitTests {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
KeyValueMappingContext context = new KeyValueMappingContext();
|
||||
KeyValuePersistentEntity<?> entity = context.getPersistentEntity(Sample.class);
|
||||
MappedProperties properties = MappedProperties.fromJacksonProperties(entity, mapper);
|
||||
MappedProperties properties = MappedProperties.forDeserialization(entity, mapper);
|
||||
|
||||
@Test // DATAREST-575
|
||||
public void doesNotExposeMappedPropertyForNonSpringDataPersistentProperty() {
|
||||
@@ -76,6 +76,15 @@ public class MappedPropertiesUnitTests {
|
||||
assertThat(properties.getPersistentProperty("readOnlyProperty"), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test // DATAREST-1248
|
||||
public void doesNotExcludeReadOnlyPropertiesForSerialization() {
|
||||
|
||||
MappedProperties properties = MappedProperties.forSerialization(entity, mapper);
|
||||
|
||||
assertThat(properties.hasPersistentPropertyForField("readOnlyProperty"), is(true));
|
||||
assertThat(properties.getPersistentProperty("readOnlyProperty"), is(notNullValue()));
|
||||
}
|
||||
|
||||
static class Sample {
|
||||
|
||||
public @Transient String notExposedBySpringData;
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.data.rest.webmvc.json.JacksonMappingAwareSortTranslat
|
||||
import org.springframework.data.rest.webmvc.mapping.Associations;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty.Access;
|
||||
import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@@ -172,12 +173,22 @@ public class SortTranslatorUnitTests {
|
||||
assertThat(translatedSort.getOrderFor("burrito.embedded.name"), is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test // DATAREST-1248
|
||||
public void allowsSortingByReadOnlyProperty() {
|
||||
|
||||
Sort sort = sortTranslator.translateSort(new Sort("readOnly"), mappingContext.getPersistentEntity(Plain.class));
|
||||
|
||||
assertThat(sort, is(notNullValue()));
|
||||
assertThat(sort.getOrderFor("readOnly"), is(notNullValue()));
|
||||
}
|
||||
|
||||
static class Plain {
|
||||
|
||||
public String name;
|
||||
public Embedded embedded;
|
||||
@Reference public Embedded refEmbedded;
|
||||
@Reference public AnotherRootEntity association;
|
||||
@JsonProperty(access = Access.READ_ONLY) public String readOnly;
|
||||
}
|
||||
|
||||
static class UnwrapEmbedded {
|
||||
|
||||
Reference in New Issue
Block a user