DATAGEODE-72 - Fix MappingPdxSerializer to ignore transient, non-writable and non-entity-based (simple type) properties and fields.
This commit is contained in:
@@ -16,14 +16,12 @@
|
||||
|
||||
package org.springframework.data.gemfire.mapping;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import org.apache.geode.DataSerializable;
|
||||
import org.apache.geode.Instantiator;
|
||||
@@ -35,9 +33,15 @@ import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.annotation.ReadOnlyProperty;
|
||||
import org.springframework.data.annotation.Transient;
|
||||
import org.springframework.data.gemfire.GemfireUtils;
|
||||
import org.springframework.data.gemfire.repository.sample.Address;
|
||||
import org.springframework.data.gemfire.repository.sample.Person;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link MappingPdxSerializer}.
|
||||
*
|
||||
@@ -46,75 +50,115 @@ import org.springframework.data.gemfire.repository.sample.Person;
|
||||
*/
|
||||
public class MappingPdxSerializerIntegrationTests {
|
||||
|
||||
static Region<Object, Object> region;
|
||||
|
||||
static Cache cache;
|
||||
|
||||
static Region<Object, Object> region;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() {
|
||||
MappingPdxSerializer serializer = new MappingPdxSerializer(new GemfireMappingContext(),
|
||||
new DefaultConversionService());
|
||||
|
||||
MappingPdxSerializer serializer =
|
||||
new MappingPdxSerializer(new GemfireMappingContext(), new DefaultConversionService());
|
||||
|
||||
cache = new CacheFactory()
|
||||
.set("name", MappingPdxSerializerIntegrationTests.class.getSimpleName())
|
||||
.set("mcast-port", "0")
|
||||
.set("log-level", "warning")
|
||||
.set("log-level", "error")
|
||||
.setPdxSerializer(serializer)
|
||||
.setPdxPersistent(true)
|
||||
.create();
|
||||
|
||||
region = cache.createRegionFactory()
|
||||
.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE)
|
||||
.create("foo");
|
||||
.setDataPolicy(DataPolicy.PARTITION)
|
||||
.create("TemporaryRegion");
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@SuppressWarnings("all")
|
||||
public static void tearDown() {
|
||||
try {
|
||||
cache.close();
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
finally {
|
||||
for (String name : new File(".").list(new FilenameFilter() {
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.startsWith("BACKUP");
|
||||
}
|
||||
})) {
|
||||
new File(name).delete();
|
||||
}
|
||||
}
|
||||
GemfireUtils.close(cache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeAndDeserializeCorrectly() {
|
||||
public void handlesEntityWithReadOnlyProperty() {
|
||||
|
||||
EntityWithReadOnlyProperty entity = new EntityWithReadOnlyProperty();
|
||||
|
||||
entity.setName("ReadOnlyEntity");
|
||||
entity.setTimestamp(LocalDateTime.now());
|
||||
entity.processId = 123;
|
||||
|
||||
region.put(100L, entity);
|
||||
|
||||
Object target = region.get(100L);
|
||||
|
||||
assertThat(target).isInstanceOf(EntityWithReadOnlyProperty.class);
|
||||
assertThat(target).isNotSameAs(entity);
|
||||
|
||||
EntityWithReadOnlyProperty deserializedEntity = (EntityWithReadOnlyProperty) target;
|
||||
|
||||
assertThat(deserializedEntity.getName()).isEqualTo(entity.getName());
|
||||
assertThat(deserializedEntity.getTimestamp()).isEqualTo(entity.getTimestamp());
|
||||
assertThat(deserializedEntity.getProcessId()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlesEntityWithTransientProperty() {
|
||||
|
||||
EntityWithTransientProperty entity = new EntityWithTransientProperty();
|
||||
|
||||
entity.setName("TransientEntity");
|
||||
entity.setValueOne("testOne");
|
||||
entity.setValueTwo("testTwo");
|
||||
|
||||
region.put(101L, entity);
|
||||
|
||||
Object target = region.get(101L);
|
||||
|
||||
assertThat(target).isInstanceOf(EntityWithTransientProperty.class);
|
||||
assertThat(target).isNotSameAs(entity);
|
||||
|
||||
EntityWithTransientProperty deserializedEntity = (EntityWithTransientProperty) target;
|
||||
|
||||
assertThat(deserializedEntity.getName()).isEqualTo(entity.getName());
|
||||
assertThat(deserializedEntity.getValueOne()).isNull();
|
||||
assertThat(deserializedEntity.getValueTwo()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void serializesAndDeserializesEntityCorrectly() {
|
||||
|
||||
Address address = new Address();
|
||||
address.zipCode = "01234";
|
||||
|
||||
address.street = "100 Main St.";
|
||||
address.city = "London";
|
||||
address.zipCode = "01234";
|
||||
|
||||
Person person = new Person(1L, "Oliver", "Gierke");
|
||||
person.address = address;
|
||||
|
||||
person.address = address;
|
||||
region.put(1L, person);
|
||||
|
||||
Object result = region.get(1L);
|
||||
|
||||
assertThat(result instanceof Person, is(true));
|
||||
assertThat(result).isInstanceOf(Person.class);
|
||||
assertThat(result).isNotSameAs(person);
|
||||
|
||||
Person reference = person;
|
||||
assertThat(reference.getFirstname(), is(person.getFirstname()));
|
||||
assertThat(reference.getLastname(), is(person.getLastname()));
|
||||
assertThat(reference.address, is(person.address));
|
||||
Person reference = (Person) result;
|
||||
|
||||
assertThat(reference.getFirstname()).isEqualTo(person.getFirstname());
|
||||
assertThat(reference.getLastname()).isEqualTo(person.getLastname());
|
||||
assertThat(reference.getAddress()).isEqualTo(person.getAddress());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void serializeAndDeserializeCorrectlyWithDataSerializable() {
|
||||
public void serializesAndDeserializesEntityWithDataSerializableProperty() {
|
||||
|
||||
Address address = new Address();
|
||||
address.zipCode = "01234";
|
||||
|
||||
address.street = "100 Main St.";
|
||||
address.city = "London";
|
||||
address.zipCode = "01234";
|
||||
|
||||
PersonWithDataSerializableProperty person =
|
||||
new PersonWithDataSerializableProperty(2L, "Oliver", "Gierke",
|
||||
@@ -123,32 +167,40 @@ public class MappingPdxSerializerIntegrationTests {
|
||||
person.address = address;
|
||||
|
||||
region.put(2L, person);
|
||||
|
||||
Object result = region.get(2L);
|
||||
|
||||
assertThat(result instanceof PersonWithDataSerializableProperty, is(true));
|
||||
assertThat(result).isInstanceOf(PersonWithDataSerializableProperty.class);
|
||||
assertThat(result).isNotSameAs(person);
|
||||
|
||||
PersonWithDataSerializableProperty reference = person;
|
||||
assertThat(reference.getFirstname(), is(person.getFirstname()));
|
||||
assertThat(reference.getLastname(), is(person.getLastname()));
|
||||
assertThat(reference.address, is(person.address));
|
||||
assertThat(reference.dsProperty.getValue(),is("foo"));
|
||||
PersonWithDataSerializableProperty reference = (PersonWithDataSerializableProperty) result;
|
||||
|
||||
assertThat(reference.getFirstname()).isEqualTo(person.getFirstname());
|
||||
assertThat(reference.getLastname()).isEqualTo(person.getLastname());
|
||||
assertThat(reference.getAddress()).isEqualTo(person.getAddress());
|
||||
assertThat(reference.property.getValue()).isEqualTo("foo");
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@SuppressWarnings({ "serial", "unused" })
|
||||
public static class PersonWithDataSerializableProperty extends Person {
|
||||
|
||||
private DataSerializableProperty dsProperty;
|
||||
private DataSerializableProperty property;
|
||||
|
||||
public PersonWithDataSerializableProperty(Long id, String firstname,
|
||||
String lastname, DataSerializableProperty dsProperty) {
|
||||
String lastname, DataSerializableProperty property) {
|
||||
|
||||
super(id, firstname, lastname);
|
||||
this.dsProperty = dsProperty;
|
||||
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public DataSerializableProperty getDataSerializableProperty() {
|
||||
return this.dsProperty;
|
||||
return this.property;
|
||||
}
|
||||
|
||||
public void setDataSerializableProperty(DataSerializableProperty property) {
|
||||
this.property = property;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@@ -170,20 +222,44 @@ public class MappingPdxSerializerIntegrationTests {
|
||||
|
||||
|
||||
@Override
|
||||
public void fromData(DataInput dataInput) throws IOException,
|
||||
ClassNotFoundException {
|
||||
value = dataInput.readUTF();
|
||||
public void fromData(DataInput dataInput) throws IOException, ClassNotFoundException {
|
||||
this.value = dataInput.readUTF();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toData(DataOutput dataOutput) throws IOException {
|
||||
dataOutput.writeUTF(value);
|
||||
dataOutput.writeUTF(this.value);
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
static class EntityWithReadOnlyProperty {
|
||||
|
||||
@Setter
|
||||
LocalDateTime timestamp;
|
||||
|
||||
@Setter
|
||||
String name;
|
||||
|
||||
// TODO: if there is not setter, then effectively this field/property is read-only
|
||||
// and should not require the @ReadOnlyProperty
|
||||
@ReadOnlyProperty
|
||||
Object processId;
|
||||
}
|
||||
|
||||
@Getter @Setter
|
||||
static class EntityWithTransientProperty {
|
||||
|
||||
private String name;
|
||||
|
||||
private transient Object valueOne;
|
||||
|
||||
@Transient
|
||||
private Object valueTwo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,36 +17,40 @@
|
||||
package org.springframework.data.gemfire.mapping;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.isA;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
import static org.mockito.Mockito.atMost;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.pdx.PdxReader;
|
||||
import org.apache.geode.pdx.PdxSerializer;
|
||||
import org.apache.geode.pdx.PdxWriter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.EntityInstantiator;
|
||||
import org.springframework.data.convert.EntityInstantiators;
|
||||
import org.springframework.data.gemfire.repository.sample.Address;
|
||||
import org.springframework.data.gemfire.repository.sample.Person;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.model.ParameterValueProvider;
|
||||
|
||||
/**
|
||||
@@ -72,12 +76,9 @@ public class MappingPdxSerializerUnitTests {
|
||||
|
||||
ConversionService conversionService;
|
||||
|
||||
GemfireMappingContext context;
|
||||
GemfireMappingContext mappingContext;
|
||||
|
||||
MappingPdxSerializer serializer;
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
MappingPdxSerializer pdxSerializer;
|
||||
|
||||
@Mock
|
||||
EntityInstantiator mockInstantiator;
|
||||
@@ -93,14 +94,70 @@ public class MappingPdxSerializerUnitTests {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
context = new GemfireMappingContext();
|
||||
conversionService = new GenericConversionService();
|
||||
serializer = new MappingPdxSerializer(context, conversionService);
|
||||
serializer.setCustomSerializers(Collections.singletonMap(Address.class, mockAddressSerializer));
|
||||
|
||||
this.conversionService = new GenericConversionService();
|
||||
this.mappingContext = new GemfireMappingContext();
|
||||
this.pdxSerializer = new MappingPdxSerializer(this.mappingContext, this.conversionService);
|
||||
this.pdxSerializer.setCustomSerializers(Collections.singletonMap(Address.class, this.mockAddressSerializer));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createFullyInitialized() {
|
||||
public void constructDefaultMappingPdxSerializer() {
|
||||
|
||||
MappingPdxSerializer pdxSerializer = new MappingPdxSerializer();
|
||||
|
||||
assertThat(pdxSerializer.getConversionService()).isInstanceOf(DefaultConversionService.class);
|
||||
assertThat(pdxSerializer.getCustomSerializers()).isEmpty();
|
||||
assertThat(pdxSerializer.getGemfireInstantiators()).isInstanceOf(EntityInstantiators.class);
|
||||
assertThat(pdxSerializer.getMappingContext()).isInstanceOf(GemfireMappingContext.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructMappingPdxSerializer() {
|
||||
|
||||
ConversionService mockConversionService = mock(ConversionService.class);
|
||||
GemfireMappingContext mockMappingContext = mock(GemfireMappingContext.class);
|
||||
|
||||
MappingPdxSerializer pdxSerializer = new MappingPdxSerializer(mockMappingContext, mockConversionService);
|
||||
|
||||
assertThat(pdxSerializer.getConversionService()).isEqualTo(mockConversionService);
|
||||
assertThat(pdxSerializer.getCustomSerializers()).isEmpty();
|
||||
assertThat(pdxSerializer.getGemfireInstantiators()).isInstanceOf(EntityInstantiators.class);
|
||||
assertThat(pdxSerializer.getMappingContext()).isEqualTo(mockMappingContext);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructMappingPdxSerializerWithNullConversionService() {
|
||||
|
||||
try {
|
||||
new MappingPdxSerializer(this.mappingContext, null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("ConversionService is required");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructMappingPdxSerializerWithNullMappingContext() {
|
||||
|
||||
try {
|
||||
new MappingPdxSerializer(null, this.conversionService);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("MappingContext is required");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createMappingPdxSerializer() {
|
||||
|
||||
ConversionService mockConversionService = mock(ConversionService.class);
|
||||
GemfireMappingContext mockMappingContext = mock(GemfireMappingContext.class);
|
||||
@@ -147,39 +204,246 @@ public class MappingPdxSerializerUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void usesRegisteredInstantiator() {
|
||||
public void setCustomSerializersWithMappingOfClassTypesToPdxSerializers() {
|
||||
|
||||
Address address = new Address();
|
||||
Map<Class<?>, PdxSerializer> customSerializers =
|
||||
Collections.singletonMap(Person.class, mock(PdxSerializer.class));
|
||||
|
||||
address.city = "London";
|
||||
address.zipCode = "01234";
|
||||
this.pdxSerializer.setCustomSerializers(customSerializers);
|
||||
|
||||
Person person = new Person(1L, "Oliver", "Gierke");
|
||||
assertThat(this.pdxSerializer.getCustomSerializers()).isEqualTo(customSerializers);
|
||||
}
|
||||
|
||||
person.address = address;
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setCustomSerializersToNull() {
|
||||
|
||||
when(mockInstantiator.createInstance(any(GemfirePersistentEntity.class), any(ParameterValueProvider.class)))
|
||||
.thenReturn(person);
|
||||
try {
|
||||
this.pdxSerializer.setCustomSerializers(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
serializer.setGemfireInstantiators(Collections.singletonMap(Person.class, mockInstantiator));
|
||||
assertThat(expected).hasMessage("Custom PdxSerializers are required");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
serializer.fromData(Person.class, mockReader);
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
GemfirePersistentEntity<?> persistentEntity = context.getPersistentEntity(Person.class);
|
||||
@Test
|
||||
public void getCustomSerializerForMappedType() {
|
||||
|
||||
verify(mockInstantiator, times(1)).createInstance(eq(persistentEntity),
|
||||
any(ParameterValueProvider.class));
|
||||
PdxSerializer mockPdxSerializer = mock(PdxSerializer.class);
|
||||
|
||||
verify(mockAddressSerializer, times(1)).fromData(eq(Address.class), any(PdxReader.class));
|
||||
Map<Class<?>, PdxSerializer> customSerializers = Collections.singletonMap(Person.class, mockPdxSerializer);
|
||||
|
||||
this.pdxSerializer.setCustomSerializers(customSerializers);
|
||||
|
||||
assertThat(this.pdxSerializer.getCustomSerializer(Person.class)).isEqualTo(mockPdxSerializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCustomSerializerForNonMappedType() {
|
||||
|
||||
PdxSerializer mockPdxSerializer = mock(PdxSerializer.class);
|
||||
|
||||
Map<Class<?>, PdxSerializer> customSerializers = Collections.singletonMap(Person.class, mockPdxSerializer);
|
||||
|
||||
this.pdxSerializer.setCustomSerializers(customSerializers);
|
||||
|
||||
assertThat(this.pdxSerializer.getCustomSerializer(Address.class)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setGemfireInstantiatorsWithEntityInstantiators() {
|
||||
|
||||
EntityInstantiators mockEntityInstantiators = mock(EntityInstantiators.class);
|
||||
|
||||
this.pdxSerializer.setGemfireInstantiators(mockEntityInstantiators);
|
||||
|
||||
assertThat(this.pdxSerializer.getGemfireInstantiators()).isSameAs(mockEntityInstantiators);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setGemfireInstantiatorsWithNullEntityInstantiators() {
|
||||
|
||||
try {
|
||||
this.pdxSerializer.setGemfireInstantiators((EntityInstantiators) null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("EntityInstantiators are required");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setGemfireInstantiatorsWithMappingOfClassTypesToEntityInstantiators() {
|
||||
|
||||
Map<Class<?>, EntityInstantiator> entityInstantiators =
|
||||
Collections.singletonMap(Person.class, mock(EntityInstantiator.class));
|
||||
|
||||
this.pdxSerializer.setGemfireInstantiators(entityInstantiators);
|
||||
|
||||
assertThat(this.pdxSerializer.getGemfireInstantiators()).isInstanceOf(EntityInstantiators.class);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setGemfireInstantiatorsWithNullMap() {
|
||||
|
||||
try {
|
||||
this.pdxSerializer.setGemfireInstantiators((Map<Class<?>, EntityInstantiator>) null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("CustomInstantiators must not be null!");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInstantiatorForManagedPersistentEntityWithInstantiator() {
|
||||
|
||||
EntityInstantiator mockEntityInstantiator = mock(EntityInstantiator.class);
|
||||
|
||||
Map<Class<?>, EntityInstantiator> entityInstantiators =
|
||||
Collections.singletonMap(Person.class, mockEntityInstantiator);
|
||||
|
||||
PersistentEntity mockEntity = mock(PersistentEntity.class);
|
||||
|
||||
when(mockEntity.getType()).thenReturn(Person.class);
|
||||
|
||||
this.pdxSerializer.setGemfireInstantiators(entityInstantiators);
|
||||
|
||||
assertThat(this.pdxSerializer.getInstantiatorFor(mockEntity)).isEqualTo(mockEntityInstantiator);
|
||||
|
||||
verify(mockEntity, atLeast(1)).getType();
|
||||
verifyZeroInteractions(mockEntityInstantiator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInstantiatorForNonManagedPersistentEntityWithNoInstantiator() {
|
||||
|
||||
EntityInstantiator mockEntityInstantiator = mock(EntityInstantiator.class);
|
||||
|
||||
Map<Class<?>, EntityInstantiator> entityInstantiators =
|
||||
Collections.singletonMap(Person.class, mockEntityInstantiator);
|
||||
|
||||
PersistentEntity mockEntity = mock(PersistentEntity.class);
|
||||
|
||||
when(mockEntity.getType()).thenReturn(Address.class);
|
||||
|
||||
this.pdxSerializer.setGemfireInstantiators(entityInstantiators);
|
||||
|
||||
assertThat(this.pdxSerializer.getInstantiatorFor(mockEntity)).isNotEqualTo(mockEntityInstantiator);
|
||||
|
||||
verify(mockEntity, atLeast(1)).getType();
|
||||
verifyZeroInteractions(mockEntityInstantiator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isReadableWithNonTransientPropertyReturnsTrue() {
|
||||
|
||||
GemfirePersistentProperty mockPersistentProperty = mock(GemfirePersistentProperty.class);
|
||||
|
||||
when(mockPersistentProperty.isTransient()).thenReturn(false);
|
||||
|
||||
assertThat(this.pdxSerializer.isReadable(mockPersistentProperty)).isTrue();
|
||||
|
||||
verify(mockPersistentProperty, times(1)).isTransient();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isReadableWithTransientPropertyReturnsFalse() {
|
||||
|
||||
GemfirePersistentProperty mockPersistentProperty = mock(GemfirePersistentProperty.class);
|
||||
|
||||
when(mockPersistentProperty.isTransient()).thenReturn(true);
|
||||
|
||||
assertThat(this.pdxSerializer.isReadable(mockPersistentProperty)).isFalse();
|
||||
|
||||
verify(mockPersistentProperty, times(1)).isTransient();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isWritableWithWritablePropertyReturnsTrue() {
|
||||
|
||||
GemfirePersistentEntity<?> mockEntity = mock(GemfirePersistentEntity.class);
|
||||
|
||||
GemfirePersistentProperty mockProperty = mock(GemfirePersistentProperty.class);
|
||||
|
||||
when(mockEntity.isConstructorArgument(any(GemfirePersistentProperty.class))).thenReturn(false);
|
||||
when(mockProperty.isTransient()).thenReturn(false);
|
||||
when(mockProperty.isWritable()).thenReturn(true);
|
||||
|
||||
assertThat(this.pdxSerializer.isWritable(mockEntity, mockProperty)).isTrue();
|
||||
|
||||
verify(mockEntity, times(1)).isConstructorArgument(eq(mockProperty));
|
||||
verify(mockProperty, times(1)).isWritable();
|
||||
verify(mockProperty, times(1)).isTransient();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isWritableWithConstructorArgumentPropertyReturnsFalse() {
|
||||
|
||||
GemfirePersistentEntity<?> mockEntity = mock(GemfirePersistentEntity.class);
|
||||
|
||||
GemfirePersistentProperty mockProperty = mock(GemfirePersistentProperty.class);
|
||||
|
||||
when(mockEntity.isConstructorArgument(any(GemfirePersistentProperty.class))).thenReturn(true);
|
||||
|
||||
assertThat(this.pdxSerializer.isWritable(mockEntity, mockProperty)).isFalse();
|
||||
|
||||
verify(mockEntity, times(1)).isConstructorArgument(eq(mockProperty));
|
||||
verify(mockProperty, never()).isWritable();
|
||||
verify(mockProperty, never()).isTransient();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isWritableWithNonWritablePropertyReturnsFalse() {
|
||||
|
||||
GemfirePersistentEntity<?> mockEntity = mock(GemfirePersistentEntity.class);
|
||||
|
||||
GemfirePersistentProperty mockProperty = mock(GemfirePersistentProperty.class);
|
||||
|
||||
when(mockEntity.isConstructorArgument(any(GemfirePersistentProperty.class))).thenReturn(false);
|
||||
when(mockProperty.isWritable()).thenReturn(false);
|
||||
|
||||
assertThat(this.pdxSerializer.isWritable(mockEntity, mockProperty)).isFalse();
|
||||
|
||||
verify(mockEntity, times(1)).isConstructorArgument(eq(mockProperty));
|
||||
verify(mockProperty, times(1)).isWritable();
|
||||
verify(mockProperty, never()).isTransient();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isWritableWithTransientPropertyReturnsFalse() {
|
||||
|
||||
GemfirePersistentEntity<?> mockEntity = mock(GemfirePersistentEntity.class);
|
||||
|
||||
GemfirePersistentProperty mockProperty = mock(GemfirePersistentProperty.class);
|
||||
|
||||
when(mockEntity.isConstructorArgument(any(GemfirePersistentProperty.class))).thenReturn(false);
|
||||
when(mockProperty.isTransient()).thenReturn(true);
|
||||
when(mockProperty.isWritable()).thenReturn(true);
|
||||
|
||||
assertThat(this.pdxSerializer.isWritable(mockEntity, mockProperty)).isFalse();
|
||||
|
||||
verify(mockEntity, times(1)).isConstructorArgument(eq(mockProperty));
|
||||
verify(mockProperty, times(1)).isWritable();
|
||||
verify(mockProperty, times(1)).isTransient();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void fromDataMapsPdxDataToApplicationDomainObject() {
|
||||
public void fromDataDeserializesPdxAndMapsToApplicationDomainObject() {
|
||||
|
||||
Address expectedAddress = new Address();
|
||||
|
||||
expectedAddress.street = "100 Main St.";
|
||||
expectedAddress.city = "Portland";
|
||||
expectedAddress.zipCode = "12345";
|
||||
|
||||
@@ -190,9 +454,9 @@ public class MappingPdxSerializerUnitTests {
|
||||
when(mockReader.readField(eq("lastname"))).thenReturn("Doe");
|
||||
when(mockAddressSerializer.fromData(eq(Address.class), eq(mockReader))).thenReturn(expectedAddress);
|
||||
|
||||
serializer.setGemfireInstantiators(Collections.singletonMap(Person.class, mockInstantiator));
|
||||
this.pdxSerializer.setGemfireInstantiators(Collections.singletonMap(Person.class, mockInstantiator));
|
||||
|
||||
Object obj = serializer.fromData(Person.class, mockReader);
|
||||
Object obj = this.pdxSerializer.fromData(Person.class, mockReader);
|
||||
|
||||
assertThat(obj).isInstanceOf(Person.class);
|
||||
|
||||
@@ -203,14 +467,15 @@ public class MappingPdxSerializerUnitTests {
|
||||
assertThat(jonDoe.getFirstname()).isEqualTo("Jon");
|
||||
assertThat(jonDoe.getLastname()).isEqualTo("Doe");
|
||||
|
||||
verify(mockInstantiator, times(1)).createInstance(any(GemfirePersistentEntity.class), any(ParameterValueProvider.class));
|
||||
verify(mockInstantiator, times(1))
|
||||
.createInstance(any(GemfirePersistentEntity.class), any(ParameterValueProvider.class));
|
||||
verify(mockReader, times(1)).readField(eq("id"));
|
||||
verify(mockReader, times(1)).readField(eq("firstname"));
|
||||
verify(mockReader, times(1)).readField(eq("lastname"));
|
||||
verify(mockAddressSerializer, times(1)).fromData(eq(Address.class), eq(mockReader));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = MappingException.class)
|
||||
@SuppressWarnings("unchecked")
|
||||
public void fromDataHandlesExceptionProperly() {
|
||||
|
||||
@@ -219,15 +484,18 @@ public class MappingPdxSerializerUnitTests {
|
||||
|
||||
when(mockReader.readField(eq("id"))).thenThrow(newIllegalArgumentException("test"));
|
||||
|
||||
serializer.setGemfireInstantiators(Collections.singletonMap(Person.class, mockInstantiator));
|
||||
|
||||
try {
|
||||
exception.expect(MappingException.class);
|
||||
exception.expectCause(isA(IllegalArgumentException.class));
|
||||
exception.expectMessage(String.format(
|
||||
"While setting value [null] of property [id] for entity of type [%s] from PDX", Person.class));
|
||||
this.pdxSerializer.setGemfireInstantiators(Collections.singletonMap(Person.class, mockInstantiator));
|
||||
this.pdxSerializer.fromData(Person.class, mockReader);
|
||||
}
|
||||
catch (MappingException expected) {
|
||||
|
||||
serializer.fromData(Person.class, mockReader);
|
||||
assertThat(expected).hasMessage("While setting value [null] of property [id] for entity of type [%s] from PDX", Person.class);
|
||||
assertThat(expected).hasCauseInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(expected.getCause()).hasMessage("test");
|
||||
assertThat(expected.getCause()).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockInstantiator, times(1))
|
||||
@@ -237,11 +505,42 @@ public class MappingPdxSerializerUnitTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void fromDataUsesRegisteredInstantiator() {
|
||||
|
||||
Address address = new Address();
|
||||
|
||||
address.street = "100 Main St.";
|
||||
address.city = "London";
|
||||
address.zipCode = "01234";
|
||||
|
||||
Person person = new Person(1L, "Oliver", "Gierke");
|
||||
|
||||
person.address = address;
|
||||
|
||||
when(mockInstantiator.createInstance(any(GemfirePersistentEntity.class), any(ParameterValueProvider.class)))
|
||||
.thenReturn(person);
|
||||
|
||||
this.pdxSerializer.setGemfireInstantiators(Collections.singletonMap(Person.class, mockInstantiator));
|
||||
this.pdxSerializer.fromData(Person.class, mockReader);
|
||||
|
||||
GemfirePersistentEntity<?> persistentEntity =
|
||||
Optional.ofNullable(mappingContext.getPersistentEntity(Person.class)).orElse(null);
|
||||
|
||||
verify(mockInstantiator, times(1))
|
||||
.createInstance(eq(persistentEntity), any(ParameterValueProvider.class));
|
||||
|
||||
verify(mockAddressSerializer, times(1))
|
||||
.fromData(eq(Address.class), any(PdxReader.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDataSerializesApplicationDomainObjectToPdx() {
|
||||
|
||||
Address address = new Address();
|
||||
|
||||
address.street = "100 Main St.";
|
||||
address.city = "Portland";
|
||||
address.zipCode = "12345";
|
||||
|
||||
@@ -249,9 +548,9 @@ public class MappingPdxSerializerUnitTests {
|
||||
|
||||
jonDoe.address = address;
|
||||
|
||||
serializer.setCustomSerializers(Collections.singletonMap(Address.class, mockAddressSerializer));
|
||||
this.pdxSerializer.setCustomSerializers(Collections.singletonMap(Address.class, mockAddressSerializer));
|
||||
|
||||
assertThat(serializer.toData(jonDoe, mockWriter)).isTrue();
|
||||
assertThat(this.pdxSerializer.toData(jonDoe, mockWriter)).isTrue();
|
||||
|
||||
verify(mockAddressSerializer, times(1)).toData(eq(address), eq(mockWriter));
|
||||
verify(mockWriter, times(1)).writeField(eq("id"), eq(1L), eq(Long.class));
|
||||
@@ -260,11 +559,12 @@ public class MappingPdxSerializerUnitTests {
|
||||
verify(mockWriter, times(1)).markIdentityField(eq("id"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = MappingException.class)
|
||||
public void toDataHandlesExceptionProperly() {
|
||||
|
||||
Address address = new Address();
|
||||
|
||||
address.street = "100 Main St.";
|
||||
address.city = "Portland";
|
||||
address.zipCode = "12345";
|
||||
|
||||
@@ -276,13 +576,19 @@ public class MappingPdxSerializerUnitTests {
|
||||
.thenThrow(newIllegalArgumentException("test"));
|
||||
|
||||
try {
|
||||
exception.expect(MappingException.class);
|
||||
exception.expectCause(isA(IllegalArgumentException.class));
|
||||
exception.expectMessage(String.format(
|
||||
"While serializing entity property [address] value [Portland, 12345] of type [%s] to PDX",
|
||||
Person.class));
|
||||
this.pdxSerializer.setCustomSerializers(Collections.emptyMap());
|
||||
this.pdxSerializer.toData(jonDoe, mockWriter);
|
||||
}
|
||||
catch (MappingException expected) {
|
||||
|
||||
new MappingPdxSerializer(context, conversionService).toData(jonDoe, mockWriter);
|
||||
assertThat(expected).hasMessage("While serializing entity [%1$s] property [address]"
|
||||
+ " value [100 Main St. Portland, 12345] of type [%2$s] to PDX",
|
||||
Person.class.getName(), Address.class.getName());
|
||||
assertThat(expected).hasCauseInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(expected.getCause()).hasMessage("test");
|
||||
assertThat(expected.getCause()).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockWriter, atMost(1)).writeField(eq("id"), eq(1L), eq(Long.class));
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.gemfire.repository.sample;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.gemfire.mapping.annotation.Region;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -25,14 +26,44 @@ import org.springframework.data.gemfire.mapping.annotation.Region;
|
||||
@Region("address")
|
||||
public class Address {
|
||||
|
||||
public String street;
|
||||
public String city;
|
||||
|
||||
@Id
|
||||
public String zipCode;
|
||||
|
||||
public String city;
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof Address)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Address that = (Address) obj;
|
||||
|
||||
return ObjectUtils.nullSafeEquals(this.street, that.street)
|
||||
&& ObjectUtils.nullSafeEquals(this.city, that.city)
|
||||
&& ObjectUtils.nullSafeEquals(this.zipCode, that.zipCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int hashValue = 17;
|
||||
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(this.street);
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(this.city);
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(this.zipCode);
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%1$s, %2$s", city, zipCode);
|
||||
return String.format("%1$s %2$s, %3$s", this.street, this.city, this.zipCode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -119,6 +119,7 @@ public class Person implements Serializable {
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user