SGF-508 - Fix embedded Locator and Manager service configuration using Java-based configuration meta-data with @Enable annotations.

This commit is contained in:
John Blum
2016-08-01 23:03:23 -07:00
parent 186157a97d
commit 0dfbfdf443
18 changed files with 428 additions and 179 deletions

View File

@@ -20,6 +20,7 @@ package org.springframework.data.gemfire.config.annotation;
import static org.springframework.data.gemfire.CacheFactoryBean.DynamicRegionSupport;
import static org.springframework.data.gemfire.CacheFactoryBean.JndiDataSource;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -40,6 +41,7 @@ import org.springframework.context.annotation.ImportAware;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.util.PropertiesBuilder;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -57,6 +59,7 @@ import org.springframework.util.StringUtils;
* @see org.springframework.beans.factory.BeanFactoryAware
* @see org.springframework.context.annotation.Bean
* @see org.springframework.context.annotation.ImportAware
* @see org.springframework.core.type.AnnotationMetadata
* @since 1.9.0
*/
@SuppressWarnings("unused")
@@ -66,6 +69,8 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
protected static final boolean DEFAULT_COPY_ON_READ = false;
protected static final boolean DEFAULT_USE_BEAN_FACTORY_LOCATOR = false;
protected static final int DEFAULT_MCAST_PORT = 0;
protected static final String DEFAULT_LOG_LEVEL = "config";
protected static final String DEFAULT_NAME = "SpringDataGemFireApplication";
@@ -83,6 +88,8 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
private DynamicRegionSupport dynamicRegionSupport;
private Integer mcastPort = 0;
private Float criticalHeapPercentage;
private Float evictionHeapPercentage;
@@ -93,12 +100,15 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
private PdxSerializer pdxSerializer;
private PropertiesBuilder customGemFireProperties = new PropertiesBuilder();
private Resource cacheXml;
private String locators = "";
private String logLevel = DEFAULT_LOG_LEVEL;
private String name;
private String pdxDiskStoreName;
private String startLocator;
private TransactionWriter transactionWriter;
@@ -174,19 +184,18 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
}
/**
* Returns a {@link Properties} object containing GemFire System properties used to configure
* the GemFire cache.
* Returns a {@link Properties} object containing GemFire System properties used to configure the GemFire cache.
*
* The name of the GemFire member/node is set to a pre-dined, descriptive default value depending
* on the type configuraiton applied.
* The name of the GemFire member/node in the cluster is set to a default, pre-defined, descriptive value
* depending on the type of configuration meta-data applied.
*
* Both 'mcast-port' and 'locators' are to set 0 and empty String respectively, which is necessary
* for {@link com.gemstone.gemfire.cache.client.ClientCache cache client}-based applications.
* for {@link com.gemstone.gemfire.cache.client.ClientCache cache client}-based applications. These values
* can be changed for peer cache and cache server applications.
*
* Finally GemFire's "log-level" System property defaults to "config".
* Finally, GemFire's {@literal log-level} System property defaults to {@literal config}.
*
* @return a {@link Properties} object containing GemFire System properties used to configure
* the GemFire cache.
* @return a {@link Properties} object containing GemFire System properties used to configure the GemFire cache.
* @see <a link="http://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html">GemFire Properties</a>
* @see java.util.Properties
* @see #name()
@@ -195,12 +204,16 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
*/
@Bean
protected Properties gemfireProperties() {
Properties gemfireProperties = new Properties();
PropertiesBuilder gemfireProperties = new PropertiesBuilder();
gemfireProperties.setProperty("name", name());
gemfireProperties.setProperty("mcast-port", "0");
gemfireProperties.setProperty("mcast-port", mcastPort());
gemfireProperties.setProperty("log-level", logLevel());
gemfireProperties.setProperty("locators", locators());
return gemfireProperties;
gemfireProperties.setProperty("start-locator", startLocator());
gemfireProperties.add(customGemFireProperties);
return gemfireProperties.build();
}
/*
@@ -213,7 +226,7 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
}
/**
* Gets a reference to the {@link ClassLoader} use by the Spring {@link BeanFactory} to load classes
* Returns a reference to the {@link ClassLoader} use by the Spring {@link BeanFactory} to load classes
* for bean definitions.
*
* @return the {@link ClassLoader} used by the Spring {@link BeanFactory} to load classes for bean definitions.
@@ -233,7 +246,7 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
}
/**
* Gets a reference to the Spring {@link BeanFactory} in the current application context.
* Returns a reference to the Spring {@link BeanFactory} in the current application context.
*
* @return a reference to the Spring {@link BeanFactory}.
* @throws IllegalStateException if the Spring {@link BeanFactory} was not properly initialized.
@@ -252,6 +265,7 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
configureCache(importMetadata);
configureMemcachedServer(importMetadata);
configurePdx(importMetadata);
configureOther(importMetadata);
}
@@ -287,6 +301,32 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
}
}
/**
* Configures the embedded GemFire Memcached Server (Gemcached) service in a GemFire server/data node.
*
* @param importMetadata {@link AnnotationMetadata} containing the Gemcached meta-data used to configure
* the embedded GemFire Memcached Server (Gemcached) service.
* @see org.springframework.core.type.AnnotationMetadata
*/
protected void configureMemcachedServer(AnnotationMetadata importMetadata) {
if (isCacheServerApplication(importMetadata) || isPeerCacheApplication(importMetadata)) {
if (importMetadata.hasAnnotation(EnableMemcachedServer.class.getName())) {
Map<String, Object> enableMemcachedServerAttributes =
importMetadata.getAnnotationAttributes(EnableMemcachedServer.class.getName());
Properties gemfireMemcachedProperties = new Properties();
gemfireMemcachedProperties.setProperty("memcached-port",
String.valueOf(enableMemcachedServerAttributes.get("port")));
gemfireMemcachedProperties.setProperty("memcached-protocol",
String.valueOf(enableMemcachedServerAttributes.get("protocol")));
add(gemfireMemcachedProperties);
}
}
}
/**
* Configures GemFire's PDX Serialization feature.
*
@@ -367,12 +407,10 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
* from the annotations used to configure the Spring application.
* @return a boolean value indicating whether this is a GemFire cache server application.
* @see org.springframework.data.gemfire.config.annotation.CacheServerApplication
* @see #getAnnotationTypeName()
* @see #getAnnotationType()
* @see #isTypedCacheApplication(Class, AnnotationMetadata)
*/
protected boolean isCacheServerApplication(AnnotationMetadata importMetadata) {
return (CacheServerApplication.class.equals(getAnnotationType())
&& importMetadata.hasAnnotation(getAnnotationTypeName()));
return isTypedCacheApplication(CacheServerApplication.class, importMetadata);
}
/**
@@ -384,12 +422,10 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
* from the annotations used to configure the Spring application.
* @return a boolean value indicating whether this is a GemFire cache client application.
* @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication
* @see #getAnnotationTypeName()
* @see #getAnnotationType()
* @see #isTypedCacheApplication(Class, AnnotationMetadata)
*/
protected boolean isClientCacheApplication(AnnotationMetadata importMetadata) {
return (ClientCacheApplication.class.equals(getAnnotationType())
&& importMetadata.hasAnnotation(getAnnotationTypeName()));
return isTypedCacheApplication(ClientCacheApplication.class, importMetadata);
}
/**
@@ -401,21 +437,38 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
* from the annotations used to configure the Spring application.
* @return a boolean value indicating whether this is a GemFire peer cache application.
* @see org.springframework.data.gemfire.config.annotation.PeerCacheApplication
* @see #isTypedCacheApplication(Class, AnnotationMetadata)
*/
protected boolean isPeerCacheApplication(AnnotationMetadata importMetadata) {
return isTypedCacheApplication(PeerCacheApplication.class, importMetadata);
}
/**
* Determines whether this Spring application is annotated with the given GemFire cache type annotation.
*
* @param annotationType {@link Annotation} cache type.
* @param importMetadata {@link AnnotationMetadata} containing application configuration meta-data
* from the annotations used to configure the Spring application.
* @return a boolean value indicating if this Spring application is annotated with the given GemFire
* cache type annotation.
* @see org.springframework.core.type.AnnotationMetadata
* @see java.lang.annotation.Annotation
* @see #getAnnotationTypeName()
* @see #getAnnotationType()
*/
protected boolean isPeerCacheApplication(AnnotationMetadata importMetadata) {
return (PeerCacheApplication.class.equals(getAnnotationType())
&& importMetadata.hasAnnotation(getAnnotationTypeName()));
protected boolean isTypedCacheApplication(Class<? extends Annotation> annotationType,
AnnotationMetadata importMetadata) {
return (annotationType.equals(getAnnotationType()) && importMetadata.hasAnnotation(getAnnotationTypeName()));
}
/**
* 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
* {@link com.gemstone.gemfire.cache.client.ClientCache} or a {@link com.gemstone.gemfire.cache.Cache} application.
*
* @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, client cache or peer cache,
* from the class type-level annotations used to configure the Spring application.
* @return a boolean value indicating whether this is a GemFire cache server, client cache or peer cache
* Spring application.
* @see #isCacheServerApplication(AnnotationMetadata)
* @see #isClientCacheApplication(AnnotationMetadata)
@@ -427,12 +480,13 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
}
/**
* Constructs a new, initialized instance of the {@link CacheFactoryBean} based on the application
* GemFire cache type (i.e. client or peer).
* Constructs a new, initialized instance of the {@link CacheFactoryBean} based on the Spring application's
* GemFire cache type (i.e. client or peer) preference specified via annotation.
*
* @param <T> Class type of the {@link CacheFactoryBean}.
* @return a new instance of the {@link CacheFactoryBean} for the particular application GemFire cache type
* (i.e client or peer).
* @return a new instance of an appropriate {@link CacheFactoryBean} given the Spring application's
* GemFire cache type preference (i.e client or peer) specified with the corresponding annotation
* (e.g. {@link ClientCacheApplication} or {@link PeerCacheApplication});
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
* @see org.springframework.data.gemfire.CacheFactoryBean
* @see #setCommonCacheConfiguration(CacheFactoryBean)
@@ -443,12 +497,13 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
}
/**
* Constructs a new, uninitialized instance of the {@link CacheFactoryBean} based on the application
* GemFire cache type (i.e. client or peer).
* Constructs a new, uninitialized instance of the {@link CacheFactoryBean} based on the Spring application's
* GemFire cache type (i.e. client or peer) preference specified via annotation.
*
* @param <T> Class type of the {@link CacheFactoryBean}.
* @return a new instance of the {@link CacheFactoryBean} for the particular application GemFire cache type
* (i.e client or peer).
* @return a new instance of an appropriate {@link CacheFactoryBean} given the Spring application's
* GemFire cache type preference (i.e client or peer) specified with the corresponding annotation
* (e.g. {@link ClientCacheApplication} or {@link PeerCacheApplication}).
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
* @see org.springframework.data.gemfire.CacheFactoryBean
*/
@@ -458,7 +513,7 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
* Configures common GemFire cache configuration settings.
*
* @param <T> Class type of the {@link CacheFactoryBean}.
* @param gemfireCache specific {@link CacheFactoryBean} instance to configure.
* @param gemfireCache {@link CacheFactoryBean} instance to configure.
* @return the given {@link CacheFactoryBean} after common configuration settings have been applied.
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
* @see org.springframework.data.gemfire.CacheFactoryBean
@@ -558,6 +613,7 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
return nullSafeList(this.jndiDataSources);
}
/* (non-Javadoc) */
void setLocators(String locators) {
this.locators = locators;
}
@@ -575,6 +631,15 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
return nullSafeValue(this.logLevel, DEFAULT_LOG_LEVEL);
}
void setMcastPort(Integer mcastPort) {
this.mcastPort = mcastPort;
}
protected Integer mcastPort() {
return (mcastPort != null ? mcastPort : DEFAULT_MCAST_PORT);
}
/* (non-Javadoc) */
void setName(String name) {
this.name = name;
}
@@ -628,6 +693,15 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
return this.pdxSerializer;
}
/* (non-Javadoc) */
void setStartLocator(String startLocator) {
this.startLocator = startLocator;
}
protected String startLocator() {
return this.startLocator;
}
/* (non-Javadoc) */
void setTransactionListeners(List<TransactionListener> transactionListeners) {
this.transactionListeners = transactionListeners;
@@ -655,6 +729,10 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be
return this.useBeanFactoryLocator;
}
public void add(Properties gemfireProperties) {
customGemFireProperties.add(gemfireProperties);
}
@Override
public String toString() {
return DEFAULT_NAME;

View File

@@ -60,7 +60,7 @@ public @interface CacheServerApplication {
/**
* Configures whether the {@link CacheServer} should start automatically at runtime.
*
* Default is {@code true).
* Default is {@literal true).
*/
boolean autoStartup() default true;
@@ -74,7 +74,7 @@ public @interface CacheServerApplication {
/**
* Indicates whether the "copy on read" is enabled for this cache.
*
* Default is {@code false}.
* Default is {@literal false}.
*/
boolean copyOnRead() default false;
@@ -90,7 +90,7 @@ public @interface CacheServerApplication {
* after it has been forced out of the distributed system by a network partition event or has otherwise been
* shunned by other members. Use this property to enable the auto-reconnect behavior.
*
* Default is {@code false}.
* Default is {@literal false}.
*/
boolean enableAutoReconnect() default false;
@@ -238,7 +238,7 @@ public @interface CacheServerApplication {
* Configures whether this GemFire cache member node would pull it's configuration meta-data
* from the cluster-based Cluster Configuration service.
*
* Default is {@code false}.
* Default is {@literal false}.
*/
boolean useClusterConfiguration() default false;

View File

@@ -55,7 +55,7 @@ public @interface ClientCacheApplication {
/**
* Indicates whether the "copy on read" is enabled for this cache.
*
* Default is {@code false}.
* Default is {@literal false}.
*/
boolean copyOnRead() default false;
@@ -104,7 +104,7 @@ public @interface ClientCacheApplication {
/**
* Configures whether to keep the client queues alive on the server when the client is disconnected
*
* Default is {@code false}.
* Default is {@literal false}.
*/
boolean keepAlive() default false;
@@ -164,7 +164,7 @@ public @interface ClientCacheApplication {
long pingInterval() default PoolFactory.DEFAULT_PING_INTERVAL;
/**
* By default {@code prSingleHopEnabled} is {@code true} in which case the client is aware of the location
* By default {@code prSingleHopEnabled} is {@literal true} in which case the client is aware of the location
* of partitions on servers hosting Regions with {@link com.gemstone.gemfire.cache.DataPolicy#PARTITION}.
*
* @see com.gemstone.gemfire.cache.client.PoolFactory#DEFAULT_PR_SINGLE_HOP_ENABLED
@@ -182,7 +182,7 @@ public @interface ClientCacheApplication {
/**
* Notifies the server that this durable client is ready to receive updates.
*
* Default is {@code false}.
* Default is {@literal false}.
*/
boolean readyForEvents() default false;

View File

@@ -20,19 +20,26 @@ package org.springframework.data.gemfire.config.annotation;
import java.util.Map;
import java.util.Properties;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport;
import org.springframework.data.gemfire.util.PropertiesBuilder;
/**
* The EmbeddedManagerConfiguration class is a Spring {@link org.springframework.context.annotation.ImportBeanDefinitionRegistrar}
* The EmbeddedLocatorConfiguration class is a Spring {@link org.springframework.context.annotation.ImportBeanDefinitionRegistrar}
* that applies additional GemFire configuration by way of GemFire System properties to configure
* an embedded GemFire Locator.
*
* @author John Blum
* @see EmbeddedServiceConfigurationSupport
* @see org.springframework.data.gemfire.config.annotation.EnableEmbeddedLocator
* @see org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport
* @since 1.9.0
*/
public class EmbeddedLocatorConfiguration extends EmbeddedServiceConfigurationSupport {
protected static final int DEFAULT_LOCATOR_PORT = GemfireUtils.DEFAULT_LOCATOR_PORT;
protected static final String START_LOCATOR_GEMFIRE_SYSTEM_PROPERTY_NAME = "start-locator";
@Override
protected Class getAnnotationType() {
return EnableEmbeddedLocator.class;
@@ -40,10 +47,11 @@ public class EmbeddedLocatorConfiguration extends EmbeddedServiceConfigurationSu
@Override
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
Properties gemfireProperties = new Properties();
String host = resolveHost((String) annotationAttributes.get("host"));
int port = resolvePort((Integer) annotationAttributes.get("port"), DEFAULT_LOCATOR_PORT);
setProperty(gemfireProperties, "start-locator", annotationAttributes.get("startLocator"));
return gemfireProperties;
return new PropertiesBuilder()
.setProperty(START_LOCATOR_GEMFIRE_SYSTEM_PROPERTY_NAME, String.format("%s[%d]", host, port))
.build();
}
}

View File

@@ -21,6 +21,7 @@ import java.util.Map;
import java.util.Properties;
import org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport;
import org.springframework.data.gemfire.util.PropertiesBuilder;
/**
* The EmbeddedManagerConfiguration class is a Spring {@link org.springframework.context.annotation.ImportBeanDefinitionRegistrar}
@@ -28,11 +29,14 @@ import org.springframework.data.gemfire.config.annotation.support.EmbeddedServic
* an embedded GemFire Manager.
*
* @author John Blum
* @see EmbeddedServiceConfigurationSupport
* @see org.springframework.data.gemfire.config.annotation.EnableEmbeddedManager
* @see org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport
* @since 1.9.0
*/
public class EmbeddedManagerConfiguration extends EmbeddedServiceConfigurationSupport {
protected static final int DEFAULT_JMX_MANAGER_PORT = 1099;
@Override
protected Class getAnnotationType() {
return EnableEmbeddedManager.class;
@@ -40,30 +44,30 @@ public class EmbeddedManagerConfiguration extends EmbeddedServiceConfigurationSu
@Override
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
Properties gemfireProperties = new Properties();
PropertiesBuilder gemfireProperties = new PropertiesBuilder();
boolean jmxManager = Boolean.valueOf(String.valueOf(annotationAttributes.get("jmxManager")));
if (jmxManager) {
setProperty(gemfireProperties, "jmx-manager", Boolean.TRUE.toString());
setProperty(gemfireProperties, "jmx-manager-access-file", annotationAttributes.get("jmxManagerAccessFile"));
setProperty(gemfireProperties, "jmx-manager-bind-address", annotationAttributes.get("jmxManagerBindAddress"));
setProperty(gemfireProperties, "jmx-manager-hostname-for-clients", annotationAttributes.get("jmxManagerHostnameForClients"));
setProperty(gemfireProperties, "jmx-manager-password-file", annotationAttributes.get("jmxManagerPasswordFile"));
setProperty(gemfireProperties, "jmx-manager-port", annotationAttributes.get("jmxManagerPort"));
setProperty(gemfireProperties, "jmx-manager-start", annotationAttributes.get("jmxManagerStart"));
setProperty(gemfireProperties, "jmx-manager-update-rate", annotationAttributes.get("jmxManagerUpdateRate"));
gemfireProperties.setProperty("jmx-manager", Boolean.TRUE.toString());
gemfireProperties.setProperty("jmx-manager-access-file", annotationAttributes.get("jmxManagerAccessFile"));
gemfireProperties.setProperty("jmx-manager-bind-address", annotationAttributes.get("jmxManagerBindAddress"));
gemfireProperties.setProperty("jmx-manager-hostname-for-clients", annotationAttributes.get("jmxManagerHostnameForClients"));
gemfireProperties.setProperty("jmx-manager-password-file", annotationAttributes.get("jmxManagerPasswordFile"));
gemfireProperties.setProperty("jmx-manager-port", resolvePort((Integer) annotationAttributes.get("jmxManagerPort"), DEFAULT_JMX_MANAGER_PORT));
gemfireProperties.setProperty("jmx-manager-start", annotationAttributes.get("jmxManagerStart"));
gemfireProperties.setProperty("jmx-manager-update-rate", annotationAttributes.get("jmxManagerUpdateRate"));
boolean jmxManagerSslEnabled = Boolean.valueOf(String.valueOf(annotationAttributes.get("jmxManagerSslEnabled")));
if (jmxManagerSslEnabled) {
setProperty(gemfireProperties, "jmx-manager-ssl-enabled", Boolean.TRUE.toString());
setProperty(gemfireProperties, "jmx-manager-ssl-ciphers", annotationAttributes.get("jmxManagerSslCiphers"));
setProperty(gemfireProperties, "jmx-manager-ssl-protocols", annotationAttributes.get("jmxManagerSslProtocols"));
setProperty(gemfireProperties, "jmx-manager-ssl-require-authentication", annotationAttributes.get("jmxManagerSslRequireAuthentication"));
gemfireProperties.setProperty("jmx-manager-ssl-enabled", Boolean.TRUE.toString());
gemfireProperties.setProperty("jmx-manager-ssl-ciphers", annotationAttributes.get("jmxManagerSslCiphers"));
gemfireProperties.setProperty("jmx-manager-ssl-protocols", annotationAttributes.get("jmxManagerSslProtocols"));
gemfireProperties.setProperty("jmx-manager-ssl-require-authentication", annotationAttributes.get("jmxManagerSslRequireAuthentication"));
}
}
return gemfireProperties;
return gemfireProperties.build();
}
}

View File

@@ -27,37 +27,36 @@ import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
/**
* The EnableEmbeddedLocator annotation marks a Spring {@link org.springframework.context.annotation.Configuration}
* class to embed a GemFire Locator service in the GemFire server-side data member node.
* The EnableEmbeddedLocator annotation marks a Spring {@link org.springframework.context.annotation.Configuration @Configuration}
* annotated class to start an embedded GemFire Locator service in this GemFire server/data node.
*
* @author John Blum
* @see org.springframework.context.annotation.Import
* @see org.springframework.data.gemfire.config.annotation.EmbeddedLocatorConfiguration
* @since 1.9.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Documented
@Import(EmbeddedLocatorConfiguration.class)
@SuppressWarnings("unused")
public @interface EnableEmbeddedLocator {
/**
* If set, automatically starts a Locator in the current process when the member connects to the distributed system
* and stops the Locator when the member disconnects.
* To use, specify the Locator with an optional address or host specification and a required port number, in one of
* these formats:
* Configures the host/IP address on which the embedded Locator service will bind to for accepting connections
* from clients sending Locator requests.
*
* start-locator=address[port1]
*
* start-locator=port1
*
* If you only specify the port, the address assigned to the member is used for the Locator.
* If not already there, this locator is automatically added to the list of Locators in this
* set of GemFire Properties.
*
* Defaults to {@literal 10334} (The default GemFire Locator port).
* Default is {@literal localhost}.
*/
String startLocator() default "localhost[10334]";
String host() default EmbeddedLocatorConfiguration.DEFAULT_HOST;
/**
* Configures the port on which the embedded Locator service will bind to listening for client connections
* sending Locator requests.
*
* Default is {@literal 10334}.
*/
int port() default EmbeddedLocatorConfiguration.DEFAULT_LOCATOR_PORT;
}

View File

@@ -27,27 +27,28 @@ import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
/**
* The EnableEmbeddedLocator annotation marks a Spring {@link org.springframework.context.annotation.Configuration}
* class to embed a GemFire Manager service in the GemFire server-side data member node.
* The EnableEmbeddedManager annotation marks a Spring {@link org.springframework.context.annotation.Configuration @Configuration}
* annotated class to embed and start a GemFire Manager service in the GemFire server/data node.
*
* @author John Blum
* @see org.springframework.context.annotation.Import
* @see org.springframework.data.gemfire.config.annotation.EmbeddedManagerConfiguration
* @since 1.9.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Documented
@Import(EmbeddedManagerConfiguration.class)
@SuppressWarnings("unused")
public @interface EnableEmbeddedManager {
/**
* If {@code true} then this member is willing to be a JMX Manager. All the other JMX Manager properties will be
* used when it does become a manager. If this property is {@code false} then all other jmx-manager-* properties
* If {@literal true} then this member is willing to be a JMX Manager. All the other JMX Manager properties will be
* used when it does become a manager. If this property is {@literal false} then all other jmx-manager-* properties
* are ignored.
*
* Defaults to {@code true}.
* Defaults to {@literal true}.
*/
boolean jmxManager() default true;
@@ -64,46 +65,46 @@ public @interface EnableEmbeddedManager {
/**
* By default, the JMX Manager (when configured with a port) will listen on all the local host's addresses.
* You can use this property to configure what IP address or host name the JMX Manager will listen on for
* non-HTTP connections. Ignored if JMX Manager is {@code false} or {@literal jmx-manager-port} is zero.
* non-HTTP connections. Ignored if JMX Manager is {@literal false} or {@literal jmx-manager-port} is zero.
*
* Defaults to {@literal localhost}.
*/
String jmxManagerBindAddress() default "localhost";
String jmxManagerBindAddress() default "";
/**
* Lets you control what hostname will be given to clients that ask the Locator for the location of a JMX Manager.
* By default, the IP address that the JMX Manager reports is used. But for clients on a different network
* this property allows you to configure a different hostname that will be given to clients. Ignored if
* {@literal jmx-manager} is {@code false} or {@literal jmx-manager-port} is zero.
* {@literal jmx-manager} is {@literal false} or {@literal jmx-manager-port} is zero.
*
* Defaults to {@literal localhost}.
*/
String jmxManagerHostnameForClients() default "localhost";
String jmxManagerHostnameForClients() default "";
/**
* By default, the JMX Manager will allow clients without credentials to connect. If this property is set to
* the name of a file then only clients that connect with credentials that match an entry in this file will
* be allowed. Most JVMs require that the file is only readable by the owner. For more information about the
* format of this file see Oracle's documentation of the {@literal com.sun.management.jmxremote.password.file}
* System property. Ignored if {@literal jmx-manager} is {@code false} or {@literal jmx-manager-port} is zero.
* System property. Ignored if {@literal jmx-manager} is {@literal false} or {@literal jmx-manager-port} is zero.
*/
String jmxManagerPasswordFile() default "";
/**
* The port this JMX Manager will listen to for client connections. If this property is set to zero then GemFire
* will not allow remote client connections but you can alternatively use the standard System properties supported
* by the JVM for configuring access from remote JMX clients. Ignored if {@literal jmx-manager} is {@code false}.
* by the JVM for configuring access from remote JMX clients. Ignored if {@literal jmx-manager} is {@literal false}.
*
* Defaults to {@literal 1099}.
*/
int jmxManagerPort() default 1099;
int jmxManagerPort() default EmbeddedManagerConfiguration.DEFAULT_JMX_MANAGER_PORT;
/**
* Enables or disables SSL for connections to the JMX Manager. If {@code true} and {@literal jmx-manager-port}
* Enables or disables SSL for connections to the JMX Manager. If {@literal true} and {@literal jmx-manager-port}
* is not zero, then the JMX Manager will only accept SSL connections. If this property is not set, then GemFire
* uses the value of {@literal cluster-ssl-enabled} to determine whether JMX connections should use SSL.
*
* Defaults to {@code false}.
* Defaults to {@literal false}.
*/
boolean jmxManagerSslEnabled() default false;
@@ -130,17 +131,17 @@ public @interface EnableEmbeddedManager {
* then GemFire uses the value of {@literal cluster-ssl-require-authentication} to determine whether JMX connections
* require authentication.
*
* Defaults to {@code true}.
* Defaults to {@literal true}.
*/
boolean jmxManagerSslRequireAuthentication() default true;
/**
* If true then this member will start a JMX Manager when it creates a cache. Management tools like Gfsh can be
* configured to connect to the JMX Manager. In most cases you should not set this because a JMX Manager will
* automatically be started when needed on a member that sets {@literal jmx-manager} to {@code true}. Ignored if
* {@literal jmx-manager} is {@code false}.
* automatically be started when needed on a member that sets {@literal jmx-manager} to {@literal true}. Ignored if
* {@literal jmx-manager} is {@literal false}.
*
* Defaults to {@code false}.
* Defaults to {@literal false}.
*/
boolean jmxManagerStart() default false;
@@ -149,7 +150,7 @@ public @interface EnableEmbeddedManager {
* should be greater than or equal to the {@literal statistic-sample-rate}. Setting this value too high will
* cause stale values to be seen by Gfsh and GemFire Pulse.
*
* Defaults to {@code 2000}.
* Defaults to {@literal 2000}.
*/
int jmxManagerUpdateRate() default 2000;

View File

@@ -27,20 +27,21 @@ import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
/**
* The EnableMemcachedServer annotation marks a Spring {@link org.springframework.context.annotation.Configuration}
* class to embed the Gemcached service in the GemFire server-side data member node.
* The EnableMemcachedServer annotation marks a Spring {@link org.springframework.context.annotation.Configuration @Configuration}
* annotated class to start an embedded Memcached Server (Gemcached) service in the GemFire server/data node.
*
* The Gemcached service implements the Memcached server protocol enabling Memcached clients to connect and speak
* to Pivotal GemFire or Apache Geode.
* The Gemcached service implements the Memcached Server protocol enabling Memcached clients to connect to
* and communicate with Pivotal GemFire or Apache Geode servers.
*
* @author John Blum
* @see org.springframework.context.annotation.Import
* @see org.springframework.data.gemfire.config.annotation.MemcachedServerConfiguration
* @since 1.9.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Documented
@Import(MemcachedServerConfiguration.class)
@SuppressWarnings("unused")
public @interface EnableMemcachedServer {
@@ -51,7 +52,7 @@ public @interface EnableMemcachedServer {
*
* Default to {@literal 11211}.
*/
int port() default 11211;
int port() default MemcachedServerConfiguration.DEFAULT_MEMCACHED_SERVER_PORT;
/**
* Sets the protocol used by an embedded Gemcached server. Valid values are BINARY and ASCII.

View File

@@ -25,26 +25,49 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The EnablePdx class...
* The EnablePdx annotation marks a Spring {@link org.springframework.context.annotation.Configuration @Configuration}
* annotated class to enable the GemFire PDX features and functionality in a GemFire server/data node
* or GemFire cache client application.
*
* @author John Blum
* @since 1.0.0
* @since 1.9.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Documented
@SuppressWarnings("unused")
public @interface EnablePdx {
String diskStoreName();
/**
* Configures the disk store that is used for PDX meta data.
*/
String diskStoreName() default "";
/**
* Configures whether pdx ignores fields that were unread during deserialization.
*
* Default is {@literal false}.
*/
boolean ignoreUnreadFields() default false;
/**
* Configures whether the type metadata for PDX objects is persisted to disk.
*
* Default is {@literal false}.
*/
boolean persistent() default false;
/**
* Configures the object preference to {@link com.gemstone.gemfire.pdx.PdxInstance} type or {@link Object}.
*
* Default is {@literal false}.
*/
boolean readSerialized() default false;
/**
* Configures the PDX serializer to be used by the cache to serialize object data.
*/
String serializerBeanName() default "";
}

View File

@@ -21,6 +21,7 @@ import java.util.Map;
import java.util.Properties;
import org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport;
import org.springframework.data.gemfire.util.PropertiesBuilder;
/**
* The MemcachedServerConfiguration class is a Spring {@link org.springframework.context.annotation.ImportBeanDefinitionRegistrar}
@@ -28,11 +29,14 @@ import org.springframework.data.gemfire.config.annotation.support.EmbeddedServic
* an embedded Memcached server.
*
* @author John Blum
* @see org.springframework.data.gemfire.config.annotation.EnableMemcachedServer
* @see org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport
* @since 1.9.0
*/
public class MemcachedServerConfiguration extends EmbeddedServiceConfigurationSupport {
protected static final int DEFAULT_MEMCACHED_SERVER_PORT = 11211;
@Override
protected Class getAnnotationType() {
return EnableMemcachedServer.class;
@@ -40,11 +44,9 @@ public class MemcachedServerConfiguration extends EmbeddedServiceConfigurationSu
@Override
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
Properties gemfireProperties = new Properties();
setProperty(gemfireProperties, "memcached-port", annotationAttributes.get("port"));
setProperty(gemfireProperties, "memcached-protocol", annotationAttributes.get("protocol"));
return gemfireProperties;
return new PropertiesBuilder()
.setProperty("memcached-port", resolvePort((Integer) annotationAttributes.get("port"), DEFAULT_MEMCACHED_SERVER_PORT))
.setProperty("memcached-protocol", annotationAttributes.get("protocol"))
.build();
}
}

View File

@@ -52,7 +52,7 @@ public @interface PeerCacheApplication {
/**
* Indicates whether the "copy on read" is enabled for this cache.
*
* Default is {@code false}.
* Default is {@literal false}.
*/
boolean copyOnRead() default false;
@@ -68,7 +68,7 @@ public @interface PeerCacheApplication {
* after it has been forced out of the distributed system by a network partition event or has otherwise been
* shunned by other members. Use this property to enable the auto-reconnect behavior.
*
* Default is {@code false}.
* Default is {@literal false}.
*/
boolean enableAutoReconnect() default false;
@@ -133,7 +133,7 @@ public @interface PeerCacheApplication {
* Configures whether this GemFire cache member node would pull it's configuration meta-data
* from the cluster-based Cluster Configuration service.
*
* Default is {@code false}.
* Default is {@literal false}.
*/
boolean useClusterConfiguration() default false;

View File

@@ -21,6 +21,7 @@ import java.util.Map;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -28,6 +29,7 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.gemfire.config.annotation.AbstractCacheConfiguration;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -42,42 +44,21 @@ import org.springframework.util.StringUtils;
*/
public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanDefinitionRegistrar {
/* (non-Javadoc) */
protected static Properties setProperty(Properties properties, String key, Object value) {
if (value != null) {
setProperty(properties, key, value.toString());
}
public static final String DEFAULT_HOST = "localhost";
return properties;
@Autowired
@SuppressWarnings("all")
private AbstractCacheConfiguration cacheConfiguration;
/* (non-Javadoc) */
@SuppressWarnings("unchecked")
protected <T extends AbstractCacheConfiguration> T cacheConfiguration() {
Assert.state(cacheConfiguration != null, "AbstractCacheConfiguration was not properly initialized");
return (T) this.cacheConfiguration;
}
/* (non-Javadoc) */
protected static Properties setProperty(Properties properties, String key, String value) {
Assert.notNull(properties, "Properties must not be null");
Assert.hasText(key, "Key must not be null or empty");
if (StringUtils.hasText(value)) {
properties.setProperty(key, value);
}
return properties;
}
/* (non-Javadoc) */
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (importingClassMetadata.hasAnnotation(getAnnotationTypeName())) {
Map<String, Object> annotationAttributes =
importingClassMetadata.getAnnotationAttributes(getAnnotationTypeName());
Properties customizedGemFireProperties = toGemFireProperties(annotationAttributes);
if (!CollectionUtils.isEmpty(customizedGemFireProperties)) {
registerGemFirePropertiesBeanPostProcessor(registry, customizedGemFireProperties);
}
}
}
protected abstract Class getAnnotationType();
/* (non-Javadoc) */
protected String getAnnotationTypeName() {
@@ -90,33 +71,70 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
}
/* (non-Javadoc) */
protected abstract Class getAnnotationType();
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (importingClassMetadata.hasAnnotation(getAnnotationTypeName())) {
Map<String, Object> annotationAttributes =
importingClassMetadata.getAnnotationAttributes(getAnnotationTypeName());
/* (non-Javadoc) */
protected String getBeanName() {
return String.format("%1$s.%2$s", getClass().getName(), getAnnotationTypeSimpleName());
}
Properties customGemFireProperties = toGemFireProperties(annotationAttributes);
/* (non-Javadoc) */
protected BeanDefinitionHolder newBeanDefinitionHolder(BeanDefinitionBuilder builder) {
return new BeanDefinitionHolder(builder.getBeanDefinition(), getBeanName());
if (hasProperties(customGemFireProperties)) {
try {
cacheConfiguration().add(customGemFireProperties);
}
catch (Exception ignore) {
registerGemFirePropertiesBeanPostProcessor(registry, customGemFireProperties);
}
}
}
}
/* (non-Javadoc) */
protected abstract Properties toGemFireProperties(Map<String, Object> annotationAttributes);
/* (non-Javadoc) */
protected boolean hasProperties(Properties properties) {
return !CollectionUtils.isEmpty(properties);
}
/* (non-Javadoc) */
protected void registerGemFirePropertiesBeanPostProcessor(BeanDefinitionRegistry registry,
Properties customizedGemFireProperties) {
Properties customGemFireProperties) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
GemFirePropertiesBeanPostProcessor.class);
builder.addConstructorArgValue(customizedGemFireProperties);
builder.addConstructorArgValue(customGemFireProperties);
BeanDefinitionReaderUtils.registerBeanDefinition(newBeanDefinitionHolder(builder), registry);
}
/* (non-Javadoc) */
protected BeanDefinitionHolder newBeanDefinitionHolder(BeanDefinitionBuilder builder) {
return new BeanDefinitionHolder(builder.getBeanDefinition(), generateBeanName());
}
/* (non-Javadoc) */
protected String generateBeanName() {
return String.format("%1$s.%2$s", getClass().getName(), getAnnotationTypeSimpleName());
}
/* (non-Javadoc) */
protected String resolveHost(String hostname) {
return resolveHost(hostname, DEFAULT_HOST);
}
/* (non-Javadoc) */
protected String resolveHost(String hostname, String defaultHostname) {
return (StringUtils.hasText(hostname) ? hostname : defaultHostname);
}
/* (non-Javadoc) */
protected Integer resolvePort(Integer port, Integer defaultPort) {
return (port != null ? port : defaultPort);
}
/**
* Spring {@link BeanPostProcessor} used to post process before initialization in GemFire System properties
* Spring bean defined in the application context.
@@ -125,7 +143,7 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
*/
protected static class GemFirePropertiesBeanPostProcessor implements BeanPostProcessor {
static final String GEMFIRE_PROPERTIES_BEAN_NAME = "gemfireProperties";
protected static final String GEMFIRE_PROPERTIES_BEAN_NAME = "gemfireProperties";
private final Properties gemfireProperties;

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2002-2013 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.
@@ -117,5 +117,4 @@ public abstract class ArrayUtils {
return newArray;
}
}

View File

@@ -125,5 +125,4 @@ public abstract class CacheUtils extends DistributedSystemUtils {
return null;
}
}
}

View File

@@ -77,7 +77,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
* @return the given Collection if not null, otherwise return an empty Collection (List).
* @see java.util.Collections#emptyList()
*/
public static <T> Collection<T> nullSafeCollection(final Collection<T> collection) {
public static <T> Collection<T> nullSafeCollection(Collection<T> collection) {
return (collection != null ? collection : Collections.<T>emptyList());
}
@@ -100,15 +100,14 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
}
@Override public T next() {
throw new NoSuchElementException("no elements in this Iterator");
throw new NoSuchElementException("No more elements");
}
@Override public void remove() {
throw new UnsupportedOperationException("operation not supported");
throw new UnsupportedOperationException("Operation not supported");
}
};
}
});
}
}

View File

@@ -18,9 +18,6 @@ package org.springframework.data.gemfire.util;
import java.util.Properties;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.server.CacheServer;
import com.gemstone.gemfire.distributed.DistributedSystem;
@@ -30,6 +27,9 @@ import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.distributed.internal.InternalLocator;
import com.gemstone.gemfire.internal.DistributionLocator;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* DistributedSystemUtils is an abstract utility class for working with the GemFire DistributedSystem.
*

View File

@@ -0,0 +1,119 @@
/*
* Copyright 2012 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.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* The PropertiesBuilder class is a Builder for {@link java.util.Properties}.
*
* @author John Blum
* @see java.util.Properties
* @since 1.0.0
*/
@SuppressWarnings("unused")
public class PropertiesBuilder {
private final Properties properties;
public PropertiesBuilder() {
this.properties = new Properties();
}
public PropertiesBuilder(Properties defaults) {
this.properties = new Properties(defaults);
}
public PropertiesBuilder(PropertiesBuilder builder) {
this(builder != null ? builder.build() : null);
}
public PropertiesBuilder add(Properties properties) {
if (!CollectionUtils.isEmpty(properties)) {
this.properties.putAll(properties);
}
return this;
}
public PropertiesBuilder add(PropertiesBuilder builder) {
if (builder != null) {
add(builder.build());
}
return this;
}
public PropertiesBuilder from(InputStream in) {
try {
this.properties.load(in);
return this;
}
catch (IOException e) {
throw new IllegalArgumentException("Failed to read properties from InputStream", e);
}
}
public PropertiesBuilder from(Reader reader) {
try {
this.properties.load(reader);
return this;
}
catch (IOException e) {
throw new IllegalArgumentException("Failed to read properties from Reader", e);
}
}
public PropertiesBuilder fromXml(InputStream xml) {
try {
this.properties.loadFromXML(xml);
return this;
}
catch (IOException e) {
throw new IllegalArgumentException("Failed to read properties from XML InputStream", e);
}
}
public PropertiesBuilder setProperty(String name, Object value) {
if (value != null) {
setProperty(name, value.toString());
}
return this;
}
public PropertiesBuilder setProperty(String name, String value) {
Assert.hasText(name, String.format("Name [%s] must not be null or empty", name));
if (StringUtils.hasText(value)) {
this.properties.setProperty(name, value);
}
return this;
}
public Properties build() {
return this.properties;
}
}

View File

@@ -148,18 +148,17 @@ public class CollectionUtilsTest {
iterator.next();
}
catch (NoSuchElementException ignore) {
assertThat(ignore.getMessage(), is(equalTo("no elements in this Iterator")));
assertThat(ignore.getMessage(), is(equalTo("No more elements")));
assertThat(ignore.getCause(), is(nullValue()));
try {
iterator.remove();
}
catch (UnsupportedOperationException expected) {
assertThat(expected.getMessage(), is(equalTo("operation not supported")));
assertThat(expected.getMessage(), is(equalTo("Operation not supported")));
assertThat(expected.getCause(), is(nullValue()));
throw expected;
}
}
}
}