diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfiguration.java index 759fe519..fc8f842d 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfiguration.java @@ -37,7 +37,9 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; @@ -45,6 +47,7 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportAware; +import org.springframework.core.convert.ConversionService; import org.springframework.core.io.Resource; import org.springframework.core.type.AnnotationMetadata; import org.springframework.data.gemfire.CacheFactoryBean; @@ -52,6 +55,8 @@ import org.springframework.data.gemfire.config.support.CustomEditorBeanFactoryPo import org.springframework.data.gemfire.config.support.DefinedIndexesApplicationListener; import org.springframework.data.gemfire.config.support.DiskStoreDirectoryBeanPostProcessor; import org.springframework.data.gemfire.config.support.PdxDiskStoreAwareBeanFactoryPostProcessor; +import org.springframework.data.gemfire.mapping.GemfireMappingContext; +import org.springframework.data.gemfire.mapping.MappingPdxSerializer; import org.springframework.data.gemfire.util.PropertiesBuilder; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -118,6 +123,9 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware private GatewayConflictResolver gatewayConflictResolver; + @Autowired(required = false) + private GemfireMappingContext mappingContext; + private List jndiDataSources; private List transactionListeners; @@ -306,20 +314,16 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware * @see GemFire PDX Serialization */ protected void configurePdx(AnnotationMetadata importMetadata) { - if (importMetadata.hasAnnotation(EnablePdx.class.getName())) { - Map enablePdxAttributes = importMetadata.getAnnotationAttributes(EnablePdx.class.getName()); + String enablePdxTypeName = EnablePdx.class.getName(); - String pdxSerializerBeanName = (String) enablePdxAttributes.get("serializerBeanName"); + if (importMetadata.hasAnnotation(enablePdxTypeName)) { + Map enablePdxAttributes = importMetadata.getAnnotationAttributes(enablePdxTypeName); - if (beanFactory().containsBean(pdxSerializerBeanName)) { - PdxSerializer pdxSerializer = beanFactory().getBean(pdxSerializerBeanName, PdxSerializer.class); - - setPdxDiskStoreName((String) enablePdxAttributes.get("diskStoreName")); - setPdxIgnoreUnreadFields(Boolean.TRUE.equals(enablePdxAttributes.get("ignoreUnreadFields"))); - setPdxPersistent(Boolean.TRUE.equals(enablePdxAttributes.get("persistent"))); - setPdxReadSerialized(Boolean.TRUE.equals(enablePdxAttributes.get("readSerialized"))); - setPdxSerializer(pdxSerializer); - } + setPdxDiskStoreName((String) enablePdxAttributes.get("diskStoreName")); + setPdxIgnoreUnreadFields(Boolean.TRUE.equals(enablePdxAttributes.get("ignoreUnreadFields"))); + setPdxPersistent(Boolean.TRUE.equals(enablePdxAttributes.get("persistent"))); + setPdxReadSerialized(Boolean.TRUE.equals(enablePdxAttributes.get("readSerialized"))); + setPdxSerializer(resolvePdxSerializer((String) enablePdxAttributes.get("serializerBeanName"))); } } @@ -333,6 +337,27 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware protected void configureOther(AnnotationMetadata importMetadata) { } + /* (non-Javadoc) */ + protected PdxSerializer resolvePdxSerializer(String pdxSerializerBeanName) { + BeanFactory beanFactory = beanFactory(); + PdxSerializer pdxSerializer = pdxSerializer(); + + return (beanFactory.containsBean(pdxSerializerBeanName) + ? beanFactory.getBean(pdxSerializerBeanName, PdxSerializer.class) + : (pdxSerializer != null ? pdxSerializer : newPdxSerializer())); + } + + /* (non-Javadoc) */ + @SuppressWarnings("unchecked") + protected T newPdxSerializer() { + BeanFactory beanFactory = beanFactory(); + + ConversionService conversionService = (beanFactory instanceof ConfigurableBeanFactory + ? ((ConfigurableBeanFactory) beanFactory).getConversionService() : null); + + return (T) MappingPdxSerializer.create(this.mappingContext, conversionService); + } + /* (non-Javadoc) */ protected void registerCustomEditorBeanFactoryPostProcessor(AnnotationMetadata importMetadata) { if (CUSTOM_EDITORS_REGISTERED.compareAndSet(false, true)) { @@ -484,6 +509,25 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware return (annotationType.equals(getAnnotationType()) && importMetadata.hasAnnotation(getAnnotationTypeName())); } + /** + * Determines whether this is a GemFire {@link com.gemstone.gemfire.cache.server.CacheServer} or + * {@link com.gemstone.gemfire.cache.Cache peer cache} application, which is indicated by the presence + * of either the {@link CacheServerApplication} annotation or the {@link PeerCacheApplication} annotation + * on a Spring application {@link org.springframework.context.annotation.Configuration @Configuration} class. + * + * @param importMetadata {@link AnnotationMetadata} containing application configuration meta-data + * from the annotations used to configure the Spring application. + * @return a boolean value indicating whether this is a GemFire cache server or peer cache application. + * @see org.springframework.core.type.AnnotationMetadata + * @see org.springframework.data.gemfire.config.annotation.CacheServerApplication + * @see org.springframework.data.gemfire.config.annotation.PeerCacheApplication + * @see #isCacheServerApplication(AnnotationMetadata) + * @see #isPeerCacheApplication(AnnotationMetadata) + */ + protected boolean isCacheServerOrPeerCacheApplication(AnnotationMetadata importMetadata) { + return (isCacheServerApplication(importMetadata) || isPeerCacheApplication(importMetadata)); + } + /** * Determine whether this Spring application is a {@link com.gemstone.gemfire.cache.server.CacheServer}, * {@link com.gemstone.gemfire.cache.client.ClientCache} or a {@link com.gemstone.gemfire.cache.Cache} application. @@ -654,6 +698,15 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware return defaultIfNull(this.logLevel, DEFAULT_LOG_LEVEL); } + /* (non-Javadoc) */ + void setMappingContext(GemfireMappingContext mappingContext) { + this.mappingContext = mappingContext; + } + + protected GemfireMappingContext mappingContext() { + return this.mappingContext; + } + void setMcastPort(Integer mcastPort) { this.mcastPort = mcastPort; setLocators(DEFAULT_LOCATORS); diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/PeerCacheConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/PeerCacheConfiguration.java index 202da39d..03d01803 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/PeerCacheConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/PeerCacheConfiguration.java @@ -82,12 +82,13 @@ public class PeerCacheConfiguration extends AbstractCacheConfiguration { * @param importMetadata {@link AnnotationMetadata} containing peer cache meta-data used to configure * the GemFire peer {@link com.gemstone.gemfire.cache.Cache}. * @see org.springframework.core.type.AnnotationMetadata + * @see #isCacheServerOrPeerCacheApplication(AnnotationMetadata) */ @Override protected void configureCache(AnnotationMetadata importMetadata) { super.configureCache(importMetadata); - if (isPeerCacheApplication(importMetadata) || isCacheServerApplication(importMetadata)) { + if (isCacheServerOrPeerCacheApplication(importMetadata)) { Map peerCacheApplicationAttributes = importMetadata.getAnnotationAttributes(getAnnotationTypeName()); diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/support/EmbeddedServiceConfigurationSupport.java b/src/main/java/org/springframework/data/gemfire/config/annotation/support/EmbeddedServiceConfigurationSupport.java index 1e896a31..b103ff61 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/support/EmbeddedServiceConfigurationSupport.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/support/EmbeddedServiceConfigurationSupport.java @@ -40,6 +40,7 @@ import org.springframework.util.StringUtils; * * @author John Blum * @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar + * @see org.springframework.data.gemfire.config.annotation.AbstractCacheConfiguration * @since 1.9.0 */ @SuppressWarnings("unused") @@ -102,11 +103,13 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD * {@inheritDoc} */ @Override - public final void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + public final void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, + BeanDefinitionRegistry registry) { + if (isAnnotationPresent(importingClassMetadata)) { Map annotationAttributes = getAnnotationAttributes(importingClassMetadata); registerBeanDefinitions(importingClassMetadata, annotationAttributes, registry); - setGemFireProperties(registry, annotationAttributes); + setGemFireProperties(importingClassMetadata, annotationAttributes, registry); } } @@ -117,7 +120,9 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD } /* (non-Javadoc) */ - protected void setGemFireProperties(BeanDefinitionRegistry registry, Map annotationAttributes) { + protected void setGemFireProperties(AnnotationMetadata importingClassMetadata, + Map annotationAttributes, BeanDefinitionRegistry registry) { + Properties gemfireProperties = toGemFireProperties(annotationAttributes); if (hasProperties(gemfireProperties)) { 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 f41c34b9..60e5a2ae 100644 --- a/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java +++ b/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java @@ -18,6 +18,10 @@ package org.springframework.data.gemfire.mapping; import java.util.Collections; import java.util.Map; +import com.gemstone.gemfire.pdx.PdxReader; +import com.gemstone.gemfire.pdx.PdxSerializer; +import com.gemstone.gemfire.pdx.PdxWriter; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; @@ -36,14 +40,10 @@ import org.springframework.data.mapping.model.PersistentEntityParameterValueProv import org.springframework.data.mapping.model.SpELContext; import org.springframework.util.Assert; -import com.gemstone.gemfire.pdx.PdxReader; -import com.gemstone.gemfire.pdx.PdxSerializer; -import com.gemstone.gemfire.pdx.PdxWriter; - /** * GemFire {@link PdxSerializer} implementation that uses a Spring Data GemFire {@link GemfireMappingContext} * to read and write entities. - * + * * @author Oliver Gierke * @author David Turanski * @author John Blum @@ -74,8 +74,34 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw private SpELContext context; /** - * Creates a new {@link MappingPdxSerializer} using the default - * {@link GemfireMappingContext} and {@link DefaultConversionService}. + * Factory method to construct a new instance of the {@link MappingPdxSerializer} initialized with the given + * {@link GemfireMappingContext} and Spring {@link ConversionService}. If either the {@link GemfireMappingContext} + * or Spring {@link ConversionService} are {@literal null}, then this factory method will construct default + * instances of each. + * + * @param mappingContext {@link GemfireMappingContext} used by this {@link PdxSerializer} to handle mappings + * between application domain object types and PDX Serialization meta-data/data. + * @param conversionService Spring's {@link ConversionService} used to convert PDX deserialized data to application + * object property types. + * @return an initialized instance of the {@link MappingPdxSerializer}. + * @see org.springframework.core.convert.ConversionService + * @see org.springframework.data.gemfire.mapping.MappingPdxSerializer + */ + public static MappingPdxSerializer create(GemfireMappingContext mappingContext, + ConversionService conversionService) { + + mappingContext = (mappingContext != null ? mappingContext : new GemfireMappingContext()); + conversionService = (conversionService != null ? conversionService : new DefaultConversionService()); + + return new MappingPdxSerializer(mappingContext, conversionService); + } + + /** + * Creates a new {@link MappingPdxSerializer} using the default {@link GemfireMappingContext} + * and {@link DefaultConversionService}. + * + * @see org.springframework.core.convert.support.DefaultConversionService + * @see org.springframework.data.gemfire.mapping.GemfireMappingContext */ public MappingPdxSerializer() { this(new GemfireMappingContext(), new DefaultConversionService()); @@ -100,11 +126,8 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw this.context = new SpELContext(PdxReaderPropertyAccessor.INSTANCE); } - /* - * (non-Javadoc) - * - * @see org.springframework.context.ApplicationContextAware#setApplicationContext( - * org.springframework.context.ApplicationContext) + /** + * {@inheritDoc} */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { @@ -151,11 +174,8 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw return mappingContext; } - /* - * (non-Javadoc) - * - * @see com.gemstone.gemfire.pdx.PdxSerializer#fromData(java.lang.Class, - * com.gemstone.gemfire.pdx.PdxReader) + /** + * {@inheritDoc} */ @Override public Object fromData(final Class type, final PdxReader reader) { @@ -205,11 +225,8 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw return accessor.getBean(); } - /* - * (non-Javadoc) - * - * @see com.gemstone.gemfire.pdx.PdxSerializer#toData(java.lang.Object, - * com.gemstone.gemfire.pdx.PdxWriter) + /** + * {@inheritDoc} */ @Override public boolean toData(final Object value, final PdxWriter writer) { @@ -240,7 +257,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw } else { writer.writeField(persistentProperty.getName(), propertyValue, (Class) persistentProperty.getType()); - } + } } catch (Exception e) { throw new MappingException(String.format( @@ -298,5 +315,4 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw protected GemfirePersistentEntity getPersistentEntity(Class entityType) { return getMappingContext().getPersistentEntity(entityType); } - } diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfigurationUnitTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfigurationUnitTests.java new file mode 100644 index 00000000..248c4d98 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfigurationUnitTests.java @@ -0,0 +1,236 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.springframework.data.gemfire.config.annotation; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; + +import com.gemstone.gemfire.pdx.PdxSerializer; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.data.gemfire.CacheFactoryBean; +import org.springframework.data.gemfire.mapping.GemfireMappingContext; +import org.springframework.data.gemfire.mapping.MappingPdxSerializer; +import org.springframework.util.MethodInvoker; + +/** + * Unit tests for {@link AbstractCacheConfiguration}. + * + * @author John Blum + * @see org.junit.Test + * @see org.mockito.Mock + * @see org.mockito.Mockito + * @see org.mockito.runners.MockitoJUnitRunner + * @see org.springframework.data.gemfire.config.annotation.AbstractCacheConfiguration + * @since 1.9.0 + */ +@RunWith(MockitoJUnitRunner.class) +public class AbstractCacheConfigurationUnitTests { + + @Mock + private BeanFactory mockBeanFactory; + + private TestCacheConfiguration cacheConfiguration; + + @Before + public void setup() { + cacheConfiguration = new TestCacheConfiguration(); + } + + @SuppressWarnings("unchecked") + protected T invokeMethod(Object obj, String methodName) throws Exception { + MethodInvoker methodInvoker = new MethodInvoker(); + methodInvoker.setTargetObject(obj); + methodInvoker.setTargetMethod(methodName); + methodInvoker.prepare(); + return (T) methodInvoker.invoke(); + } + + @Test + public void configurePdxWhenEnablePdxIsConfigured() { + AnnotationMetadata mockAnnotationMetadata = mock(AnnotationMetadata.class); + PdxSerializer mockPdxSerializer = mock(PdxSerializer.class); + + Map annotationAttributes = new HashMap(5); + + annotationAttributes.put("diskStoreName", "BlockDiskStore"); + annotationAttributes.put("ignoreUnreadFields", Boolean.FALSE); + annotationAttributes.put("persistent", Boolean.TRUE); + annotationAttributes.put("readSerialized", Boolean.TRUE); + annotationAttributes.put("serializerBeanName", "MockPdxSerializer"); + + when(mockAnnotationMetadata.hasAnnotation(eq(EnablePdx.class.getName()))).thenReturn(true); + when(mockAnnotationMetadata.getAnnotationAttributes(eq(EnablePdx.class.getName()))) + .thenReturn(annotationAttributes); + when(mockBeanFactory.containsBean(eq("MockPdxSerializer"))).thenReturn(true); + when(mockBeanFactory.getBean(eq("MockPdxSerializer"), eq(PdxSerializer.class))).thenReturn(mockPdxSerializer); + + cacheConfiguration.setBeanFactory(mockBeanFactory); + cacheConfiguration.configurePdx(mockAnnotationMetadata); + + assertThat(cacheConfiguration.pdxDiskStoreName()).isEqualTo("BlockDiskStore"); + assertThat(cacheConfiguration.pdxIgnoreUnreadFields()).isFalse(); + assertThat(cacheConfiguration.pdxPersistent()).isTrue(); + assertThat(cacheConfiguration.pdxReadSerialized()).isTrue(); + assertThat(cacheConfiguration.pdxSerializer()).isEqualTo(mockPdxSerializer); + + verify(mockAnnotationMetadata, times(1)).hasAnnotation(eq(EnablePdx.class.getName())); + verify(mockAnnotationMetadata, times(1)).getAnnotationAttributes(eq(EnablePdx.class.getName())); + verify(mockBeanFactory, times(1)).containsBean(eq("MockPdxSerializer")); + verify(mockBeanFactory, times(1)).getBean(eq("MockPdxSerializer"), eq(PdxSerializer.class)); + } + + @Test + public void configurePdxWhenEnablePdxIsNotConfigured() { + AnnotationMetadata mockAnnotationMetadata = mock(AnnotationMetadata.class); + + when(mockAnnotationMetadata.hasAnnotation(anyString())).thenReturn(false); + + cacheConfiguration.configurePdx(mockAnnotationMetadata); + + assertThat(cacheConfiguration.pdxDiskStoreName()).isNull(); + assertThat(cacheConfiguration.pdxIgnoreUnreadFields()).isNull(); + assertThat(cacheConfiguration.pdxPersistent()).isNull(); + assertThat(cacheConfiguration.pdxReadSerialized()).isNull(); + assertThat(cacheConfiguration.pdxSerializer()).isNull(); + + verify(mockAnnotationMetadata, times(1)).hasAnnotation(eq(EnablePdx.class.getName())); + verifyNoMoreInteractions(mockAnnotationMetadata); + } + + @Test + public void resolvePdxSerializerUsesPdxSerializerBean() { + PdxSerializer mockPdxSerializer = mock(PdxSerializer.class); + + when(mockBeanFactory.containsBean(anyString())).thenReturn(true); + when(mockBeanFactory.getBean(anyString(), eq(PdxSerializer.class))).thenReturn(mockPdxSerializer); + + cacheConfiguration.setBeanFactory(mockBeanFactory); + + PdxSerializer actualPdxSerializer = cacheConfiguration.resolvePdxSerializer("MockPdxSerializer"); + + assertThat(actualPdxSerializer).isEqualTo(mockPdxSerializer); + + verify(mockBeanFactory, times(1)).containsBean(eq("MockPdxSerializer")); + verify(mockBeanFactory, times(1)).getBean(eq("MockPdxSerializer"), eq(PdxSerializer.class)); + } + + @Test + public void resolvePdxSerializerUsesConfiguredPdxSerializer() { + PdxSerializer mockPdxSerializer = mock(PdxSerializer.class); + + when(mockBeanFactory.containsBean(anyString())).thenReturn(false); + + cacheConfiguration.setBeanFactory(mockBeanFactory); + cacheConfiguration.setPdxSerializer(mockPdxSerializer); + + PdxSerializer actualPdxSerializer = cacheConfiguration.resolvePdxSerializer("TestPdxSerializer"); + + assertThat(actualPdxSerializer).isEqualTo(mockPdxSerializer); + + verify(mockBeanFactory, times(1)).containsBean(eq("TestPdxSerializer")); + verify(mockBeanFactory, never()).getBean(anyString(), eq(PdxSerializer.class)); + verifyZeroInteractions(mockPdxSerializer); + } + + @Test + public void resolvePdxSerializerCallsNewMappingPdxSerializer() { + AbstractCacheConfiguration cacheConfigurationSpy = spy(this.cacheConfiguration); + MappingPdxSerializer mockPdxSerializer = mock(MappingPdxSerializer.class); + + when(mockBeanFactory.containsBean(anyString())).thenReturn(false); + doReturn(mockPdxSerializer).when(cacheConfigurationSpy).newPdxSerializer(); + + cacheConfigurationSpy.setBeanFactory(mockBeanFactory); + + PdxSerializer actualPdxSerializer = cacheConfigurationSpy.resolvePdxSerializer("TestPdxSerializer"); + + assertThat(actualPdxSerializer).isEqualTo(mockPdxSerializer); + + verify(mockBeanFactory, times(1)).containsBean(eq("TestPdxSerializer")); + verify(mockBeanFactory, never()).getBean(anyString(), eq(PdxSerializer.class)); + verify(cacheConfigurationSpy, times(1)).newPdxSerializer(); + } + + @Test + public void newPdxSerializerUsesConfiguredConversionServiceAndMappingContext() throws Exception { + ConfigurableBeanFactory mockBeanFactory = mock(ConfigurableBeanFactory.class); + ConversionService mockConversionService = mock(ConversionService.class); + GemfireMappingContext mockMappingContext = mock(GemfireMappingContext.class); + + when(mockBeanFactory.getConversionService()).thenReturn(mockConversionService); + + cacheConfiguration.setBeanFactory(mockBeanFactory); + cacheConfiguration.setMappingContext(mockMappingContext); + + MappingPdxSerializer pdxSerializer = cacheConfiguration.newPdxSerializer(); + + assertThat(pdxSerializer).isNotNull(); + assertThat(invokeMethod(pdxSerializer, "getConversionService")).isEqualTo(mockConversionService); + assertThat(invokeMethod(pdxSerializer, "getMappingContext")).isEqualTo(mockMappingContext); + + verify(mockBeanFactory, times(1)).getConversionService(); + verifyZeroInteractions(mockConversionService); + verifyZeroInteractions(mockMappingContext); + } + + @Test + public void newPdxSerializerDefaultsConversionServiceAndMappingContextWhenNotConfigured() throws Exception { + cacheConfiguration.setBeanFactory(mockBeanFactory); + + MappingPdxSerializer pdxSerializer = cacheConfiguration.newPdxSerializer(); + + assertThat(pdxSerializer).isNotNull(); + assertThat(invokeMethod(pdxSerializer, "getConversionService")).isInstanceOf(ConversionService.class); + assertThat(invokeMethod(pdxSerializer, "getMappingContext")).isInstanceOf(GemfireMappingContext.class); + } + + protected static class TestCacheConfiguration extends AbstractCacheConfiguration { + + @Override + protected Class getAnnotationType() { + throw new UnsupportedOperationException("Not Implemented"); + } + + @Override + protected T newCacheFactoryBean() { + throw new UnsupportedOperationException("Not Implemented"); + } + } +} 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 ba8d0f4b..d0b00314 100644 --- a/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerUnitTests.java @@ -15,15 +15,13 @@ */ package org.springframework.data.gemfire.mapping; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.isA; -import static org.junit.Assert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; 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; @@ -31,6 +29,10 @@ import static org.mockito.Mockito.when; import java.util.Collections; +import com.gemstone.gemfire.pdx.PdxReader; +import com.gemstone.gemfire.pdx.PdxSerializer; +import com.gemstone.gemfire.pdx.PdxWriter; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -46,13 +48,9 @@ import org.springframework.data.gemfire.repository.sample.Person; import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mapping.model.ParameterValueProvider; -import com.gemstone.gemfire.pdx.PdxReader; -import com.gemstone.gemfire.pdx.PdxSerializer; -import com.gemstone.gemfire.pdx.PdxWriter; - /** * Unit tests for {@link MappingPdxSerializer}. - * + * * @author Oliver Gierke * @author John Blum * @see org.junit.Rule @@ -101,6 +99,49 @@ public class MappingPdxSerializerUnitTests { Address.class, mockAddressSerializer)); } + @Test + public void createFullyInitialized() { + ConversionService mockConversionService = mock(ConversionService.class); + GemfireMappingContext mockMappingContext = mock(GemfireMappingContext.class); + + MappingPdxSerializer pdxSerializer = MappingPdxSerializer.create(mockMappingContext, mockConversionService); + + assertThat(pdxSerializer).isNotNull(); + assertThat(pdxSerializer.getConversionService()).isEqualTo(mockConversionService); + assertThat(pdxSerializer.getMappingContext()).isEqualTo(mockMappingContext); + } + + @Test + public void createWithNullConversionService() { + GemfireMappingContext mockMappingContext = mock(GemfireMappingContext.class); + + MappingPdxSerializer pdxSerializer = MappingPdxSerializer.create(mockMappingContext, null); + + assertThat(pdxSerializer).isNotNull(); + assertThat(pdxSerializer.getConversionService()).isInstanceOf(ConversionService.class); + assertThat(pdxSerializer.getMappingContext()).isEqualTo(mockMappingContext); + } + + @Test + public void createWithNullMappingContext() { + ConversionService mockConversionService = mock(ConversionService.class); + + MappingPdxSerializer pdxSerializer = MappingPdxSerializer.create(null, mockConversionService); + + assertThat(pdxSerializer).isNotNull(); + assertThat(pdxSerializer.getConversionService()).isEqualTo(mockConversionService); + assertThat(pdxSerializer.getMappingContext()).isInstanceOf(GemfireMappingContext.class); + } + + @Test + public void createWithNullConversionServiceAndNullMappingContext() { + MappingPdxSerializer pdxSerializer = MappingPdxSerializer.create(null, null); + + assertThat(pdxSerializer).isNotNull(); + assertThat(pdxSerializer.getConversionService()).isInstanceOf(ConversionService.class); + assertThat(pdxSerializer.getMappingContext()).isInstanceOf(GemfireMappingContext.class); + } + @Test @SuppressWarnings("unchecked") public void usesRegisteredInstantiator() { @@ -142,14 +183,14 @@ public class MappingPdxSerializerUnitTests { Object obj = serializer.fromData(Person.class, mockReader); - assertThat(obj, is(instanceOf(Person.class))); + assertThat(obj).isInstanceOf(Person.class); Person jonDoe = (Person) obj; - assertThat(jonDoe.getAddress(), is(equalTo(expectedAddress))); - assertThat(jonDoe.getId(), is(equalTo(1l))); - assertThat(jonDoe.getFirstname(), is(equalTo("Jon"))); - assertThat(jonDoe.getLastname(), is(equalTo("Doe"))); + assertThat(jonDoe.getAddress()).isEqualTo(expectedAddress); + assertThat(jonDoe.getId()).isEqualTo(1l); + assertThat(jonDoe.getFirstname()).isEqualTo("Jon"); + assertThat(jonDoe.getLastname()).isEqualTo("Doe"); verify(mockInstantiator, times(1)).createInstance(any(GemfirePersistentEntity.class), any(ParameterValueProvider.class)); verify(mockReader, times(1)).readField(eq("id")); @@ -193,7 +234,7 @@ public class MappingPdxSerializerUnitTests { serializer.setCustomSerializers(Collections., PdxSerializer>singletonMap( Address.class, mockAddressSerializer)); - assertThat(serializer.toData(jonDoe, mockWriter), is(true)); + assertThat(serializer.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)); @@ -231,5 +272,4 @@ public class MappingPdxSerializerUnitTests { verify(mockWriter, never()).markIdentityField(anyString()); } } - }