SGF-439 - Add 'durable-client-id' and 'durable-client-timeout' attributes to the <gfe:client-cache> namespace element for convenience.

(cherry picked from commit e74768f006d59210ddd3d4fe5294a60ca505674f)

Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
John Blum
2015-10-15 16:39:12 -07:00
parent 23374a583f
commit 1bb8e7b7a9
14 changed files with 303 additions and 99 deletions

View File

@@ -24,6 +24,7 @@ import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.gemfire.CacheFactoryBean; import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.GemfireUtils; import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.config.GemfireConstants; import org.springframework.data.gemfire.config.GemfireConstants;
import org.springframework.data.gemfire.util.DistributedSystemUtils;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@@ -56,11 +57,13 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
public class ClientCacheFactoryBean extends CacheFactoryBean implements ApplicationListener<ContextRefreshedEvent> { public class ClientCacheFactoryBean extends CacheFactoryBean implements ApplicationListener<ContextRefreshedEvent> {
protected Boolean keepAlive = false; protected Boolean keepAlive = false;
protected Boolean readyForEvents = false; protected Boolean readyForEvents = false;
protected Integer durableClientTimeout;
private Pool pool; private Pool pool;
protected String durableClientId;
protected String poolName; protected String poolName;
@Override @Override
@@ -101,6 +104,8 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
gemfireProperties = distributedSystemProperties; gemfireProperties = distributedSystemProperties;
} }
DistributedSystemUtils.configureDurableClient(gemfireProperties, durableClientId, durableClientTimeout);
return gemfireProperties; return gemfireProperties;
} }
@@ -179,7 +184,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @see com.gemstone.gemfire.cache.client.ClientCacheFactory * @see com.gemstone.gemfire.cache.client.ClientCacheFactory
*/ */
private ClientCacheFactory initializePool(ClientCacheFactory clientCacheFactory) { private ClientCacheFactory initializePool(ClientCacheFactory clientCacheFactory) {
resolvePool(this.pool); resolvePool(pool);
return clientCacheFactory; return clientCacheFactory;
} }
@@ -246,21 +251,62 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
((ClientCache) cache).close(isKeepAlive()); ((ClientCache) cache).close(isKeepAlive());
} }
@Override
public Class<? extends GemFireCache> getObjectType() {
return (cache != null ? cache.getClass() : ClientCache.class);
}
@Override @Override
public final void setEnableAutoReconnect(final Boolean enableAutoReconnect) { public final void setEnableAutoReconnect(final Boolean enableAutoReconnect) {
throw new UnsupportedOperationException("Auto-reconnect is not supported on ClientCache."); throw new UnsupportedOperationException("Auto-reconnect is not supported on ClientCache.");
} }
/**
* Set the GemFire System property 'durable-client-id' to indicate to the server that this client is durable.
*
* @param durableClientId a String value indicating the durable client id.
*/
public void setDurableClientId(final String durableClientId) {
this.durableClientId = durableClientId;
}
/**
* Gets the value of the GemFire System property 'durable-client-id' indicating to the server whether
* this client is durable.
*
* @return a String value indicating the durable client id.
*/
public String getDurableClientId() {
return durableClientId;
}
/**
* Set the GemFire System property 'durable-client-timeout' indicating to the server how long to track events
* for the durable client when disconnected.
*
* @param durableClientTimeout an Integer value indicating the timeout in seconds for the server to keep
* the durable client's queue around.
*/
public void setDurableClientTimeout(final Integer durableClientTimeout) {
this.durableClientTimeout = durableClientTimeout;
}
/**
* Get the value of the GemFire System property 'durable-client-timeout' indicating to the server how long
* to track events for the durable client when disconnected.
*
* @return an Integer value indicating the timeout in seconds for the server to keep
* the durable client's queue around.
*/
public Integer getDurableClientTimeout() {
return durableClientTimeout;
}
@Override @Override
public final Boolean getEnableAutoReconnect() { public final Boolean getEnableAutoReconnect() {
return Boolean.FALSE; return Boolean.FALSE;
} }
@Override
public Class<? extends GemFireCache> getObjectType() {
return (cache != null ? cache.getClass() : ClientCache.class);
}
/** /**
* Sets whether the server(s) should keep the durable client's queue alive for the duration of the timeout * Sets whether the server(s) should keep the durable client's queue alive for the duration of the timeout
* when the client voluntarily disconnects. * when the client voluntarily disconnects.
@@ -271,6 +317,16 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
this.keepAlive = keepAlive; this.keepAlive = keepAlive;
} }
/**
* Gets the user specified value for whether the server(s) should keep the durable client's queue alive
* for the duration of the timeout when the client voluntarily disconnects.
*
* @return a boolean value indicating whether the server should keep the durable client's queues alive.
*/
public Boolean getKeepAlive() {
return keepAlive;
}
/** /**
* Determines whether the server(s) should keep the durable client's queue alive for the duration of the timeout * Determines whether the server(s) should keep the durable client's queue alive for the duration of the timeout
* when the client voluntarily disconnects. * when the client voluntarily disconnects.
@@ -278,7 +334,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @return a boolean value indicating whether the server should keep the durable client's queues alive. * @return a boolean value indicating whether the server should keep the durable client's queues alive.
*/ */
public boolean isKeepAlive() { public boolean isKeepAlive() {
return Boolean.TRUE.equals(this.keepAlive); return Boolean.TRUE.equals(getKeepAlive());
} }
/** /**
@@ -311,10 +367,11 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
} }
/** /**
* Set the readyForEvents flag. * Sets the readyForEvents property to indicate whether the cache client should notify the server
* that it is ready to receive updates.
* *
* @param readyForEvents sets a boolean flag to notify the server that this durable client is ready * @param readyForEvents sets a boolean flag to notify the server that this durable client
* to receive updates. * is ready to receive updates.
* @see #getReadyForEvents() * @see #getReadyForEvents()
*/ */
public void setReadyForEvents(Boolean readyForEvents){ public void setReadyForEvents(Boolean readyForEvents){
@@ -322,7 +379,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
} }
/** /**
* Gets the value for the readyForEvents property. * Gets the user-specified value for the readyForEvents property.
* *
* @return a boolean value indicating the state of the 'readyForEvents' property. * @return a boolean value indicating the state of the 'readyForEvents' property.
*/ */

