diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfiguration.java index b85b619c..6122f55a 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/AbstractCacheConfiguration.java @@ -26,6 +26,7 @@ import java.lang.annotation.Annotation; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; import com.gemstone.gemfire.cache.TransactionListener; import com.gemstone.gemfire.cache.TransactionWriter; @@ -36,11 +37,18 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportAware; import org.springframework.core.io.Resource; import org.springframework.core.type.AnnotationMetadata; import org.springframework.data.gemfire.CacheFactoryBean; +import org.springframework.data.gemfire.config.support.CustomEditorBeanFactoryPostProcessor; import org.springframework.data.gemfire.util.PropertiesBuilder; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -59,15 +67,19 @@ import org.springframework.util.StringUtils; * @see org.springframework.beans.factory.BeanFactory * @see org.springframework.beans.factory.BeanFactoryAware * @see org.springframework.context.annotation.Bean + * @see org.springframework.context.annotation.Configuration * @see org.springframework.context.annotation.ImportAware * @see org.springframework.core.io.Resource * @see org.springframework.core.type.AnnotationMetadata * @see org.springframework.data.gemfire.CacheFactoryBean * @since 1.9.0 */ +@Configuration @SuppressWarnings("unused") public abstract class AbstractCacheConfiguration implements BeanFactoryAware, BeanClassLoaderAware, ImportAware { + private static final AtomicBoolean CUSTOM_EDITORS_REGISTERED = new AtomicBoolean(false); + protected static final boolean DEFAULT_CLOSE = true; protected static final boolean DEFAULT_COPY_ON_READ = false; protected static final boolean DEFAULT_USE_BEAN_FACTORY_LOCATOR = false; @@ -116,7 +128,7 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be private TransactionWriter transactionWriter; /** - * Determines whether the give {@link Object} has value. The {@link Object} is valuable + * Determines whether the given {@link Object} has value. The {@link Object} is valuable * if it is not {@literal null}. * * @param value {@link Object} to evaluate. @@ -225,11 +237,24 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be */ @Override public void setImportMetadata(AnnotationMetadata importMetadata) { + configureInfrastructure(importMetadata); configureCache(importMetadata); configurePdx(importMetadata); configureOther(importMetadata); } + /** + * Configures Spring container infrastructure components used by Spring Data GemFire + * to enable GemFire to function properly inside a Spring context. + * + * @param importMetadata {@link AnnotationMetadata} containing annotation meta-data + * for the Spring GemFire cache application class. + * @see org.springframework.core.type.AnnotationMetadata + */ + protected void configureInfrastructure(AnnotationMetadata importMetadata) { + registerCustomEditorBeanFactoryPostProcessor(); + } + /** * Configures the GemFire cache settings. * @@ -262,7 +287,7 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be } /** - * Configures GemFire's PDX Serialization feature. + * Configures GemFire's PDX Serialization components. * * @param importMetadata {@link AnnotationMetadata} containing PDX meta-data used to configure * the GemFire cache with PDX de/serialization capabilities. @@ -290,13 +315,44 @@ public abstract class AbstractCacheConfiguration implements BeanFactoryAware, Be /** * Callback method to configure other, specific GemFire cache configuration settings. * - * @param importMetadata {@link AnnotationMetadata} containing the cache meta-data used to configure + * @param importMetadata {@link AnnotationMetadata} containing meta-data used to configure * the GemFire cache. * @see org.springframework.core.type.AnnotationMetadata */ protected void configureOther(AnnotationMetadata importMetadata) { } + /* (non-Javadoc) */ + protected void registerCustomEditorBeanFactoryPostProcessor() { + if (CUSTOM_EDITORS_REGISTERED.compareAndSet(false, true)) { + BeanDefinitionBuilder customEditorBeanFactoryPostProcessor = + BeanDefinitionBuilder.rootBeanDefinition(CustomEditorBeanFactoryPostProcessor.class); + + customEditorBeanFactoryPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + register(customEditorBeanFactoryPostProcessor.getBeanDefinition()); + } + } + + /** + * Registers the given {@link BeanDefinition} with the {@link BeanDefinitionRegistry} using a generated bean name. + * + * @param beanDefinition {@link AbstractBeanDefinition} to register. + * @return the given {@link BeanDefinition}. + * @see org.springframework.beans.factory.support.AbstractBeanDefinition + * @see org.springframework.beans.factory.support.BeanDefinitionRegistry + * @see org.springframework.beans.factory.support.BeanDefinitionReaderUtils + * #registerWithGeneratedName(AbstractBeanDefinition, BeanDefinitionRegistry) + * @see #beanFactory() + */ + protected AbstractBeanDefinition register(AbstractBeanDefinition beanDefinition) { + if (beanFactory() instanceof BeanDefinitionRegistry) { + BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, + ((BeanDefinitionRegistry) beanFactory())); + } + + return beanDefinition; + } + /** * Returns the GemFire cache application {@link java.lang.annotation.Annotation} type pertaining to * this configuration. diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/support/EmbeddedServiceConfigurationSupport.java b/src/main/java/org/springframework/data/gemfire/config/annotation/support/EmbeddedServiceConfigurationSupport.java index a02744f6..1e896a31 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/support/EmbeddedServiceConfigurationSupport.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/support/EmbeddedServiceConfigurationSupport.java @@ -35,42 +35,72 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * The EmbeddedServiceConfigurationSupport class is an abstract base class supporting the configuration + * The {@link EmbeddedServiceConfigurationSupport} class is an abstract base class supporting the configuration * of Pivotal GemFire and Apache Geode embedded services. * * @author John Blum * @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar * @since 1.9.0 */ +@SuppressWarnings("unused") public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanDefinitionRegistrar { + public static final Integer DEFAULT_PORT = 0; public static final String DEFAULT_HOST = "localhost"; @Autowired @SuppressWarnings("all") private AbstractCacheConfiguration cacheConfiguration; - /* (non-Javadoc) */ + /** + * Returns a reference to an instance of the {@link AbstractCacheConfiguration} class used to configure + * a GemFire (Singleton, client or peer) cache instance along with it's associated, embedded services. + * + * @param {@link Class} type extension of {@link AbstractCacheConfiguration}. + * @return a reference to a single {@link AbstractCacheConfiguration} instance. + * @throws IllegalStateException if the {@link AbstractCacheConfiguration} reference was not configured. + * @see org.springframework.data.gemfire.config.annotation.AbstractCacheConfiguration + */ @SuppressWarnings("unchecked") protected T cacheConfiguration() { Assert.state(cacheConfiguration != null, "AbstractCacheConfiguration was not properly initialized"); return (T) this.cacheConfiguration; } - /* (non-Javadoc) */ + /** + * Returns the configured GemFire cache application annotation type + * (e.g. {@link org.springframework.data.gemfire.config.annotation.ClientCacheApplication} + * or {@link org.springframework.data.gemfire.config.annotation.PeerCacheApplication}. + * + * @return an {@link Class annotation} defining the GemFire cache application type. + */ protected abstract Class getAnnotationType(); - /* (non-Javadoc) */ + /** + * Returns the fully-qualified class name of the GemFire cache application annotation type. + * + * @return a fully-qualified class name of the GemFire cache application annotation type. + * @see java.lang.Class#getName() + * @see #getAnnotationType() + */ protected String getAnnotationTypeName() { return getAnnotationType().getName(); } - /* (non-Javadoc) */ + /** + * Returns the simple class name of the GemFire cache application annotation type. + * + * @return the simple class name of the GemFire cache application annotation type. + * @see java.lang.Class#getSimpleName() + * @see #getAnnotationType() + */ protected String getAnnotationTypeSimpleName() { return getAnnotationType().getSimpleName(); } - /* (non-Javadoc) */ + /** + * {@inheritDoc} + */ @Override public final void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { if (isAnnotationPresent(importingClassMetadata)) { @@ -160,14 +190,19 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD return (StringUtils.hasText(hostname) ? hostname : defaultHostname); } + /* (non-Javadoc) */ + protected Integer resolvePort(Integer port) { + return resolvePort(port, DEFAULT_PORT); + } + /* (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. + * Spring {@link BeanPostProcessor} used to process GemFire System properties defined as a Spring bean + * in the Spring application context before initialization. * * @see org.springframework.beans.factory.config.BeanPostProcessor */ @@ -177,11 +212,15 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD private final Properties gemfireProperties; + /* (non-Javadoc) */ protected GemFirePropertiesBeanPostProcessor(Properties gemfireProperties) { Assert.notEmpty(gemfireProperties, "GemFire Properties must not be null or empty"); this.gemfireProperties = gemfireProperties; } + /** + * {@inheritDoc} + */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof Properties && GEMFIRE_PROPERTIES_BEAN_NAME.equals(beanName)) { @@ -192,6 +231,9 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD return bean; } + /** + * {@inheritDoc} + */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean;