From 7ef14587e207ad0d8144333add2656aef3abcfd1 Mon Sep 17 00:00:00 2001 From: John Blum Date: Tue, 29 Mar 2016 18:04:17 -0700 Subject: [PATCH] SGF-476 - Polish Spring (Data GemFire) provided, GemFire ServerLauncherCacheProvider implementation and tests. Closes #87. --- .../SpringServerLauncherCacheProvider.java | 77 ++++++------- .../gemfire/util/DistributedSystemUtils.java | 2 + ...rLauncherCacheProviderIntegrationTest.java | 81 +++++++------ ...SpringServerLauncherCacheProviderTest.java | 106 +++++++++++------- ...erCacheProviderIntegrationTest-context.xml | 11 +- 5 files changed, 149 insertions(+), 128 deletions(-) diff --git a/src/main/java/org/springframework/data/gemfire/support/SpringServerLauncherCacheProvider.java b/src/main/java/org/springframework/data/gemfire/support/SpringServerLauncherCacheProvider.java index 687f6a32..3786ab3f 100644 --- a/src/main/java/org/springframework/data/gemfire/support/SpringServerLauncherCacheProvider.java +++ b/src/main/java/org/springframework/data/gemfire/support/SpringServerLauncherCacheProvider.java @@ -15,66 +15,67 @@ */ package org.springframework.data.gemfire.support; -import java.util.Collections; import java.util.Properties; +import org.springframework.data.gemfire.GemfireUtils; + import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.distributed.ServerLauncher; import com.gemstone.gemfire.distributed.ServerLauncher.Builder; -import com.gemstone.gemfire.distributed.internal.DistributionConfig; -import com.gemstone.gemfire.internal.util.CollectionUtils; import com.gemstone.gemfire.distributed.ServerLauncherCacheProvider; /** - * The SpringServerLauncherCacheProvider class is overrides the default behavior - * of GemFire's ServerLauncher to bootstrap the cache using a Spring - * ApplicationContext instead of a GemFire cache.xml inside a GemFire Server - * JVM-based process. This enables a GemFire Cache Server resources to be - * configured with Spring Data GemFire's XML namespace. + * The SpringServerLauncherCacheProvider class overrides the default behavior of GemFire's {@link ServerLauncher} + * to bootstrap the GemFire cache using a Spring {@link org.springframework.context.ApplicationContext} instead + * of GemFire cache.xml inside a GemFire Server JVM-based process. This enables a GemFire Cache Server's resources + * to be configured with Spring Data GemFire's XML namespace. * - * Unlike {@link SpringContextBootstrappingInitializer}, this allows the configuration - * of the cache to specified in the Spring Context. + * Unlike {@link SpringContextBootstrappingInitializer}, this allows the configuration of the cache to specified + * in the Spring context. * - * To use this cache provider, ensure that the spring data gemfire jars are on - * the classpath of the GemFire server and specify the --spring-xml-location - * option from the command line or call {@link Builder#setSpringXmlLocation(String)} - * when launching the GemFire server. + * To use this cache provider, ensure that the Spring Data GemFire JAR file is on the classpath of the GemFire server + * and specify the --spring-xml-location option from the Gfsh command line or call + * {@link Builder#setSpringXmlLocation(String)} when launching the GemFire server. * * @author Dan Smith - * @see ServerLauncherCacheProvider - * @see SpringContextBootstrappingInitializer + * @author John Blum * @see org.springframework.context.ApplicationContext - * @see org.springframework.context.ApplicationListener - * @see org.springframework.context.ConfigurableApplicationContext - * @see org.springframework.context.annotation. - * AnnotationConfigApplicationContext - * @see org.springframework.context.event.ApplicationContextEvent - * @see org.springframework.context.event.ApplicationEventMulticaster - * @see org.springframework.context.support.ClassPathXmlApplicationContext - * @see com.gemstone.gemfire.cache.Declarable - * @link http://gemfire.docs.pivotal.io/latest/userguide/index.html#basic_config - * /the_cache/setting_cache_initializer.html + * @see org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer + * @see com.gemstone.gemfire.distributed.ServerLauncherCacheProvider + * @since 1.7.0 + * @link http://gemfire.docs.pivotal.io/latest/userguide/index.html#basic_config/the_cache/setting_cache_initializer.html */ public class SpringServerLauncherCacheProvider implements ServerLauncherCacheProvider { + /* (non-Javadoc) */ @Override public Cache createCache(Properties gemfireProperties, ServerLauncher serverLauncher) { - if (!serverLauncher.isSpringXmlLocationSpecified()) { - return null; + Cache cache = null; + + if (serverLauncher.isSpringXmlLocationSpecified()) { + System.setProperty(gemfireName(), serverLauncher.getMemberName()); + newSpringContextBootstrappingInitializer().init(createParameters(serverLauncher)); + cache = SpringContextBootstrappingInitializer.getApplicationContext().getBean(Cache.class); } - System.setProperty(DistributionConfig.GEMFIRE_PREFIX + DistributionConfig.NAME_NAME, - serverLauncher.getMemberName()); - - createSpringContextBootstrappingInitializer().init(CollectionUtils.createProperties( - Collections.singletonMap(SpringContextBootstrappingInitializer.CONTEXT_CONFIG_LOCATIONS_PARAMETER, - serverLauncher.getSpringXmlLocation()))); - - return SpringContextBootstrappingInitializer.getApplicationContext().getBean(Cache.class); + return cache; } - /* Used for testing purposes */ - protected SpringContextBootstrappingInitializer createSpringContextBootstrappingInitializer() { + /* (non-Javadoc) */ + Properties createParameters(ServerLauncher serverLauncher) { + Properties parameters = new Properties(); + parameters.setProperty(SpringContextBootstrappingInitializer.CONTEXT_CONFIG_LOCATIONS_PARAMETER, + serverLauncher.getSpringXmlLocation()); + return parameters; + } + + /* (non-Javadoc) */ + String gemfireName() { + return (GemfireUtils.GEMFIRE_PREFIX + GemfireUtils.NAME_PROPERTY_NAME); + } + + /* (non-Javadoc) */ + SpringContextBootstrappingInitializer newSpringContextBootstrappingInitializer() { return new SpringContextBootstrappingInitializer(); } diff --git a/src/main/java/org/springframework/data/gemfire/util/DistributedSystemUtils.java b/src/main/java/org/springframework/data/gemfire/util/DistributedSystemUtils.java index 72002c5c..b7e77d36 100644 --- a/src/main/java/org/springframework/data/gemfire/util/DistributedSystemUtils.java +++ b/src/main/java/org/springframework/data/gemfire/util/DistributedSystemUtils.java @@ -47,6 +47,8 @@ public abstract class DistributedSystemUtils extends SpringUtils { public static final String DURABLE_CLIENT_ID_PROPERTY_NAME = DistributionConfig.DURABLE_CLIENT_ID_NAME; public static final String DURABLE_CLIENT_TIMEOUT_PROPERTY_NAME = DistributionConfig.DURABLE_CLIENT_TIMEOUT_NAME; + public static final String GEMFIRE_PREFIX = DistributionConfig.GEMFIRE_PREFIX; + public static final String NAME_PROPERTY_NAME = DistributionConfig.NAME_NAME; /* (non-Javadoc) */ public static Properties configureDurableClient(Properties gemfireProperties, diff --git a/src/test/java/org/springframework/data/gemfire/support/SpringServerLauncherCacheProviderIntegrationTest.java b/src/test/java/org/springframework/data/gemfire/support/SpringServerLauncherCacheProviderIntegrationTest.java index 0505ed15..72951b44 100644 --- a/src/test/java/org/springframework/data/gemfire/support/SpringServerLauncherCacheProviderIntegrationTest.java +++ b/src/test/java/org/springframework/data/gemfire/support/SpringServerLauncherCacheProviderIntegrationTest.java @@ -13,81 +13,78 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.data.gemfire.support; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import java.util.Collections; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; import org.junit.After; import org.junit.Test; import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.data.gemfire.support.SpringContextBootstrappingInitializerIntegrationTest.UserDataStoreCacheLoader; +import org.springframework.data.gemfire.GemfireUtils; import com.gemstone.gemfire.cache.Cache; -import com.gemstone.gemfire.cache.CacheClosedException; -import com.gemstone.gemfire.cache.CacheFactory; import com.gemstone.gemfire.distributed.AbstractLauncher.Status; import com.gemstone.gemfire.distributed.ServerLauncher; import com.gemstone.gemfire.distributed.ServerLauncher.ServerState; -import com.gemstone.gemfire.distributed.internal.DistributionConfig; -import com.gemstone.gemfire.internal.util.CollectionUtils; /** * The SpringServerLauncherCacheProviderTest class is a test suite of test cases testing the contract and functionality - * of the SpringServerLauncherCacheProvider class. This test class focuses on testing isolated units of functionality in - * the ServerLauncherCacheProvider class directly, mocking any dependencies as appropriate, in order for the class to - * uphold it's contract. + * of the {@link SpringServerLauncherCacheProvider} class. + * + * This test class focuses on testing isolated units of functionality in the + * {@link com.gemstone.gemfire.distributed.ServerLauncherCacheProvider} class directly, mocking any dependencies + * as appropriate, in order for the class to uphold it's contract. * * @author Dan Smith + * @author John Blum * @see org.junit.Test - * @see org.mockito.Mockito * @see org.springframework.context.ApplicationContext * @see org.springframework.context.ConfigurableApplicationContext * @see org.springframework.data.gemfire.support.SpringServerLauncherCacheProvider + * @see com.gemstone.gemfire.cache.Cache + * @see com.gemstone.gemfire.distributed.ServerLauncher */ public class SpringServerLauncherCacheProviderIntegrationTest { - + @After public void tearDown() { - System.clearProperty(DistributionConfig.GEMFIRE_PREFIX + DistributionConfig.NAME_NAME); + System.clearProperty(gemfireName()); SpringContextBootstrappingInitializer.getApplicationContext().close(); - tearDownCache(); + GemfireUtils.closeClientCache(); } - private void tearDownCache() { - try { - Cache cache = CacheFactory.getAnyInstance(); - - if (cache != null) { - cache.close(); - } - } - catch (CacheClosedException ignore) { - // CacheClosedExceptions happen when the Cache reference returned by GemFireCacheImpl.getInstance() - // inside the CacheFactory.getAnyInstance() is null, or the Cache is already closed with calling - // Cache.close(); - } + String gemfireName() { + return (GemfireUtils.GEMFIRE_PREFIX + GemfireUtils.NAME_PROPERTY_NAME); } @Test - public void createCacheWithSpecifiedConfig() { - String xmlLocation = getClass().getSimpleName() + "-context.xml"; - - ServerLauncher launcher = mock(ServerLauncher.class); - + public void createCacheWithSpring() { + String springXmlLocation = getClass().getSimpleName() + "-context.xml"; ServerLauncher.Builder builder = new ServerLauncher.Builder(); - builder.setSpringXmlLocation(xmlLocation); + + builder.setSpringXmlLocation(springXmlLocation); builder.setMemberName("membername"); - launcher = builder.build(); + + ServerLauncher launcher = builder.build(); ServerState state = launcher.start(); - assertEquals(Status.ONLINE, state.getStatus()); - ConfigurableApplicationContext ctx = SpringContextBootstrappingInitializer.getApplicationContext(); - Cache cache = ctx.getBean(Cache.class); - assertNotNull(cache); - assertEquals(55, cache.getResourceManager().getCriticalHeapPercentage(), 0.1); - assertEquals(Status.STOPPED, launcher.stop().getStatus()); + + assertThat(state.getStatus(), is(equalTo(Status.ONLINE))); + + ConfigurableApplicationContext applicationContext = + SpringContextBootstrappingInitializer.getApplicationContext(); + + Cache cache = applicationContext.getBean(Cache.class); + + assertThat(cache, is(notNullValue())); + assertThat(cache.getResourceManager().getCriticalHeapPercentage(), is(equalTo(55.0f))); + + state = launcher.stop(); + + assertThat(state.getStatus(), is(equalTo(Status.STOPPED))); } } diff --git a/src/test/java/org/springframework/data/gemfire/support/SpringServerLauncherCacheProviderTest.java b/src/test/java/org/springframework/data/gemfire/support/SpringServerLauncherCacheProviderTest.java index 3a53c3b7..8339f62f 100644 --- a/src/test/java/org/springframework/data/gemfire/support/SpringServerLauncherCacheProviderTest.java +++ b/src/test/java/org/springframework/data/gemfire/support/SpringServerLauncherCacheProviderTest.java @@ -15,78 +15,104 @@ */ package org.springframework.data.gemfire.support; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; -import java.util.Collections; +import java.util.Properties; import org.junit.After; import org.junit.Test; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.data.gemfire.GemfireUtils; import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.distributed.ServerLauncher; -import com.gemstone.gemfire.distributed.internal.DistributionConfig; -import com.gemstone.gemfire.internal.util.CollectionUtils; /** * The SpringServerLauncherCacheProviderTest class is a test suite of test cases testing the contract and functionality - * of the SpringServerLauncherCacheProvider class. This test class focuses on testing isolated units of functionality in - * the ServerLauncherCacheProvider class directly, mocking any dependencies as appropriate, in order for the class to - * uphold it's contract. + * of the {@link SpringServerLauncherCacheProvider} class. This test class focuses on testing isolated units + * of functionality in the {@link com.gemstone.gemfire.distributed.ServerLauncherCacheProvider} class directly, mocking + * any dependencies as appropriate, in order for the class to uphold it's contract. * * @author Dan Smith + * @author John Blum * @see org.junit.Test * @see org.mockito.Mockito * @see org.springframework.context.ApplicationContext * @see org.springframework.context.ConfigurableApplicationContext * @see org.springframework.data.gemfire.support.SpringServerLauncherCacheProvider + * @see com.gemstone.gemfire.cache.Cache + * @see com.gemstone.gemfire.distributed.ServerLauncher + * @see com.gemstone.gemfire.distributed.ServerLauncherCacheProvider */ public class SpringServerLauncherCacheProviderTest { - + + String gemfireName() { + return (GemfireUtils.GEMFIRE_PREFIX + GemfireUtils.NAME_PROPERTY_NAME); + } + + Properties singletonProperties(String propertyName, String propertyValue) { + Properties properties = new Properties(); + properties.setProperty(propertyName, propertyValue); + return properties; + } + @After public void tearDown() { - System.clearProperty(DistributionConfig.GEMFIRE_PREFIX + DistributionConfig.NAME_NAME); + System.clearProperty(gemfireName()); SpringContextBootstrappingInitializer.applicationContext = null; } @Test - public void doesNothingWhenSpringXmlLocationNotSpecified() { - SpringServerLauncherCacheProvider provider = new SpringServerLauncherCacheProvider(); - ServerLauncher launcher = mock(ServerLauncher.class); - when(launcher.isSpringXmlLocationSpecified()).thenReturn(false); - assertEquals(null, provider.createCache(null, launcher)); - verify(launcher).isSpringXmlLocationSpecified(); - } - - @Test - public void createCacheWithSpecifiedConfig() { - String xmlLocation = "xml/location"; - - ServerLauncher launcher = mock(ServerLauncher.class); - when(launcher.isSpringXmlLocationSpecified()).thenReturn(true); - when(launcher.getSpringXmlLocation()).thenReturn(xmlLocation); - when(launcher.getMemberName()).thenReturn("membername"); - + public void createsCacheWhenSpringXmlLocationIsSpecified() { + Cache mockCache = mock(Cache.class); + ConfigurableApplicationContext mockApplicationContext = mock(ConfigurableApplicationContext.class); + ServerLauncher mockServerLauncher = mock(ServerLauncher.class); + + SpringContextBootstrappingInitializer.applicationContext = mockApplicationContext; + + when(mockServerLauncher.isSpringXmlLocationSpecified()).thenReturn(true); + when(mockServerLauncher.getSpringXmlLocation()).thenReturn("test-context.xml"); + when(mockServerLauncher.getMemberName()).thenReturn("TEST"); + when(mockApplicationContext.getBean(eq(Cache.class))).thenReturn(mockCache); + final SpringContextBootstrappingInitializer initializer = mock(SpringContextBootstrappingInitializer.class); - ConfigurableApplicationContext context = mock(ConfigurableApplicationContext.class); - SpringContextBootstrappingInitializer.applicationContext = context; - Cache cache = mock(Cache.class); - when(context.getBean(eq(Cache.class))).thenReturn(cache ); - + SpringServerLauncherCacheProvider provider = new SpringServerLauncherCacheProvider() { @Override - public SpringContextBootstrappingInitializer createSpringContextBootstrappingInitializer() { + public SpringContextBootstrappingInitializer newSpringContextBootstrappingInitializer() { return initializer; } }; - - assertEquals(cache, provider.createCache(null, launcher)); - verify(launcher).isSpringXmlLocationSpecified(); - - verify(initializer).init(CollectionUtils.createProperties( - Collections.singletonMap(SpringContextBootstrappingInitializer.CONTEXT_CONFIG_LOCATIONS_PARAMETER, - xmlLocation))); + + Properties expectedParameters = singletonProperties( + SpringContextBootstrappingInitializer.CONTEXT_CONFIG_LOCATIONS_PARAMETER, "test-context.xml"); + + assertThat(provider.createCache(null, mockServerLauncher), is(equalTo(mockCache))); + + verify(mockServerLauncher, times(1)).isSpringXmlLocationSpecified(); + verify(mockServerLauncher, times(1)).getSpringXmlLocation(); + verify(mockServerLauncher, times(1)).getMemberName(); + verify(mockApplicationContext, times(1)).getBean(eq(Cache.class)); + verify(initializer).init(eq(expectedParameters)); + } + + @Test + public void doesNothingWhenSpringXmlLocationNotSpecified() { + ServerLauncher launcher = mock(ServerLauncher.class); + + when(launcher.isSpringXmlLocationSpecified()).thenReturn(false); + + assertThat(new SpringServerLauncherCacheProvider().createCache(null, launcher), is(nullValue())); + + verify(launcher, times(1)).isSpringXmlLocationSpecified(); } } diff --git a/src/test/resources/SpringServerLauncherCacheProviderIntegrationTest-context.xml b/src/test/resources/SpringServerLauncherCacheProviderIntegrationTest-context.xml index c8c078bd..ab33c819 100644 --- a/src/test/resources/SpringServerLauncherCacheProviderIntegrationTest-context.xml +++ b/src/test/resources/SpringServerLauncherCacheProviderIntegrationTest-context.xml @@ -1,5 +1,4 @@ - - SpringContextBootstrappingInitializerTest - false + SpringServerLauncherCacheProviderIntegrationTest 0 - config + warn - - - +