View File

@@ -108,18 +108,6 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
private String serverGroup = PoolFactory.DEFAULT_SERVER_GROUP; private String serverGroup = PoolFactory.DEFAULT_SERVER_GROUP;
public Pool getObject() throws Exception {
return pool;
}
public Class<?> getObjectType() {
return (pool != null ? pool.getClass() : Pool.class);
}
public boolean isSingleton() {
return true;
}
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
if (!StringUtils.hasText(name)) { if (!StringUtils.hasText(name)) {
Assert.hasText(beanName, "Pool 'name' is required"); Assert.hasText(beanName, "Pool 'name' is required");
@@ -184,14 +172,20 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
} }
} }
/* (non-Javadoc) */ /**
* Creates an instance of the GemFire PoolFactory interface to construct, configure and initialize a GemFire Pool.
*
* @return a PoolFactory implementation to create Pool.
* @see com.gemstone.gemfire.cache.client.PoolFactory
* @see com.gemstone.gemfire.cache.client.PoolManager#createFactory()
*/
protected PoolFactory createPoolFactory() { protected PoolFactory createPoolFactory() {
return PoolManager.createFactory(); return PoolManager.createFactory();
} }
/* (non-Javadoc) */ /* (non-Javadoc) */
void resolveDistributedSystem() { void resolveDistributedSystem() {
if (DistributedSystemUtils.getDistributedSystem() == null) { if (DistributedSystemUtils.isNotConnected(DistributedSystemUtils.getDistributedSystem())) {
doDistributedSystemConnect(resolveGemfireProperties()); doDistributedSystemConnect(resolveGemfireProperties());
} }
} }
@@ -200,7 +194,7 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
Properties resolveGemfireProperties() { Properties resolveGemfireProperties() {
try { try {
ClientCacheFactoryBean clientCacheFactoryBean = beanFactory.getBean(ClientCacheFactoryBean.class); ClientCacheFactoryBean clientCacheFactoryBean = beanFactory.getBean(ClientCacheFactoryBean.class);
return clientCacheFactoryBean.getProperties(); return clientCacheFactoryBean.resolveProperties();
} }
catch (Exception ignore) { catch (Exception ignore) {
return null; return null;
@@ -208,8 +202,8 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
} }
/** /**
* A workaround to create a Pool if no ClientCache has been created yet. Initialize a client-like * A workaround to create a Pool if no ClientCache has been created yet. Initialize a cache client-like
* Distributed System before initializing the Pool. * DistributedSystem before initializing the Pool.
* *
* @param properties GemFire System Properties. * @param properties GemFire System Properties.
* @see java.util.Properties * @see java.util.Properties
@@ -235,6 +229,18 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
} }
} }
public Pool getObject() throws Exception {
return pool;
}
public Class<?> getObjectType() {
return (pool != null ? pool.getClass() : Pool.class);
}
public boolean isSingleton() {
return true;
}
public void setBeanFactory(BeanFactory beanFactory) { public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory; this.beanFactory = beanFactory;
} }

View File

@@ -38,8 +38,10 @@ class ClientCacheParser extends CacheParser {
@Override @Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder); super.doParse(element, parserContext, builder);
ParsingUtils.setPropertyValue(element, builder, "keep-alive", "keepAlive"); ParsingUtils.setPropertyValue(element, builder, "durable-client-id");
ParsingUtils.setPropertyValue(element, builder, "pool-name", "poolName"); ParsingUtils.setPropertyValue(element, builder, "durable-client-timeout");
ParsingUtils.setPropertyValue(element, builder, "keep-alive");
ParsingUtils.setPropertyValue(element, builder, "pool-name");
ParsingUtils.setPropertyValue(element, builder, "ready-for-events"); ParsingUtils.setPropertyValue(element, builder, "ready-for-events");
} }

View File

@@ -16,10 +16,16 @@
package org.springframework.data.gemfire.util; package org.springframework.data.gemfire.util;
import java.util.Properties;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.server.CacheServer; import com.gemstone.gemfire.cache.server.CacheServer;
import com.gemstone.gemfire.distributed.DistributedSystem; import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.distributed.internal.DistributionConfig;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem; import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.internal.DistributionLocator; import com.gemstone.gemfire.internal.DistributionLocator;
import com.gemstone.gemfire.management.internal.cli.util.spring.StringUtils;
/** /**
* DistributedSystemUtils is an abstract utility class for working with the GemFire DistributedSystem. * DistributedSystemUtils is an abstract utility class for working with the GemFire DistributedSystem.
@@ -28,11 +34,29 @@ import com.gemstone.gemfire.internal.DistributionLocator;
* @see com.gemstone.gemfire.distributed.DistributedSystem * @see com.gemstone.gemfire.distributed.DistributedSystem
* @since 1.7.0 * @since 1.7.0
*/ */
@SuppressWarnings("unused")
public abstract class DistributedSystemUtils { public abstract class DistributedSystemUtils {
public static final int DEFAULT_CACHE_SERVER_PORT = CacheServer.DEFAULT_PORT; public static final int DEFAULT_CACHE_SERVER_PORT = CacheServer.DEFAULT_PORT;
public static final int DEFAULT_LOCATOR_PORT = DistributionLocator.DEFAULT_LOCATOR_PORT; public static final int DEFAULT_LOCATOR_PORT = DistributionLocator.DEFAULT_LOCATOR_PORT;
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 Properties configureDurableClient(Properties gemfireProperties, String durableClientId, Integer durableClientTimeout) {
if (StringUtils.hasText(durableClientId)) {
Assert.notNull(gemfireProperties, "gemfireProperties must not be null");
gemfireProperties.setProperty(DURABLE_CLIENT_ID_PROPERTY_NAME, durableClientId);
if (durableClientTimeout != null) {
gemfireProperties.setProperty(DURABLE_CLIENT_TIMEOUT_PROPERTY_NAME, durableClientTimeout.toString());
}
}
return gemfireProperties;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T extends DistributedSystem> T getDistributedSystem() { public static <T extends DistributedSystem> T getDistributedSystem() {
return (T) InternalDistributedSystem.getAnyInstance(); return (T) InternalDistributedSystem.getAnyInstance();
@@ -42,4 +66,8 @@ public abstract class DistributedSystemUtils {
return (distributedSystem != null && distributedSystem.isConnected()); return (distributedSystem != null && distributedSystem.isConnected());
} }
public static boolean isNotConnected(DistributedSystem distributedSystem) {
return !isConnected(distributedSystem);
}
} }

View File

@@ -349,6 +349,27 @@ Defines a GemFire Client Cache instance used for creating or retrieving 'regions
<xsd:complexType> <xsd:complexType>
<xsd:complexContent> <xsd:complexContent>
<xsd:extension base="cacheBaseType"> <xsd:extension base="cacheBaseType">
<xsd:attribute name="durable-client-id" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Used only for clients in a client/server installation. If set, this indicates that the client is durable
and identifies the client. The ID is used by servers to reestablish any messaging that was interrupted
by client downtime. The default value is unset. In addition, this attribute value overrides any setting
specified in gemfire.properties passed using 'properties-ref'.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="durable-client-timeout" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Used only for clients in a client/server installation. Number of seconds this client can remain disconnected
from its server and have the server continue to accumulate durable events for it. The default value is 300 seconds.
In addition, this attribute value overrides any setting specified in gemfire.properties passed using 'properties-ref'.
Also, durable-client-timeout is only used if durable-client-id is set.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="keep-alive" type="xsd:string" use="optional" default="false"> <xsd:attribute name="keep-alive" type="xsd:string" use="optional" default="false">
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[

View File

@@ -16,11 +16,13 @@
package org.springframework.data.gemfire.client; package org.springframework.data.gemfire.client;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame; import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
@@ -42,6 +44,7 @@ import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.gemfire.TestUtils; import org.springframework.data.gemfire.TestUtils;
import org.springframework.data.gemfire.config.GemfireConstants; import org.springframework.data.gemfire.config.GemfireConstants;
import org.springframework.data.gemfire.util.DistributedSystemUtils;
import com.gemstone.gemfire.cache.CacheClosedException; import com.gemstone.gemfire.cache.CacheClosedException;
import com.gemstone.gemfire.cache.GemFireCache; import com.gemstone.gemfire.cache.GemFireCache;
@@ -60,13 +63,21 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
* @see org.mockito.Mockito * @see org.mockito.Mockito
* @see org.junit.Test * @see org.junit.Test
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean * @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
* @see com.gemstone.gemfire.cache.GemFireCache
* @see com.gemstone.gemfire.cache.client.ClientCache * @see com.gemstone.gemfire.cache.client.ClientCache
* @see com.gemstone.gemfire.cache.client.ClientCacheFactory
* @see com.gemstone.gemfire.cache.client.Pool
* @see com.gemstone.gemfire.distributed.DistributedSystem
* @since 1.7.0 * @since 1.7.0
*/ */
public class ClientCacheFactoryBeanTest { public class ClientCacheFactoryBeanTest {
protected Properties createProperties(String key, String value) { protected Properties createProperties(String key, String value) {
Properties properties = new Properties(); return addProperty(null, key, value);
}
protected Properties addProperty(Properties properties, String key, String value) {
properties = (properties != null ? properties : new Properties());
properties.setProperty(key, value); properties.setProperty(key, value);
return properties; return properties;
} }
@@ -101,12 +112,52 @@ public class ClientCacheFactoryBeanTest {
Properties resolvedProperties = clientCacheFactoryBean.resolveProperties(); Properties resolvedProperties = clientCacheFactoryBean.resolveProperties();
assertNotNull(resolvedProperties); assertThat(resolvedProperties, is(notNullValue()));
assertNotSame(gemfireProperties, resolvedProperties); assertThat(resolvedProperties, is(not(sameInstance(gemfireProperties))));
assertNotSame(distributedSystemProperties, resolvedProperties); assertThat(resolvedProperties, is(not(sameInstance(distributedSystemProperties))));
assertEquals(2, resolvedProperties.size()); assertThat(resolvedProperties.size(), is(equalTo(2)));
assertEquals("test", resolvedProperties.getProperty("gf")); assertThat(resolvedProperties.containsKey(DistributedSystemUtils.DURABLE_CLIENT_ID_PROPERTY_NAME), is(false));
assertEquals("mock", resolvedProperties.getProperty("ds")); assertThat(resolvedProperties.containsKey(DistributedSystemUtils.DURABLE_CLIENT_TIMEOUT_PROPERTY_NAME), is(false));
assertThat(resolvedProperties.getProperty("gf"), is(equalTo("test")));
assertThat(resolvedProperties.getProperty("ds"), is(equalTo("mock")));
verify(mockDistributedSystem, times(1)).isConnected();
verify(mockDistributedSystem, times(1)).getProperties();
}
@Test
public void resolvePropertiesWhenDistributedSystemIsConnectedAndClientIsDurable() {
Properties gemfireProperties = DistributedSystemUtils.configureDurableClient(createProperties("gf", "test"),
"123", 600);
Properties distributedSystemProperties = DistributedSystemUtils.configureDurableClient(
createProperties("ds", "mock"), "987", 300);
final DistributedSystem mockDistributedSystem = mock(DistributedSystem.class, "MockDistributedSystem");
when(mockDistributedSystem.isConnected()).thenReturn(true);
when(mockDistributedSystem.getProperties()).thenReturn(distributedSystemProperties);
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean() {
@SuppressWarnings("unchecked") @Override <T extends DistributedSystem> T getDistributedSystem() {
return (T) mockDistributedSystem;
}
};
clientCacheFactoryBean.setProperties(gemfireProperties);
Properties resolvedProperties = clientCacheFactoryBean.resolveProperties();
assertThat(resolvedProperties, is(notNullValue()));
assertThat(resolvedProperties, is(not(sameInstance(gemfireProperties))));
assertThat(resolvedProperties, is(not(sameInstance(distributedSystemProperties))));
assertThat(resolvedProperties.size(), is(equalTo(4)));
assertThat(resolvedProperties.getProperty("gf"), is(equalTo("test")));
assertThat(resolvedProperties.getProperty("ds"), is(equalTo("mock")));
assertThat(resolvedProperties.getProperty(DistributedSystemUtils.DURABLE_CLIENT_ID_PROPERTY_NAME),
is(equalTo("123")));
assertThat(resolvedProperties.getProperty(DistributedSystemUtils.DURABLE_CLIENT_TIMEOUT_PROPERTY_NAME),
is(equalTo("600")));
verify(mockDistributedSystem, times(1)).isConnected(); verify(mockDistributedSystem, times(1)).isConnected();
verify(mockDistributedSystem, times(1)).getProperties(); verify(mockDistributedSystem, times(1)).getProperties();
@@ -252,10 +303,13 @@ public class ClientCacheFactoryBeanTest {
@Test @Test
public void createCache() { public void createCache() {
BeanFactory mockBeanFactory = mock(BeanFactory.class, "MockSpringBeanFactory"); BeanFactory mockBeanFactory = mock(BeanFactory.class, "MockBeanFactory");
ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class, "MockGemFireClientCacheFactory");
ClientCache mockClientCache = mock(ClientCache.class, "MockGemFireClientCache"); ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class, "MockClientCacheFactory");
Pool mockPool = mock(Pool.class, "MockGemFirePool");
ClientCache mockClientCache = mock(ClientCache.class, "MockClientCache");
Pool mockPool = mock(Pool.class, "MockPool");
when(mockClientCacheFactory.create()).thenReturn(mockClientCache); when(mockClientCacheFactory.create()).thenReturn(mockClientCache);
when(mockBeanFactory.isTypeMatch(eq("testCreateCache.Pool"), eq(Pool.class))).thenReturn(true); when(mockBeanFactory.isTypeMatch(eq("testCreateCache.Pool"), eq(Pool.class))).thenReturn(true);

View File

@@ -46,7 +46,8 @@ import com.gemstone.gemfire.cache.LoaderHelper;
import com.gemstone.gemfire.cache.Region; import com.gemstone.gemfire.cache.Region;
/** /**
* The ClientCacheSecurityTest class... * The ClientCacheSecurityTest class is a test suite with test cases testing SSL configuration between a GemFire client
* and server using the cluster-ssl-* GemFire System properties.
* *
* @author John Blum * @author John Blum
* @see org.junit.Test * @see org.junit.Test

View File

@@ -47,6 +47,7 @@ import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.process.ProcessWrapper; import org.springframework.data.gemfire.process.ProcessWrapper;
import org.springframework.data.gemfire.test.AbstractGemFireClientServerIntegrationTest; import org.springframework.data.gemfire.test.AbstractGemFireClientServerIntegrationTest;
import org.springframework.data.gemfire.test.support.ThreadUtils; import org.springframework.data.gemfire.test.support.ThreadUtils;
import org.springframework.data.gemfire.util.DistributedSystemUtils;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -95,6 +96,8 @@ public class DurableClientCacheIntegrationTest extends AbstractGemFireClientServ
private static final String CLIENT_CACHE_INTERESTS_RESULT_POLICY_SYSTEM_PROPERTY = private static final String CLIENT_CACHE_INTERESTS_RESULT_POLICY_SYSTEM_PROPERTY =
"gemfire.cache.client.interests.result-policy"; "gemfire.cache.client.interests.result-policy";
private static final String DURABLE_CLIENT_TIMEOUT_SYSTEM_PROPERTY = "gemfire.cache.client.durable-client-timeout";
private static final String SERVER_HOST = "localhost"; private static final String SERVER_HOST = "localhost";
@Autowired @Autowired
@@ -119,6 +122,14 @@ public class DurableClientCacheIntegrationTest extends AbstractGemFireClientServ
@Before @Before
public void setup() { public void setup() {
assertThat(clientCache.getDistributedSystem().getProperties().getProperty(
DistributedSystemUtils.DURABLE_CLIENT_ID_PROPERTY_NAME),
is(equalTo(DurableClientCacheIntegrationTest.class.getSimpleName())));
assertThat(clientCache.getDistributedSystem().getProperties().getProperty(
DistributedSystemUtils.DURABLE_CLIENT_TIMEOUT_PROPERTY_NAME),
is(equalTo(RUN_COUNT.get() == 1 ? "300" : "600")));
assertRegion(example, "Example", DataPolicy.NORMAL); assertRegion(example, "Example", DataPolicy.NORMAL);
} }
@@ -127,8 +138,7 @@ public class DurableClientCacheIntegrationTest extends AbstractGemFireClientServ
if (RUN_COUNT.get() == 1) { if (RUN_COUNT.get() == 1) {
closeApplicationContext(); closeApplicationContext();
runClientCacheProducer(); runClientCacheProducer();
System.setProperty(CLIENT_CACHE_INTERESTS_RESULT_POLICY_SYSTEM_PROPERTY, setSystemProperties();
InterestResultPolicyType.NONE.name());
RUN_COUNT.incrementAndGet(); RUN_COUNT.incrementAndGet();
} }
@@ -162,6 +172,11 @@ public class DurableClientCacheIntegrationTest extends AbstractGemFireClientServ
} }
} }
protected void setSystemProperties() {
System.setProperty(CLIENT_CACHE_INTERESTS_RESULT_POLICY_SYSTEM_PROPERTY, InterestResultPolicyType.NONE.name());
System.setProperty(DURABLE_CLIENT_TIMEOUT_SYSTEM_PROPERTY, "600");
}
protected void waitForRegionEntryEvents() { protected void waitForRegionEntryEvents() {
ThreadUtils.timedWait(TimeUnit.SECONDS.toMillis(5), TimeUnit.MILLISECONDS.toMillis(500), ThreadUtils.timedWait(TimeUnit.SECONDS.toMillis(5), TimeUnit.MILLISECONDS.toMillis(500),
new ThreadUtils.WaitCondition() { new ThreadUtils.WaitCondition() {

View File

@@ -16,6 +16,8 @@
package org.springframework.data.gemfire.client; package org.springframework.data.gemfire.client;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame; import static org.junit.Assert.assertSame;
@@ -30,11 +32,12 @@ import static org.mockito.Mockito.when;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Properties; import java.util.Properties;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.data.gemfire.TestUtils; import org.springframework.data.gemfire.TestUtils;
@@ -57,26 +60,24 @@ import com.gemstone.gemfire.cache.client.PoolFactory;
*/ */
public class PoolFactoryBeanTest { public class PoolFactoryBeanTest {
@Test @Rule
public void testGetObjectType() { public ExpectedException expectedException = ExpectedException.none();
assertEquals(Pool.class, new PoolFactoryBean().getObjectType());
}
@Test @Test
public void testIsSingleton() { @SuppressWarnings("deprecation")
assertTrue(new PoolFactoryBean().isSingleton()); public void afterPropertiesSet() throws Exception {
} BeanFactory mockBeanFactory = mock(BeanFactory.class, "MockBeanFactory");
@Test final PoolFactory mockPoolFactory = mock(PoolFactory.class, "MockPoolFactory");
public void testAfterPropertiesSet() throws Exception {
BeanFactory mockBeanFactory = mock(BeanFactory.class, "MockSpringBeanFactory"); Pool mockPool = mock(Pool.class, "MockPool");
final PoolFactory mockPoolFactory = mock(PoolFactory.class, "MockGemFirePoolFactory");
Pool mockPool = mock(Pool.class, "GemFirePool");
final Properties gemfireProperties = new Properties(); final Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", "testAfterPropertiesSet"); gemfireProperties.setProperty("name", "testAfterPropertiesSet");
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean(); ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
clientCacheFactoryBean.setProperties(gemfireProperties); clientCacheFactoryBean.setProperties(gemfireProperties);
when(mockBeanFactory.getBean(eq(ClientCacheFactoryBean.class))).thenReturn(clientCacheFactoryBean); when(mockBeanFactory.getBean(eq(ClientCacheFactoryBean.class))).thenReturn(clientCacheFactoryBean);
@@ -139,39 +140,40 @@ public class PoolFactoryBeanTest {
verify(mockPoolFactory, times(1)).create(eq("GemFirePool")); verify(mockPoolFactory, times(1)).create(eq("GemFirePool"));
} }
@Test(expected = IllegalArgumentException.class) @Test
public void testAfterPropertiesSetWithNoLocatorsServersSpecified() throws Exception { public void afterPropertiesSetWithUnspecifiedName() throws Exception {
try { PoolFactoryBean poolFactoryBean = new PoolFactoryBean();
PoolFactoryBean poolFactoryBean = new PoolFactoryBean();
poolFactoryBean.setName("GemFirePool"); poolFactoryBean.setBeanName(null);
poolFactoryBean.setLocators((Collection) null); poolFactoryBean.setName(null);
poolFactoryBean.setServers(Collections.<InetSocketAddress>emptyList());
poolFactoryBean.afterPropertiesSet();
}
catch (IllegalArgumentException expected) {
assertEquals("at least one GemFire Locator or Server is required", expected.getMessage());
throw expected;
}
}
@Test(expected = IllegalArgumentException.class) expectedException.expect(IllegalArgumentException.class);
public void testAfterPropertiesSetWithUnspecifiedName() throws Exception { expectedException.expectCause(is(nullValue(Throwable.class)));
try { expectedException.expectMessage("Pool 'name' is required");
PoolFactoryBean poolFactoryBean = new PoolFactoryBean();
poolFactoryBean.setBeanName(null); poolFactoryBean.afterPropertiesSet();
poolFactoryBean.setName(null);
poolFactoryBean.afterPropertiesSet();
}
catch (IllegalArgumentException expected) {
assertEquals("Pool 'name' is required", expected.getMessage());
throw expected;
}
} }
@Test @Test
public void testResolveGemfireProperties() { @SuppressWarnings("deprecation")
BeanFactory mockBeanFactory = mock(BeanFactory.class, "MockSpringBeanFactory"); public void afterPropertiesSetWithNoLocatorsOrServersSpecified() throws Exception {
PoolFactoryBean poolFactoryBean = new PoolFactoryBean();
poolFactoryBean.setBeanName("GemFirePool");
poolFactoryBean.setLocators(null);
poolFactoryBean.setServers(Collections.<InetSocketAddress>emptyList());
expectedException.expect(IllegalArgumentException.class);
expectedException.expectCause(is(nullValue(Throwable.class)));
expectedException.expectMessage("at least one GemFire Locator or Server is required");
poolFactoryBean.afterPropertiesSet();
}
@Test
public void resolveGemfireProperties() {
BeanFactory mockBeanFactory = mock(BeanFactory.class, "MockBeanFactory");
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean(); ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
when(mockBeanFactory.getBean(eq(ClientCacheFactoryBean.class))).thenReturn(clientCacheFactoryBean); when(mockBeanFactory.getBean(eq(ClientCacheFactoryBean.class))).thenReturn(clientCacheFactoryBean);
@@ -191,8 +193,8 @@ public class PoolFactoryBeanTest {
} }
@Test @Test
public void testResolveUnresolvableGemfireProperties() { public void resolveUnresolvableGemfireProperties() {
BeanFactory mockBeanFactory = mock(BeanFactory.class, "MockSpringBeanFactory"); BeanFactory mockBeanFactory = mock(BeanFactory.class, "MockBeanFactory");
when(mockBeanFactory.getBean(eq(ClientCacheFactoryBean.class))).thenThrow( when(mockBeanFactory.getBean(eq(ClientCacheFactoryBean.class))).thenThrow(
new NoSuchBeanDefinitionException("TEST")); new NoSuchBeanDefinitionException("TEST"));
@@ -205,8 +207,8 @@ public class PoolFactoryBeanTest {
} }
@Test @Test
public void testDestroy() throws Exception { public void destroy() throws Exception {
Pool mockPool = mock(Pool.class, "MockGemFirePool"); Pool mockPool = mock(Pool.class, "MockPool");
when(mockPool.isDestroyed()).thenReturn(false); when(mockPool.isDestroyed()).thenReturn(false);
@@ -222,7 +224,7 @@ public class PoolFactoryBeanTest {
} }
@Test @Test
public void testDestroyNonSpringBasedPool() throws Exception { public void destroyWithNonSpringBasedPool() throws Exception {
Pool mockPool = mock(Pool.class, "MockGemFirePool"); Pool mockPool = mock(Pool.class, "MockGemFirePool");
PoolFactoryBean poolFactoryBean = new PoolFactoryBean(); PoolFactoryBean poolFactoryBean = new PoolFactoryBean();
@@ -237,11 +239,21 @@ public class PoolFactoryBeanTest {
} }
@Test @Test
public void testDestroyWithUninitializedPool() throws Exception { public void destroyWithUninitializedPool() throws Exception {
PoolFactoryBean poolFactoryBean = new PoolFactoryBean(); PoolFactoryBean poolFactoryBean = new PoolFactoryBean();
poolFactoryBean.setPool(null); poolFactoryBean.setPool(null);
poolFactoryBean.destroy(); poolFactoryBean.destroy();
} }
@Test
public void getObjectType() {
assertEquals(Pool.class, new PoolFactoryBean().getObjectType());
}
@Test
public void isSingleton() {
assertTrue(new PoolFactoryBean().isSingleton());
}
} }

View File

@@ -67,6 +67,8 @@ public class ClientCacheNamespaceTest {
assertThat(clientCacheFactoryBean.isLazyInitialize(), is(true)); assertThat(clientCacheFactoryBean.isLazyInitialize(), is(true));
assertThat(clientCacheFactoryBean.getCopyOnRead(), is(true)); assertThat(clientCacheFactoryBean.getCopyOnRead(), is(true));
assertThat(clientCacheFactoryBean.getCriticalHeapPercentage(), is(equalTo(0.85f))); assertThat(clientCacheFactoryBean.getCriticalHeapPercentage(), is(equalTo(0.85f)));
assertThat(clientCacheFactoryBean.getDurableClientId(), is(equalTo("TestDurableClientId")));
assertThat(clientCacheFactoryBean.getDurableClientTimeout(), is(equalTo(600)));
assertThat(clientCacheFactoryBean.getEvictionHeapPercentage(), is(equalTo(0.65f))); assertThat(clientCacheFactoryBean.getEvictionHeapPercentage(), is(equalTo(0.65f)));
assertThat((PdxSerializer) clientCacheFactoryBean.getPdxSerializer(), is(equalTo(reflectionPdxSerializer))); assertThat((PdxSerializer) clientCacheFactoryBean.getPdxSerializer(), is(equalTo(reflectionPdxSerializer)));
assertThat(clientCacheFactoryBean.getPdxIgnoreUnreadFields(), is(true)); assertThat(clientCacheFactoryBean.getPdxIgnoreUnreadFields(), is(true));

View File

@@ -40,6 +40,8 @@ public class MockClientCacheFactoryBean extends ClientCacheFactoryBean {
this.cacheXml = clientCacheFactoryBean.getCacheXml(); this.cacheXml = clientCacheFactoryBean.getCacheXml();
this.copyOnRead = clientCacheFactoryBean.getCopyOnRead(); this.copyOnRead = clientCacheFactoryBean.getCopyOnRead();
this.criticalHeapPercentage = clientCacheFactoryBean.getCriticalHeapPercentage(); this.criticalHeapPercentage = clientCacheFactoryBean.getCriticalHeapPercentage();
this.durableClientId = clientCacheFactoryBean.getDurableClientId();
this.durableClientTimeout = clientCacheFactoryBean.getDurableClientTimeout();
this.dynamicRegionSupport = clientCacheFactoryBean.getDynamicRegionSupport(); this.dynamicRegionSupport = clientCacheFactoryBean.getDynamicRegionSupport();
this.evictionHeapPercentage = clientCacheFactoryBean.getEvictionHeapPercentage(); this.evictionHeapPercentage = clientCacheFactoryBean.getEvictionHeapPercentage();
this.gatewayConflictResolver = clientCacheFactoryBean.getGatewayConflictResolver(); this.gatewayConflictResolver = clientCacheFactoryBean.getGatewayConflictResolver();

View File

@@ -11,7 +11,7 @@
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
"> ">
<util:properties id="client.properties"> <util:properties id="clientProperties">
<prop key="client.server.host">localhost</prop> <prop key="client.server.host">localhost</prop>
<prop key="client.server.port">31517</prop> <prop key="client.server.port">31517</prop>
<prop key="gemfire.security.ssl.enabled">true</prop> <prop key="gemfire.security.ssl.enabled">true</prop>
@@ -23,7 +23,7 @@
<prop key="gemfire.security.ssl.keystore.type">jks</prop> <prop key="gemfire.security.ssl.keystore.type">jks</prop>
</util:properties> </util:properties>
<context:property-placeholder properties-ref="client.properties" system-properties-mode="FALLBACK"/> <context:property-placeholder properties-ref="clientProperties" system-properties-mode="FALLBACK"/>
<util:properties id="gemfireProperties"> <util:properties id="gemfireProperties">
<prop key="cluster-ssl-enabled">${gemfire.security.ssl.enabled}</prop> <prop key="cluster-ssl-enabled">${gemfire.security.ssl.enabled}</prop>

View File

@@ -12,6 +12,7 @@
"> ">
<util:properties id="clientProperties"> <util:properties id="clientProperties">
<prop key="gemfire.cache.client.durable-client-id">DurableClientCacheIntegrationTest</prop>
<prop key="gemfire.cache.client.server.host">localhost</prop> <prop key="gemfire.cache.client.server.host">localhost</prop>
<prop key="gemfire.cache.client.server.port">24842</prop> <prop key="gemfire.cache.client.server.port">24842</prop>
</util:properties> </util:properties>
@@ -21,7 +22,7 @@
<bean class="org.springframework.data.gemfire.client.DurableClientCacheIntegrationTest$ClientCacheBeanPostProcessor"/> <bean class="org.springframework.data.gemfire.client.DurableClientCacheIntegrationTest$ClientCacheBeanPostProcessor"/>
<util:properties id="gemfireProperties"> <util:properties id="gemfireProperties">
<prop key="durable-client-id">DurableClientCacheIntegrationTestClientId</prop> <prop key="durable-client-id">TestDurableClientId</prop>
<prop key="durable-client-timeout">300</prop> <prop key="durable-client-timeout">300</prop>
<prop key="log-level">warning</prop> <prop key="log-level">warning</prop>
<prop key="mcast-port">0</prop> <prop key="mcast-port">0</prop>
@@ -32,8 +33,10 @@
<gfe:server host="${gemfire.cache.client.server.host}" port="${gemfire.cache.client.server.port}"/> <gfe:server host="${gemfire.cache.client.server.host}" port="${gemfire.cache.client.server.port}"/>
</gfe:pool> </gfe:pool>
<gfe:client-cache properties-ref="gemfireProperties" keep-alive="true" pool-name="gemfireServerPool" ready-for-events="true" <gfe:client-cache properties-ref="gemfireProperties" pool-name="gemfireServerPool" use-bean-factory-locator="false"
use-bean-factory-locator="false"/> durable-client-id="${gemfire.cache.client.durable-client-id}"
durable-client-timeout="${gemfire.cache.client.durable-client-timeout:}"
keep-alive="true" ready-for-events="true"/>
<gfe:client-region id="Example" pool-name="gemfireServerPool" shortcut="CACHING_PROXY"> <gfe:client-region id="Example" pool-name="gemfireServerPool" shortcut="CACHING_PROXY">
<gfe:cache-listener> <gfe:cache-listener>

View File

@@ -22,6 +22,7 @@
<bean id="reflectionPdxSerializer" class="com.gemstone.gemfire.pdx.ReflectionBasedAutoSerializer"/> <bean id="reflectionPdxSerializer" class="com.gemstone.gemfire.pdx.ReflectionBasedAutoSerializer"/>
<gfe:client-cache cache-xml-location="/path/to/bogus/cache.xml" properties-ref="gemfireProperties" lazy-init="true" <gfe:client-cache cache-xml-location="/path/to/bogus/cache.xml" properties-ref="gemfireProperties" lazy-init="true"
durable-client-id="TestDurableClientId" durable-client-timeout="600"
copy-on-read="true" critical-heap-percentage="0.85" eviction-heap-percentage="0.65" copy-on-read="true" critical-heap-percentage="0.85" eviction-heap-percentage="0.65"
pdx-serializer-ref="reflectionPdxSerializer" pdx-ignore-unread-fields="true" pdx-persistent="false" pdx-serializer-ref="reflectionPdxSerializer" pdx-ignore-unread-fields="true" pdx-persistent="false"
pdx-read-serialized="true" keep-alive="true" pool-name="serverPool" ready-for-events="false"/> pdx-read-serialized="true" keep-alive="true" pool-name="serverPool" ready-for-events="false"/>