SGF-455 - Simplified registration for shared GemfireMappingContext for repositories.

A <gemfire:repositories /> now registers a single bean definition for a GemfireMappingContext that gets wired to the GemfireRepositoryFactoryBean instances registered within the system unless an explicit mapping context is referenced.

The GemfireRepositoryFactoryBean now checks a GemfireMappingContext being registered and rejects to start without one. The same applies to GemfireRepositoryFactory.

Related tickets: SGF-448, SGF-449, SGF-450.
This commit is contained in:
Oliver Gierke
2015-12-16 14:59:44 +01:00
parent 6ad886ffae
commit 34665d16ec
8 changed files with 137 additions and 332 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012 the original author or authors.
* Copyright 2012-2015 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.
@@ -16,17 +16,20 @@
package org.springframework.data.gemfire.repository.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
import org.springframework.data.gemfire.repository.support.GemfireRepositoryFactoryBean;
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
import org.springframework.data.repository.config.RepositoryConfigurationSource;
import org.springframework.data.repository.config.XmlRepositoryConfigurationSource;
import org.springframework.util.StringUtils;
/**
* {@link RepositoryConfigurationExtension} implementation to add Gemfire
* specific extensions to the repository XML namespace and annotation based
* configuration.
* {@link RepositoryConfigurationExtension} implementation to add Gemfire specific extensions to the repository XML
* namespace and annotation based configuration.
*
* @author Oliver Gierke
* @author John Blum
@@ -36,13 +39,13 @@ public class GemfireRepositoryConfigurationExtension extends RepositoryConfigura
private static final String ANNOTATION_MAPPING_CONTEXT_REF = "mappingContextRef";
private static final String MAPPING_CONTEXT_PROPERTY_NAME = "gemfireMappingContext";
private static final String XML_MAPPING_CONTEXT_REF = "mapping-context-ref";
static final String DEFAULT_MAPPING_CONTEXT_BEAN_NAME = String.format("%1$s.%2$s",
GemfireMappingContext.class.getName(), "DEFAULT");
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.config.RepositoryConfigurationExtension
* #getRepositoryFactoryClassName()
* @see org.springframework.data.repository.config.RepositoryConfigurationExtension#getRepositoryFactoryClassName()
*/
@Override
public String getRepositoryFactoryClassName() {
@@ -51,42 +54,53 @@ public class GemfireRepositoryConfigurationExtension extends RepositoryConfigura
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.config.
* RepositoryConfigurationExtensionSupport#getModulePrefix()
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getModulePrefix()
*/
@Override
protected String getModulePrefix() {
return "gemfire";
}
/**
*
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport
* #postProcess(BeanDefinitionBuilder, AnnotationRepositoryConfigurationSource)
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#registerBeansForRoot(org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.data.repository.config.RepositoryConfigurationSource)
*/
@Override
public void postProcess(BeanDefinitionBuilder builder, AnnotationRepositoryConfigurationSource config) {
String mappingContextRef = config.getAttribute(ANNOTATION_MAPPING_CONTEXT_REF);
public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource configurationSource) {
if (StringUtils.hasText(mappingContextRef)) {
builder.addPropertyReference(MAPPING_CONTEXT_PROPERTY_NAME, mappingContextRef);
super.registerBeansForRoot(registry, configurationSource);
String attribute = configurationSource.getAttribute(ANNOTATION_MAPPING_CONTEXT_REF);
if (!StringUtils.hasText(attribute)) {
registry.registerBeanDefinition(DEFAULT_MAPPING_CONTEXT_BEAN_NAME,
new RootBeanDefinition(GemfireMappingContext.class));
}
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport
* #postProcess(BeanDefinitionBuilder, XmlRepositoryConfigurationSource)
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource)
*/
@Override
public void postProcess(BeanDefinitionBuilder builder, AnnotationRepositoryConfigurationSource config) {
String mappingContextRef = config.getAttribute(ANNOTATION_MAPPING_CONTEXT_REF);
builder.addPropertyReference(MAPPING_CONTEXT_PROPERTY_NAME, getDefaultedMappingContextBeanName(mappingContextRef));
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config.XmlRepositoryConfigurationSource)
*/
@Override
public void postProcess(BeanDefinitionBuilder builder, XmlRepositoryConfigurationSource config) {
String mappingContextRef = config.getElement().getAttribute(XML_MAPPING_CONTEXT_REF);
if (StringUtils.hasText(mappingContextRef)) {
builder.addPropertyReference(MAPPING_CONTEXT_PROPERTY_NAME, mappingContextRef);
}
String mappingContextRef = config.getElement().getAttribute(XML_MAPPING_CONTEXT_REF);
builder.addPropertyReference(MAPPING_CONTEXT_PROPERTY_NAME, getDefaultedMappingContextBeanName(mappingContextRef));
}
private static String getDefaultedMappingContextBeanName(String source) {
return StringUtils.hasText(source) ? source : DEFAULT_MAPPING_CONTEXT_BEAN_NAME;
}
}

View File

@@ -19,7 +19,6 @@ import java.io.Serializable;
import java.lang.reflect.Method;
import org.springframework.data.gemfire.GemfireTemplate;
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
import org.springframework.data.gemfire.mapping.GemfirePersistentEntity;
import org.springframework.data.gemfire.mapping.GemfirePersistentProperty;
import org.springframework.data.gemfire.mapping.Regions;
@@ -48,11 +47,11 @@ import com.gemstone.gemfire.cache.Region;
*
* @author Oliver Gierke
* @author David Turanski
* @author John Blum
*/
public class GemfireRepositoryFactory extends RepositoryFactorySupport {
private final MappingContext<? extends GemfirePersistentEntity<?>, GemfirePersistentProperty> context;
private final Regions regions;
/**
@@ -60,20 +59,21 @@ public class GemfireRepositoryFactory extends RepositoryFactorySupport {
*
* @param regions must not be {@literal null}.
* @param context the {@link MappingContext} used by the constructed Repository for mapping entities
* to the underlying data store.
* to the underlying data store, must not be {@literal null}.
*/
public GemfireRepositoryFactory(Iterable<Region<?, ?>> regions, MappingContext<? extends GemfirePersistentEntity<?>,
GemfirePersistentProperty> context) {
Assert.notNull(regions);
this.context = (context != null ? context : new GemfireMappingContext());
Assert.notNull(regions, "Regions must not be null!");
Assert.notNull(context, "MappingContext must not be null!");
this.context = context;
this.regions = new Regions(regions, this.context);
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport
* #getEntityInformation(java.lang.Class)
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getEntityInformation(java.lang.Class)
*/
@Override
@SuppressWarnings("unchecked")
@@ -84,12 +84,9 @@ public class GemfireRepositoryFactory extends RepositoryFactorySupport {
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport
* #getTargetRepository(org.springframework.data.repository.core.RepositoryMetadata)
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getTargetRepository(org.springframework.data.repository.core.RepositoryInformation)
*/
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Object getTargetRepository(RepositoryInformation repositoryInformation) {
GemfireEntityInformation<?, Serializable> entityInformation = getEntityInformation(
repositoryInformation.getDomainType());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012 the original author or authors.
* Copyright 2012-2015 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.
@@ -24,8 +24,6 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
import org.springframework.data.gemfire.mapping.GemfirePersistentEntity;
import org.springframework.data.gemfire.mapping.GemfirePersistentProperty;
import org.springframework.data.mapping.context.MappingContext;
@@ -53,19 +51,12 @@ import com.gemstone.gemfire.cache.Region;
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport
* @see com.gemstone.gemfire.cache.Region
*/
@SuppressWarnings("unused")
public class GemfireRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
extends RepositoryFactoryBeanSupport<T, S, ID> implements ApplicationContextAware {
protected static final String DEFAULT_MAPPING_CONTEXT_BEAN_NAME =
String.format("%1$s.%2$s", GemfireMappingContext.class.getName(), "DEFAULT");
private ApplicationContext applicationContext;
private Iterable<Region<?, ?>> regions;
private MappingContext<? extends GemfirePersistentEntity<?>, GemfirePersistentProperty> context;
/**
* Sets a reference to the Spring {@link ApplicationContext} in which this object runs.
*
@@ -76,23 +67,11 @@ public class GemfireRepositoryFactoryBean<T extends Repository<S, ID>, S, ID ext
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Collection<Region> regions = applicationContext.getBeansOfType(Region.class).values();
this.regions = (Iterable) Collections.unmodifiableCollection(regions);
this.applicationContext = applicationContext;
}
/**
* Gets a reference to the Spring {@link ApplicationContext} in which this object runs.
*
* @return a reference to the Spring {@link ApplicationContext}.
* @see org.springframework.context.ApplicationContext
* @see #setApplicationContext(ApplicationContext)
*/
protected ApplicationContext getApplicationContext() {
Assert.state(applicationContext != null, "The Spring ApplicationContext was not properly initialized");
return applicationContext;
}
/**
* Configures the {@link MappingContext} used to perform domain object type to store mappings.
*
@@ -101,6 +80,7 @@ public class GemfireRepositoryFactoryBean<T extends Repository<S, ID>, S, ID ext
* @see org.springframework.data.mapping.context.MappingContext
*/
public void setGemfireMappingContext(MappingContext<? extends GemfirePersistentEntity<?>, GemfirePersistentProperty> mappingContext) {
setMappingContext(mappingContext);
this.context = mappingContext;
}
@@ -117,21 +97,10 @@ public class GemfireRepositoryFactoryBean<T extends Repository<S, ID>, S, ID ext
return this.context;
}
/* (non-Javadoce) */
Iterable<Region<?, ?>> getRegions() {
return regions;
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() {
resolveMappingContext();
super.afterPropertiesSet();
}
/**
* Creates an instance of {@link RepositoryFactorySupport} that interfaces with GemFire.
*
@@ -142,36 +111,17 @@ public class GemfireRepositoryFactoryBean<T extends Repository<S, ID>, S, ID ext
protected RepositoryFactorySupport createRepositoryFactory() {
return new GemfireRepositoryFactory(regions, context);
}
/**
* Resolves the appropriate Spring Data {@link MappingContext} to use for handling entity domain object type
* to store mappings.
*
* @see org.springframework.data.mapping.context.MappingContext
* @see #getApplicationContext()
* @see #setMappingContext(MappingContext)
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport#afterPropertiesSet()
*/
protected void resolveMappingContext() {
if (getGemfireMappingContext() == null) {
ApplicationContext applicationContext = getApplicationContext();
@Override
public void afterPropertiesSet() {
GemfireMappingContext gemfireMappingContext;
try {
gemfireMappingContext = applicationContext.getBean(DEFAULT_MAPPING_CONTEXT_BEAN_NAME,
GemfireMappingContext.class);
}
catch (BeansException ignore) {
gemfireMappingContext = new GemfireMappingContext();
if (applicationContext instanceof ConfigurableApplicationContext) {
((ConfigurableApplicationContext) applicationContext).getBeanFactory()
.registerSingleton(DEFAULT_MAPPING_CONTEXT_BEAN_NAME, gemfireMappingContext);
}
}
setGemfireMappingContext(gemfireMappingContext);
}
Assert.state(context != null, "GemfireMappingContext must not be null!");
super.afterPropertiesSet();
}
}

View File

@@ -1,3 +1,18 @@
/*
* Copyright 2012-2015 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.repository.support;
import java.io.Serializable;
@@ -37,7 +52,6 @@ import com.gemstone.gemfire.cache.query.SelectResults;
public class SimpleGemfireRepository<T, ID extends Serializable> implements GemfireRepository<T, ID> {
private final GemfireTemplate template;
private final EntityInformation<T, ID> entityInformation;
/**
@@ -47,6 +61,7 @@ public class SimpleGemfireRepository<T, ID extends Serializable> implements Gemf
* @param entityInformation must not be {@literal null}.
*/
public SimpleGemfireRepository(GemfireTemplate template, EntityInformation<T, ID> entityInformation) {
Assert.notNull(template);
Assert.notNull(entityInformation);