diff --git a/docs/src/reference/docbook/reference/cache.xml b/docs/src/reference/docbook/reference/cache.xml index 1247b4b0..78dbb1f2 100644 --- a/docs/src/reference/docbook/reference/cache.xml +++ b/docs/src/reference/docbook/reference/cache.xml @@ -193,7 +193,9 @@ com.gemstone.gemfire.pdx.ReflectionBasedAutoSerializer, however it is common for developers to provide their own implementation. The value of the attribute is simply a reference to a Spring bean that - implements the required interface. More information on serialization support can be found in + implements the required interface. More information on serialization + support can be found in + @@ -264,7 +266,7 @@ instantiators defined declaratively to be fully initialized and registered before the server starts accepting connections. Keep this in mind when programmatically configuring these items as the server might - start before your components and thus not be seen by the clients + start after your components and thus not be seen by the clients connecting right away. diff --git a/docs/src/reference/docbook/reference/repositories.xml b/docs/src/reference/docbook/reference/repositories.xml index a2992777..79626bde 100644 --- a/docs/src/reference/docbook/reference/repositories.xml +++ b/docs/src/reference/docbook/reference/repositories.xml @@ -15,7 +15,8 @@ Spring Data GemFire provides support to use the Spring Data repository abstraction to easily persist entities into GemFire and execute queries. A general introduction into the repository programming model is - been provided here + been provided here . @@ -30,14 +31,14 @@ Bootstrap GemFire repositories <beans xmlns="http://www.springframework.org/schema/beans" - xmlns:gf="http://www.springframework.org/schema/gemfire" + xmlns:gfe-data="http://www.springframework.org/schema/data/gemfire" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/gemfire - http://www.springframework.org/schema/gemfire/spring-gemfire.xsd> + http://www.springframework.org/schema/data/gemfire + http://www.springframework.org/schema/data/gemfire/spring-data-gemfire.xsd> - <gf:repositories base-package="com.acme.repository" /> + <gfe-data:repositories base-package="com.acme.repository" /> </beans> @@ -88,11 +89,11 @@ public class Person { … } Supported keywords for query methods - + - + - + diff --git a/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java b/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java index 3e2690cd..6c3ec971 100644 --- a/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java +++ b/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java @@ -121,8 +121,6 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw */ @Override public Object fromData(Class type, final PdxReader reader) { - // TODO: check for custom serializer (PDX) - final GemfirePersistentEntity entity = mappingContext.getPersistentEntity(type); EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity); GemfirePropertyValueProvider propertyValueProvider = new GemfirePropertyValueProvider(reader); @@ -143,9 +141,15 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw if (entity.isConstructorArgument(persistentProperty)) { return; } - // TODO: check for custom serializer (Spring Converter - primitives) - Object value = reader.readField(persistentProperty.getName()); - + + PdxSerializer customSerializer = getCustomSerializer(persistentProperty.getType()); + Object value = null; + if (customSerializer != null) { + System.out.println("using custom serializer"); + value = customSerializer.fromData(persistentProperty.getType(), reader); + } else { + value = reader.readField(persistentProperty.getName()); + } try { wrapper.setProperty(persistentProperty, value); } @@ -166,7 +170,6 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw */ @Override public boolean toData(Object value, final PdxWriter writer) { - // TODO: check for custom serializer (PDX) GemfirePersistentEntity entity = mappingContext.getPersistentEntity(value.getClass()); final BeanWrapper, Object> wrapper = BeanWrapper.create(value, conversionService); @@ -174,10 +177,15 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public void doWithPersistentProperty(GemfirePersistentProperty persistentProperty) { - // TODO: check for custom serializer (Spring Converter) + try { Object propertyValue = wrapper.getProperty(persistentProperty); - writer.writeField(persistentProperty.getName(), propertyValue, (Class) persistentProperty.getType()); + PdxSerializer customSerializer = getCustomSerializer(persistentProperty.getType()); + if (customSerializer != null) { + customSerializer.toData(propertyValue, writer); + } else { + writer.writeField(persistentProperty.getName(), propertyValue, (Class) persistentProperty.getType()); + } } catch (Exception e) { throw new MappingException("Could not write value for property " + persistentProperty.toString(), e); @@ -193,4 +201,8 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw return true; } + + private PdxSerializer getCustomSerializer(Class clazz) { + return customSerializers == null ? null : customSerializers.get(clazz); + } } diff --git a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.2.xsd b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.2.xsd index e8d7ebdd..2de2c78c 100755 --- a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.2.xsd +++ b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.2.xsd @@ -122,12 +122,12 @@ when the same cache is used in multiple application context/bean factories insid ]]> - diff --git a/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerIntegrationTest.java b/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerIntegrationTest.java index 69129378..68b30090 100644 --- a/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerIntegrationTest.java +++ b/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerIntegrationTest.java @@ -18,16 +18,21 @@ package org.springframework.data.gemfire.mapping; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import java.io.DataInput; +import java.io.DataOutput; import java.io.File; import java.io.FilenameFilter; +import java.io.IOException; import org.junit.AfterClass; -import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.data.gemfire.repository.sample.Address; import org.springframework.data.gemfire.repository.sample.Person; +import com.gemstone.gemfire.DataSerializable; +import com.gemstone.gemfire.Instantiator; import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.cache.CacheFactory; import com.gemstone.gemfire.cache.DataPolicy; @@ -41,12 +46,12 @@ import com.gemstone.gemfire.cache.RegionFactory; */ public class MappingPdxSerializerIntegrationTest { - Region region; + static Region region; static Cache cache; - @Before - public void setUp() { + @BeforeClass + public static void setUp() { MappingPdxSerializer serializer = new MappingPdxSerializer(new GemfireMappingContext(), new DefaultConversionService()); @@ -81,6 +86,29 @@ public class MappingPdxSerializerIntegrationTest { assertThat(reference.getLastname(), is(person.getLastname())); assertThat(reference.address, is(person.address)); } + + @Test + public void serializeAndDeserializeCorrectlyWithDataSerializable() { + + Address address = new Address(); + address.zipCode = "01234"; + address.city = "London"; + + PersonWithDataSerializableProperty person = new PersonWithDataSerializableProperty(2L, "Oliver", "Gierke", new DataSerializableProperty("foo")); + person.address = address; + + region.put(2L, person); + Object result = region.get(2L); + + assertThat(result instanceof PersonWithDataSerializableProperty, is(true)); + + 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")); + } + @AfterClass public static void tearDown() { @@ -99,4 +127,57 @@ public class MappingPdxSerializerIntegrationTest { new File(name).delete(); } } + + @SuppressWarnings("serial") + public static class PersonWithDataSerializableProperty extends Person { + + private DataSerializableProperty dsProperty; + + public PersonWithDataSerializableProperty(Long id, String firstname, + String lastname, DataSerializableProperty dsProperty) { + super(id, firstname, lastname); + this.dsProperty = dsProperty; + } + + public DataSerializableProperty getDataSerializableProperty() { + return this.dsProperty; + } + + } + + @SuppressWarnings("serial") + public static class DataSerializableProperty implements DataSerializable { + + static { + Instantiator.register(new Instantiator(DataSerializableProperty.class,101) { + public DataSerializable newInstance() { + return new DataSerializableProperty(""); + } + }); + } + + private String value; + + public DataSerializableProperty(String value) { + this.value = value; + } + + + @Override + public void fromData(DataInput dataInput) throws IOException, + ClassNotFoundException { + value = dataInput.readUTF(); + + } + + @Override + public void toData(DataOutput dataOutput) throws IOException { + dataOutput.writeUTF(value); + } + + public String getValue() { + return this.value; + } + + } } diff --git a/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerUnitTests.java b/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerUnitTests.java index a6f43ace..b95ace9c 100644 --- a/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerUnitTests.java @@ -29,10 +29,12 @@ import org.mockito.runners.MockitoJUnitRunner; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.convert.EntityInstantiator; +import org.springframework.data.gemfire.repository.sample.Address; import org.springframework.data.gemfire.repository.sample.Person; import org.springframework.data.mapping.model.ParameterValueProvider; import com.gemstone.gemfire.pdx.PdxReader; +import com.gemstone.gemfire.pdx.PdxSerializer; /** * Unit tests for {@link MappingPdxSerializer}. @@ -50,6 +52,9 @@ public class MappingPdxSerializerUnitTests { EntityInstantiator instantiator; @Mock PdxReader reader; + + @Mock + PdxSerializer addressSerializer; @Before public void setUp() { @@ -57,14 +62,21 @@ public class MappingPdxSerializerUnitTests { context = new GemfireMappingContext(); conversionService = new GenericConversionService(); serializer = new MappingPdxSerializer(context, conversionService); + Map,PdxSerializer> customSerializers = new HashMap, PdxSerializer>(); + customSerializers.put(Address.class, addressSerializer); + serializer.setCustomSerializers(customSerializers); } @Test @SuppressWarnings("unchecked") public void usesRegisteredInstantiator() { + Address address = new Address(); + address.zipCode = "01234"; + address.city = "London"; Person person = new Person(1L, "Oliver", "Gierke"); - + person.address = address; + ParameterValueProvider provider = any(ParameterValueProvider.class); GemfirePersistentEntity entity = any(GemfirePersistentEntity.class); when(instantiator.createInstance(entity, provider)).thenReturn(person); @@ -77,5 +89,6 @@ public class MappingPdxSerializerUnitTests { verify(instantiator, times(1)).createInstance(eq(context.getPersistentEntity(Person.class)), any(ParameterValueProvider.class)); + verify(addressSerializer,times(1)).fromData(eq(Address.class), any(PdxReader.class)); } }