SGF-469 - Add support for CDI.

This commit is contained in:
John Blum
2016-02-17 09:08:16 -08:00
parent 53a1fc217a
commit 34da7ec910
18 changed files with 1231 additions and 15 deletions

View File

@@ -51,6 +51,17 @@ if (project.hasProperty('platformVersion')) {
}
}
sourceSets {
main {
output.resourcesDir = 'build/classes/main'
output.classesDir = 'build/classes/main'
}
test {
output.resourcesDir = 'build/classes/test'
output.classesDir = 'build/classes/test'
}
}
[compileJava, compileTestJava]*.options*.compilerArgs = ["-Xlint:-serial"]
tasks.withType(Test).all {
@@ -80,6 +91,7 @@ dependencies {
optional("com.google.code.findbugs:annotations:2.0.2")
runtime("antlr:antlr:$antlrVersion")
optional "javax.enterprise:cdi-api:$cdiVersion"
compile "org.aspectj:aspectjweaver:$aspectjVersion"
compile "com.fasterxml.jackson.core:jackson-core:$jacksonVersion"
compile "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion"
@@ -94,11 +106,15 @@ dependencies {
testCompile "org.hamcrest:hamcrest-library:$hamcrestVersion"
testCompile "org.mockito:mockito-core:$mockitoVersion"
testCompile "edu.umd.cs.mtc:multithreadedtc:$multiThreadedtcVersion"
testCompile "org.apache.openwebbeans.test:cditest-owb:$openwebbeansVersion"
testCompile "javax.annotation:jsr250-api:1.0", optional
testRuntime "javax.el:el-api:$cdiVersion"
testRuntime "javax.servlet:servlet-api:$servletApiVersion"
testRuntime "log4j:log4j:$log4jVersion"
testRuntime "org.apache.derby:derbyLocale_zh_TW:10.9.1.0"
testRuntime "org.slf4j:slf4j-log4j12:$slf4jVersion"
testRuntime "org.springframework.shell:spring-shell:1.0.0.RELEASE"
sharedResources "org.springframework.data.build:spring-data-build-resources:$springDataBuildVersion@zip"
}

View File

@@ -1,5 +1,6 @@
antlrVersion=2.7.7
aspectjVersion=1.8.5
cdiVersion=1.0
gemfireVersion=8.2.0
hamcrestVersion=1.3
jacksonVersion=2.6.0
@@ -7,6 +8,8 @@ junitVersion=4.12
log4jVersion=1.2.17
mockitoVersion=1.10.19
multiThreadedtcVersion=1.01
openwebbeansVersion=1.2.8
servletApiVersion=2.5
slf4jVersion=1.7.12
spring.range="[4.0.0, 5.0.0)"
springVersion=4.1.9.RELEASE

29
pom.xml
View File

@@ -20,6 +20,7 @@
<antlr.version>2.7.7</antlr.version>
<gemfire.version>8.2.0</gemfire.version>
<multithreadedtc.version>1.01</multithreadedtc.version>
<servlet-api.version>2.5</servlet-api.version>
<springdata.commons>1.12.0.BUILD-SNAPSHOT</springdata.commons>
</properties>
@@ -41,6 +42,14 @@
<version>${springdata.commons}</version>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>${cdi}</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.gemstone.gemfire</groupId>
<artifactId>gemfire</artifactId>
@@ -90,6 +99,26 @@
<!-- Test -->
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>${cdi}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans.test</groupId>
<artifactId>cditest-owb</artifactId>
<version>${webbeans}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyLocale_zh_TW</artifactId>

View File

@@ -35,14 +35,12 @@ import org.w3c.dom.Element;
@SuppressWarnings("unused")
class GemfireNamespaceHandler extends NamespaceHandlerSupport {
protected static final List<String> GEMFIRE7_ELEMENTS = Arrays.asList("async-event-queue", "gateway-sender",
static final List<String> GEMFIRE7_ELEMENTS = Arrays.asList("async-event-queue", "gateway-sender",
"gateway-receiver");
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
boolean v7ElementsPresent = GEMFIRE7_ELEMENTS.contains(element.getLocalName());
if (v7ElementsPresent) {
if (GEMFIRE7_ELEMENTS.contains(element.getLocalName())) {
ParsingUtils.throwExceptionIfNotGemfireV7(element.getLocalName(), null, parserContext);
}

View File

@@ -0,0 +1,155 @@
/*
* 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.repository.cdi;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Set;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
import org.springframework.data.gemfire.repository.support.GemfireRepositoryFactory;
import org.springframework.data.repository.cdi.CdiRepositoryBean;
import org.springframework.data.repository.config.CustomRepositoryImplementationDetector;
import com.gemstone.gemfire.cache.Region;
/**
* A CDI-based bean that represents a GemFire Repository.
*
* @author John Blum
* @param <T> class type of the Repository.
* @see javax.enterprise.context.spi.CreationalContext
* @see javax.enterprise.inject.spi.Bean
* @see javax.enterprise.inject.spi.BeanManager
* @see org.springframework.data.gemfire.mapping.GemfireMappingContext
* @see org.springframework.data.gemfire.repository.support.GemfireRepositoryFactory
* @see org.springframework.data.repository.cdi.CdiRepositoryBean
* @see org.springframework.data.repository.config.CustomRepositoryImplementationDetector
* @see com.gemstone.gemfire.cache.Region
* @since 1.8.0
*/
class GemfireRepositoryBean<T> extends CdiRepositoryBean<T> {
static final GemfireMappingContext DEFAULT_GEMFIRE_MAPPING_CONTEXT = new GemfireMappingContext();
private final Bean<GemfireMappingContext> gemfireMappingContextBean;
private final BeanManager beanManager;
private final Set<Bean<Region>> regionBeans;
/* (non-Javadoc) */
@SuppressWarnings("unchecked")
GemfireRepositoryBean(BeanManager beanManager, Class<T> repositoryType, Set<Annotation> qualifiers,
CustomRepositoryImplementationDetector detector, Bean<GemfireMappingContext> gemfireMappingContextBean,
Set<Bean<Region>> regionBeans) {
super(qualifiers, repositoryType, beanManager, detector);
this.beanManager = beanManager;
this.gemfireMappingContextBean = gemfireMappingContextBean;
this.regionBeans = regionBeans;
}
/**
* Returns an instance of the given {@link Bean} from the container.
*
* @param <S> the actual class type of the {@link Bean}.
* @param bean the {@link Bean} defining the instance to create.
* @param type the expected component type of the instance created from the {@link Bean}.
* @return an instance of the given {@link Bean}.
* @see javax.enterprise.inject.spi.BeanManager#getReference(Bean, Type, CreationalContext)
* @see javax.enterprise.inject.spi.Bean
* @see java.lang.reflect.Type
*/
@SuppressWarnings("unchecked")
protected <S> S getDependencyInstance(Bean<S> bean, Type type) {
return (S) beanManager.getReference(bean, type, beanManager.createCreationalContext(bean));
}
/**
* Resolves the desired, actual component type from the {@link Bean} in which the instance is created.
*
* @param <S> the class type of the component.
* @param bean the {@link Bean} from which the types are evaluated and an instance is created.
* @param targetType the desired class type of the component.
* @return a resolved component {@link Type} of the {@link Bean}instance.
* @throws IllegalStateException if the desired class type cannot be resolved.
* @see javax.enterprise.inject.spi.Bean#getTypes()
* @see java.lang.Class
*/
@SuppressWarnings("unchecked")
protected <S> Type resolveType(Bean<S> bean, Class<S> targetType) {
for (Type type : bean.getTypes()) {
Type assignableType = (type instanceof ParameterizedType ? ((ParameterizedType) type).getRawType() : type);
if (assignableType instanceof Class && targetType.isAssignableFrom((Class) assignableType)) {
return type;
}
}
throw new IllegalStateException(String.format(
"unable to resolve bean instance of type [%1$s] from bean definition [%2$s]",
targetType, bean));
}
/* (non-Javadoc) */
Iterable<Region<?, ?>> resolveGemfireRegions() {
Set<Region<?, ?>> regions = new HashSet<Region<?, ?>>(regionBeans.size());
for (Bean<Region> regionBean : regionBeans) {
regions.add(getDependencyInstance(regionBean, resolveType(regionBean, Region.class)));
}
return regions;
}
/* (non-Javadoc) */
GemfireMappingContext resolveGemfireMappingContext() {
return (gemfireMappingContextBean != null
? getDependencyInstance(gemfireMappingContextBean, GemfireMappingContext.class)
: DEFAULT_GEMFIRE_MAPPING_CONTEXT);
}
/* (non-Javadoc) */
GemfireRepositoryFactory newGemfireRepositoryFactory() {
return new GemfireRepositoryFactory(resolveGemfireRegions(), resolveGemfireMappingContext());
}
/**
* Creates an instance of the given Repository type as a bean instance in the CDI container.
*
* @param creationalContext operations used by the {@link javax.enterprise.context.spi.Contextual} implementation
* during creation of the bean instance.
* @param repositoryType the actual class type of the SD (GemFire) Repository.
* @param customImplementation the supporting custom Repository implementing class.
* @return a factory used to create instance of {@link org.springframework.data.gemfire.repository.GemfireRepository}.
* @see javax.enterprise.context.spi.Contextual#create(javax.enterprise.context.spi.CreationalContext)
* @see #newGemfireRepositoryFactory()
*/
@Override
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType, Object customImplementation) {
return newGemfireRepositoryFactory().getRepository(repositoryType, customImplementation);
}
}

View File

@@ -0,0 +1,134 @@
/*
* 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.repository.cdi;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.ProcessBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
import org.springframework.data.repository.cdi.CdiRepositoryBean;
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
import com.gemstone.gemfire.cache.Region;
/**
* The GemfireRepositoryExtension class...
*
* @author John Blum
* @see org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport
* @since 1.8.0
*/
@SuppressWarnings("unused")
public class GemfireRepositoryExtension extends CdiRepositoryExtensionSupport {
protected final Logger logger = LoggerFactory.getLogger(getClass());
final Map<Set<Annotation>, Bean<GemfireMappingContext>> mappingContexts =
new HashMap<Set<Annotation>, Bean<GemfireMappingContext>>();
final Set<Bean<Region>> regionBeans = new HashSet<Bean<Region>>();
/* (non-Javadoc) */
public GemfireRepositoryExtension() {
logger.info("Activating CDI extension for Spring Data GemFire Repositories");
}
/**
* Implementation of an observer that captures GemFire Region beans defined in the CDI container, storing them
* along with any defined GemfireMappingContexts for later construction of the Repository beans.
*
* @param <X> class type of the bean instance.
* @param processBean annotated type as defined by CDI.
* @see javax.enterprise.inject.spi.ProcessBean
* @see javax.enterprise.event.Observes
*/
@SuppressWarnings("unchecked")
<X> void processBean(@Observes ProcessBean<X> processBean) {
Bean<X> bean = processBean.getBean();
for (Type type : bean.getTypes()) {
Type resolvedType = (type instanceof ParameterizedType ? ((ParameterizedType) type).getRawType() : type);
if (resolvedType instanceof Class<?>) {
Class<?> classType = (Class<?>) resolvedType;
if (Region.class.isAssignableFrom(classType)) {
logger.debug("Found Region bean with name {}", bean.getName());
regionBeans.add((Bean<Region>) bean);
}
else if (GemfireMappingContext.class.isAssignableFrom(classType)) {
logger.debug("Discovered {} bean with types {} having qualifiers {}",
GemfireMappingContext.class.getName(), bean.getTypes(), bean.getQualifiers());
mappingContexts.put(bean.getQualifiers(), (Bean<GemfireMappingContext>) bean);
}
}
}
}
/**
* Implementation of an observer that registers beans in the CDI container for the detected Spring Data
* Repositories.
*
* Repository beans are associated to the appropriate GemfireMappingContexts based on their qualifiers.
*
* @param beanManager the BeanManager instance.
* @see javax.enterprise.inject.spi.AfterBeanDiscovery
* @see javax.enterprise.inject.spi.BeanManager
* @see javax.enterprise.event.Observes
*/
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
for (Map.Entry<Class<?>, Set<Annotation>> entry : getRepositoryTypes()) {
Class<?> repositoryType = entry.getKey();
Set<Annotation> qualifiers = entry.getValue();
// Create the bean representing the Repository.
CdiRepositoryBean<?> repositoryBean = createRepositoryBean(beanManager, repositoryType, qualifiers);
logger.info("Registering bean for '{}' with qualifiers {}.", repositoryType.getName(), qualifiers);
// Register the bean with the extension and the container.
registerBean(repositoryBean);
afterBeanDiscovery.addBean(repositoryBean);
}
}
/* (non-Javadoc) */
<T> CdiRepositoryBean<T> createRepositoryBean(BeanManager beanManager, Class<T> repositoryType,
Set<Annotation> qualifiers) {
// Determine the GemfireMappingContext bean that matches the qualifiers of the Repository.
Bean<GemfireMappingContext> gemfireMappingContextBean = mappingContexts.get(qualifiers);
// Construct and return a GemFire Repository bean.
return new GemfireRepositoryBean<T>(beanManager, repositoryType, qualifiers, getCustomImplementationDetector(),
gemfireMappingContextBean, regionBeans);
}
}

View File

@@ -55,6 +55,7 @@ public class GemfireRepositoryFactoryBean<T extends Repository<S, ID>, S, ID ext
extends RepositoryFactoryBeanSupport<T, S, ID> implements ApplicationContextAware {
private Iterable<Region<?, ?>> regions;
private MappingContext<? extends GemfirePersistentEntity<?>, GemfirePersistentProperty> context;
/**
@@ -67,7 +68,6 @@ 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);
}
@@ -80,7 +80,6 @@ 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;
}
@@ -118,10 +117,8 @@ public class GemfireRepositoryFactoryBean<T extends Repository<S, ID>, S, ID ext
*/
@Override
public void afterPropertiesSet() {
Assert.state(context != null, "GemfireMappingContext must not be null!");
super.afterPropertiesSet();
}
}

View File

@@ -0,0 +1 @@
org.springframework.data.gemfire.repository.cdi.GemfireRepositoryExtension

View File

@@ -0,0 +1,109 @@
/*
* 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.repository.cdi;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import org.apache.webbeans.cditest.CdiTestContainer;
import org.apache.webbeans.cditest.CdiTestContainerLoader;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.data.gemfire.repository.sample.Person;
import com.gemstone.gemfire.cache.CacheClosedException;
import com.gemstone.gemfire.cache.CacheFactory;
/**
* The CdiExtensionIntegrationTest class...
*
* @author John Blum
* @see org.junit.Test
* @see org.springframework.data.gemfire.repository.cdi.GemfireRepositoryBean
* @see org.springframework.data.gemfire.repository.cdi.GemfireRepositoryExtension
* @see org.apache.webbeans.cditest.CdiTestContainer
* @see org.apache.webbeans.cditest.CdiTestContainerLoader
* @since 1.8.0
*/
public class CdiExtensionIntegrationTest {
static CdiTestContainer container;
@BeforeClass
public static void setUp() throws Exception {
container = CdiTestContainerLoader.getCdiContainer();
container.bootContainer();
}
@AfterClass
public static void tearDown() throws Exception {
container.shutdownContainer();
closeGemfireCache();
}
private static void closeGemfireCache() {
try {
CacheFactory.getAnyInstance().close();
}
catch (CacheClosedException ignore) {
}
}
protected void assertIsExpectedPerson(Person actual, Person expected) {
assertThat(actual.getId(), is(equalTo(expected.getId())));
assertThat(actual.getFirstname(), is(equalTo(expected.getFirstname())));
assertThat(actual.getLastname(), is(equalTo(expected.getLastname())));
}
@Test
public void bootstrapsRepositoryCorrectly() {
RepositoryClient repositoryClient = container.getInstance(RepositoryClient.class);
assertThat(repositoryClient.getPersonRepository(), is(notNullValue()));
Person expectedJonDoe = repositoryClient.newPerson("Jon", "Doe");
assertThat(expectedJonDoe, is(notNullValue()));
assertThat(expectedJonDoe.getId(), is(greaterThan(0l)));
assertThat(expectedJonDoe.getName(), is(equalTo("Jon Doe")));
Person savedJonDoe = repositoryClient.save(expectedJonDoe);
assertIsExpectedPerson(savedJonDoe, expectedJonDoe);
Person foundJonDoe = repositoryClient.find(expectedJonDoe.getId());
assertIsExpectedPerson(foundJonDoe, expectedJonDoe);
assertThat(repositoryClient.delete(expectedJonDoe), is(true));
assertThat(repositoryClient.find(expectedJonDoe.getId()), is(nullValue()));
}
@Test
public void returnOneFromCustomImplementation() {
RepositoryClient repositoryClient = container.getInstance(RepositoryClient.class);
assertThat(repositoryClient.getPersonRepository().returnOne(), is(equalTo(1)));
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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.repository.cdi;
/**
* The CustomPersonRepository interface is an Spring Data Repository extension type specifying additional, "custom"
* data access operations on people.
*
* @author John Blum
* @since 1.8.0
*/
public interface CustomPersonRepository {
int returnOne();
}

View File

@@ -0,0 +1,69 @@
/*
* 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.repository.cdi;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import org.springframework.data.gemfire.repository.sample.Person;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionFactory;
import com.gemstone.gemfire.cache.RegionShortcut;
/**
* The GemfireCacheRegionProducer class is an application scoped CDI context bean that is responsible
* for creating the GemFire Cache "People" Region used to store {@link Person} instances.
*
* @author John Blum
* @see javax.enterprise.context.ApplicationScoped
* @see javax.enterprise.inject.Produces
* @see com.gemstone.gemfire.cache.Cache
* @see com.gemstone.gemfire.cache.CacheFactory
* @see com.gemstone.gemfire.cache.Region
* @see com.gemstone.gemfire.cache.RegionFactory
* @since 1.8.0
*/
@SuppressWarnings("unused")
public class GemfireCacheRegionProducer {
@Produces
@ApplicationScoped
public Region<Long, Person> createPeopleRegion() {
Cache gemfireCache = new CacheFactory()
.set("name", "SpringDataGemFireCdiTest")
.set("mcast-port", "0")
.set("log-level", "warning")
.create();
RegionFactory<Long, Person> peopleRegionFactory = gemfireCache.createRegionFactory(RegionShortcut.REPLICATE);
peopleRegionFactory.setKeyConstraint(Long.class);
peopleRegionFactory.setValueConstraint(Person.class);
Region<Long, Person> peopleRegion = peopleRegionFactory.create("People");
Assert.notNull(peopleRegion);
return peopleRegion;
}
}

View File

@@ -0,0 +1,344 @@
/*
* 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.repository.cdi;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isIn;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.data.gemfire.GemfireAccessor;
import org.springframework.data.gemfire.TestUtils;
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
import org.springframework.data.gemfire.repository.GemfireRepository;
import org.springframework.data.gemfire.repository.support.GemfireRepositoryFactory;
import org.springframework.data.gemfire.repository.support.SimpleGemfireRepository;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
/**
* The GemfireRepositoryBeanTest class is a test suite of test cases testing the contract and functionality
* of the GemfireRepositoryBean class.
*
* @author John Blum
* @see org.junit.Rule
* @see org.junit.Test
* @see org.junit.rules.ExpectedException
* @see org.junit.runner.RunWith
* @see org.mockito.Mock
* @see org.mockito.Mockito
* @see org.mockito.runners.MockitoJUnitRunner
* @see org.springframework.data.gemfire.repository.cdi.GemfireRepositoryBean
* @since 1.0.0
*/
@RunWith(MockitoJUnitRunner.class)
@SuppressWarnings("unchecked")
public class GemfireRepositoryBeanTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Mock
private BeanManager mockBeanManager;
protected <T> T[] asArray(T... array) {
return array;
}
protected <T> Set<T> asSet(T... array) {
return new HashSet<T>(Arrays.asList(array));
}
protected <T> Set<T> asSet(Iterable<T> collection) {
Set<T> set = new HashSet<T>();
for (T element : collection) {
set.add(element);
}
return set;
}
@Test
public void getDependencyInstanceGetsReference() {
Bean<Region> mockRegionBean = mock(Bean.class);
CreationalContext<Region> mockCreationalContext = mock(CreationalContext.class);
Region mockRegion = mock(Region.class);
when(mockBeanManager.createCreationalContext(eq(mockRegionBean))).thenReturn(mockCreationalContext);
when(mockBeanManager.getReference(eq(mockRegionBean), eq(Region.class), eq(mockCreationalContext)))
.thenReturn(mockRegion);
GemfireRepositoryBean<PersonRepository> repositoryBean = new GemfireRepositoryBean<PersonRepository>(
mockBeanManager, PersonRepository.class, Collections.<Annotation>emptySet(), null, null, null);
assertThat(repositoryBean.getDependencyInstance(mockRegionBean, Region.class), is(equalTo(mockRegion)));
verify(mockBeanManager, times(1)).createCreationalContext(eq(mockRegionBean));
verify(mockBeanManager, times(1)).getReference(eq(mockRegionBean), eq(Region.class), eq(mockCreationalContext));
}
@Test
public void resolveGemfireMappingContextUsesDefault() {
GemfireRepositoryBean<PersonRepository> repositoryBean = new GemfireRepositoryBean<PersonRepository>(
mockBeanManager, PersonRepository.class, Collections.<Annotation>emptySet(), null, null, null);
assertThat(repositoryBean.resolveGemfireMappingContext(),
is(equalTo(GemfireRepositoryBean.DEFAULT_GEMFIRE_MAPPING_CONTEXT)));
}
@Test
public void resolveGemfireMappingContextUsesQualifiedMappingContext() {
Bean<GemfireMappingContext> mockMappingContextBean = mock(Bean.class);
CreationalContext<GemfireMappingContext> mockCreationalContext = mock(CreationalContext.class);
GemfireMappingContext expectedGemfireMappingContext = new GemfireMappingContext();
when(mockBeanManager.createCreationalContext(eq(mockMappingContextBean))).thenReturn(mockCreationalContext);
when(mockBeanManager.getReference(eq(mockMappingContextBean), eq(GemfireMappingContext.class),
eq(mockCreationalContext))).thenReturn(expectedGemfireMappingContext);
GemfireRepositoryBean<PersonRepository> repositoryBean = new GemfireRepositoryBean<PersonRepository>(
mockBeanManager, PersonRepository.class, Collections.<Annotation>emptySet(), null,
mockMappingContextBean, null);
GemfireMappingContext actualGemfireMappingContext = repositoryBean.resolveGemfireMappingContext();
assertThat(actualGemfireMappingContext, is(equalTo(expectedGemfireMappingContext)));
verify(mockBeanManager, times(1)).createCreationalContext(eq(mockMappingContextBean));
verify(mockBeanManager, times(1)).getReference(eq(mockMappingContextBean), eq(GemfireMappingContext.class),
eq(mockCreationalContext));
}
@Test
public void resolveGemfireRegions() {
Region mockRegionOne = mock(Region.class);
Region mockRegionTwo = mock(Region.class);
CreationalContext<Bean<Region>> mockCreationalContext = mock(CreationalContext.class);
Bean<Region> mockRegionBeanOne = mock(Bean.class);
Bean<Region> mockRegionBeanTwo = mock(Bean.class);
when(mockRegionBeanOne.getTypes()).thenReturn(asSet((Type) Region.class));
when(mockRegionBeanTwo.getTypes()).thenReturn(asSet((Type) Region.class));
when(mockBeanManager.createCreationalContext(any(Bean.class))).thenReturn(mockCreationalContext);
when(mockBeanManager.getReference(eq(mockRegionBeanOne), eq(Region.class), eq(mockCreationalContext)))
.thenReturn(mockRegionOne);
when(mockBeanManager.getReference(eq(mockRegionBeanTwo), eq(Region.class), eq(mockCreationalContext)))
.thenReturn(mockRegionTwo);
GemfireRepositoryBean repositoryBean = new GemfireRepositoryBean(mockBeanManager,
PersonRepository.class, Collections.emptySet(), null, null, asSet(mockRegionBeanOne, mockRegionBeanTwo));
Iterable<Region> regions = repositoryBean.resolveGemfireRegions();
assertThat(regions, is(notNullValue()));
assertThat(asSet(regions).containsAll(asSet(mockRegionOne, mockRegionTwo)), is(true));
verify(mockRegionBeanOne, times(1)).getTypes();
verify(mockRegionBeanTwo, times(1)).getTypes();
verify(mockBeanManager, times(1)).createCreationalContext(eq(mockRegionBeanOne));
verify(mockBeanManager, times(1)).createCreationalContext(eq(mockRegionBeanTwo));
verify(mockBeanManager, times(1)).getReference(eq(mockRegionBeanOne), eq(Region.class),
eq(mockCreationalContext));
verify(mockBeanManager, times(1)).getReference(eq(mockRegionBeanTwo), eq(Region.class),
eq(mockCreationalContext));
}
@Test
public void resolveTypeFindsTargetComponentType() {
Bean mockBean = mock(Bean.class);
when(mockBean.getTypes()).thenReturn(
asSet((Type) Object.class, Map.class, ConcurrentMap.class, Region.class));
GemfireRepositoryBean<PersonRepository> repositoryBean = new GemfireRepositoryBean<PersonRepository>(
mockBeanManager, PersonRepository.class, Collections.<Annotation>emptySet(), null, null, null);
assertThat(repositoryBean.resolveType(mockBean, Region.class), is(equalTo((Type) Region.class)));
assertThat(repositoryBean.resolveType(mockBean, Map.class), isIn(asArray((Type) Map.class,
ConcurrentMap.class, Region.class)));
verify(mockBean, times(2)).getTypes();
}
@Test
public void resolveTypeWithParameterizedType() {
Bean<Map> mockBean = mock(Bean.class);
Map<Long, Object> parameterizedTypeMap = Collections.emptyMap();
ParameterizedType mockParameterizedType = mock(ParameterizedType.class);
assertThat(parameterizedTypeMap.getClass(), is(instanceOf(Type.class)));
assertThat(parameterizedTypeMap.getClass().getGenericSuperclass(), is(instanceOf(ParameterizedType.class)));
assertThat(parameterizedTypeMap.getClass().getTypeParameters().length, is(equalTo(2)));
when(mockBean.getTypes()).thenReturn(asSet((Type) mockParameterizedType));
when(mockParameterizedType.getRawType()).thenReturn(parameterizedTypeMap.getClass());
GemfireRepositoryBean<PersonRepository> repositoryBean = new GemfireRepositoryBean<PersonRepository>(
mockBeanManager, PersonRepository.class, Collections.<Annotation>emptySet(), null, null, null);
assertThat(repositoryBean.resolveType(mockBean, Map.class), is(equalTo((Type) mockParameterizedType)));
verify(mockBean, times(1)).getTypes();
verify(mockParameterizedType, times(1)).getRawType();
}
@Test
public void resolveTypeWithUnresolvableType() {
Bean mockBean = mock(Bean.class);
when(mockBean.getTypes()).thenReturn(asSet((Type) Map.class, Object.class));
GemfireRepositoryBean<PersonRepository> repositoryBean = new GemfireRepositoryBean<PersonRepository>(
mockBeanManager, PersonRepository.class, Collections.<Annotation>emptySet(), null, null, null);
try {
expectedException.expect(IllegalStateException.class);
expectedException.expectCause(is(nullValue(Throwable.class)));
expectedException.expectMessage(is(equalTo(String.format(
"unable to resolve bean instance of type [%1$s] from bean definition [%2$s]",
Region.class, mockBean))));
repositoryBean.resolveType(mockBean, Region.class);
}
finally {
verify(mockBean, times(1)).getTypes();
}
}
@Test
// IntegrationTest
public void createGemfireRepositoryInstanceSuccessfully() throws Exception {
Bean<Region> mockRegionBean = mock(Bean.class);
CreationalContext<Bean<Region>> mockCreationalContext = mock(CreationalContext.class);
final Region mockRegion = mock(Region.class);
RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
when(mockRegion.getName()).thenReturn("Person");
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
when(mockRegionAttributes.getKeyConstraint()).thenReturn(Long.class);
when(mockRegionBean.getTypes()).thenReturn(asSet((Type) Region.class));
when(mockBeanManager.createCreationalContext(any(Bean.class))).thenReturn(mockCreationalContext);
when(mockBeanManager.getReference(eq(mockRegionBean), eq(Region.class), eq(mockCreationalContext)))
.thenReturn(mockRegion);
final AtomicBoolean repositoryProxyPostProcessed = new AtomicBoolean(false);
GemfireRepositoryBean<PersonRepository> repositoryBean = new GemfireRepositoryBean<PersonRepository>(
mockBeanManager, PersonRepository.class, Collections.<Annotation>emptySet(), null, null,
asSet(mockRegionBean))
{
@Override
GemfireRepositoryFactory newGemfireRepositoryFactory() {
GemfireRepositoryFactory gemfireRepositoryFactory = super.newGemfireRepositoryFactory();
gemfireRepositoryFactory.addRepositoryProxyPostProcessor(new RepositoryProxyPostProcessor() {
public void postProcess(ProxyFactory factory, RepositoryInformation repositoryInformation) {
try {
assertThat((Class<PersonRepository>) repositoryInformation.getRepositoryInterface(),
is(equalTo(PersonRepository.class)));
assertThat((Class<SimpleGemfireRepository>) repositoryInformation.getRepositoryBaseClass(),
is(equalTo(SimpleGemfireRepository.class)));
assertThat((Class<Person>) repositoryInformation.getDomainType(), is(equalTo(Person.class)));
assertThat((Class<Long>) repositoryInformation.getIdType(), is(equalTo(Long.class)));
assertThat((Class<SimpleGemfireRepository>) factory.getTargetClass(),
is(equalTo(SimpleGemfireRepository.class)));
Object gemfireRepository = factory.getTargetSource().getTarget();
GemfireAccessor gemfireAccessor = TestUtils.readField("template", gemfireRepository);
assertThat(gemfireAccessor, is(notNullValue()));
assertThat(gemfireAccessor.getRegion(), is(equalTo(mockRegion)));
repositoryProxyPostProcessed.set(true);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
return gemfireRepositoryFactory;
}
};
GemfireRepository<Person, Long> gemfireRepository = repositoryBean.create(null, PersonRepository.class, null);
assertThat(gemfireRepository, is(notNullValue()));
assertThat(repositoryProxyPostProcessed.get(), is(true));
verify(mockBeanManager, times(1)).createCreationalContext(eq(mockRegionBean));
verify(mockBeanManager, times(1)).getReference(eq(mockRegionBean), eq(Region.class),
eq(mockCreationalContext));
verify(mockRegionBean, times(1)).getTypes();
verify(mockRegion, times(1)).getName();
verify(mockRegion, times(1)).getAttributes();
verify(mockRegionAttributes, times(1)).getKeyConstraint();
}
class TestMap extends AbstractMap<Long, Object> {
@Override public Set<Entry<Long, Object>> entrySet() {
return Collections.emptySet();
}
}
class Person {}
interface PersonRepository extends GemfireRepository<Person, Long> {
}
}

View File

@@ -0,0 +1,191 @@
/*
* 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.repository.cdi;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.ProcessBean;
import javax.inject.Qualifier;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
import org.springframework.data.gemfire.repository.GemfireRepository;
import com.gemstone.gemfire.cache.Region;
/**
* The GemfireRepositoryExtensionTest class is a test suite of unit tests testing the contract and proper functionality
* of the {@link GemfireRepositoryExtension} class in a Java EE CDI context.
*
* @author John Blum
* @see javax.enterprise.inject.spi.Bean
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.springframework.data.gemfire.mapping.GemfireMappingContext
* @see org.springframework.data.gemfire.repository.GemfireRepository
* @see org.springframework.data.gemfire.repository.cdi.GemfireRepositoryExtension
* @since 1.0.0
*/
@SuppressWarnings("unchecked")
public class GemfireRepositoryExtensionTest {
private GemfireRepositoryExtension repositoryExtension;
@Before
public void setup() {
repositoryExtension = new GemfireRepositoryExtension();
}
protected <T> Set<T> asSet(T... array) {
return new HashSet<T>(Arrays.asList(array));
}
protected Annotation mockAnnotation(Class annotationType) {
Annotation mockAnnotation = mock(Annotation.class);
when(mockAnnotation.annotationType()).thenReturn(annotationType);
return mockAnnotation;
}
@Test
public void processBeanIdentifiesAndProcessesRegionBeanCorrectly() {
ProcessBean<Region> mockProcessBean = mock(ProcessBean.class);
Bean<Region> mockBean = mock(Bean.class);
when(mockProcessBean.getBean()).thenReturn(mockBean);
when(mockBean.getTypes()).thenReturn(Collections.singleton((Type) Region.class));
assertThat(repositoryExtension.regionBeans.isEmpty(), is(true));
repositoryExtension.processBean(mockProcessBean);
assertThat(repositoryExtension.regionBeans.contains(mockBean), is(true));
verify(mockProcessBean, times(1)).getBean();
verify(mockBean, times(1)).getTypes();
}
@Test
public void processBeanIdentifiesAndProcessesGemfireMappingContextBeanCorrectly() {
ProcessBean<GemfireMappingContext> mockProcessBean = mock(ProcessBean.class);
Bean<GemfireMappingContext> mockBean = mock(Bean.class);
Set<Annotation> expectedQualifiers = asSet(mockAnnotation(SpringDataRepo.class),
mockAnnotation(GemfireRepo.class));
when(mockProcessBean.getBean()).thenReturn(mockBean);
when(mockBean.getTypes()).thenReturn(Collections.singleton((Type) GemfireMappingContext.class));
when(mockBean.getQualifiers()).thenReturn(expectedQualifiers);
assertThat(repositoryExtension.mappingContexts.isEmpty(), is(true));
repositoryExtension.processBean(mockProcessBean);
assertThat(repositoryExtension.mappingContexts.containsKey(expectedQualifiers), is(true));
assertThat(repositoryExtension.mappingContexts.get(expectedQualifiers), is(equalTo(mockBean)));
verify(mockProcessBean, times(1)).getBean();
verify(mockBean, times(2)).getTypes();
verify(mockBean, times(2)).getQualifiers();
}
@Test
public void processBeanIgnoresNonRegionNonGemfireMappingContextBeansProperly() {
ProcessBean<Object> mockProcessBean = mock(ProcessBean.class);
Bean<Object> mockBean = mock(Bean.class);
when(mockProcessBean.getBean()).thenReturn(mockBean);
when(mockBean.getTypes()).thenReturn(Collections.singleton((Type) Object.class));
assertThat(repositoryExtension.mappingContexts.isEmpty(), is(true));
assertThat(repositoryExtension.regionBeans.isEmpty(), is(true));
repositoryExtension.processBean(mockProcessBean);
assertThat(repositoryExtension.mappingContexts.isEmpty(), is(true));
assertThat(repositoryExtension.regionBeans.isEmpty(), is(true));
verify(mockProcessBean, times(1)).getBean();
verify(mockBean, times(1)).getTypes();
}
@Test
public void afterBeanDiscoveryRegistersRepositoryBean() {
AfterBeanDiscovery mockAfterBeanDiscovery = mock(AfterBeanDiscovery.class);
final Set<Annotation> expectedQualifiers = asSet(mockAnnotation(SpringDataRepo.class),
mockAnnotation(GemfireRepo.class));
doAnswer(new Answer<Void>() {
public Void answer(final InvocationOnMock invocation) throws Throwable {
GemfireRepositoryBean<?> repositoryBean = invocation.getArgumentAt(0, GemfireRepositoryBean.class);
assertThat(repositoryBean, is(notNullValue()));
assertThat((Class<TestRepository>) repositoryBean.getBeanClass(), is(equalTo(TestRepository.class)));
assertThat(repositoryBean.getQualifiers(), is(equalTo(expectedQualifiers)));
return null;
}
}).when(mockAfterBeanDiscovery).addBean(isA(GemfireRepositoryBean.class));
GemfireRepositoryExtension repositoryExtension = new GemfireRepositoryExtension() {
@Override protected Iterable<Map.Entry<Class<?>, Set<Annotation>>> getRepositoryTypes() {
return Collections.<Class<?>, Set<Annotation>>singletonMap(TestRepository.class, expectedQualifiers).entrySet();
}
};
repositoryExtension.afterBeanDiscovery(mockAfterBeanDiscovery, mock(BeanManager.class));
verify(mockAfterBeanDiscovery, times(1)).addBean(isA(GemfireRepositoryBean.class));
}
@Qualifier
@interface GemfireRepo {
}
@Qualifier
@interface SpringDataRepo {
}
@GemfireRepo
@SpringDataRepo
interface TestRepository extends GemfireRepository<Object, Long> {
}
}

View File

@@ -0,0 +1,62 @@
/*
* 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.repository.cdi;
import java.util.concurrent.atomic.AtomicLong;
import javax.inject.Inject;
import org.springframework.data.gemfire.repository.sample.Person;
import org.springframework.util.Assert;
/**
* The RepositoryClient class is a user/consumer of the {@link SamplePersonRepository} bean in a CDI context.
*
* @author John Blum
* @see javax.inject.Inject
* @see org.springframework.data.gemfire.repository.cdi.SamplePersonRepository
* @since 1.8.0
*/
public class RepositoryClient {
private static final AtomicLong ID_SEQUENCE = new AtomicLong(0l);
@Inject
private SamplePersonRepository personRepository;
protected SamplePersonRepository getPersonRepository() {
Assert.state(personRepository != null, "personRepository was not properly initialized");
return personRepository;
}
public Person newPerson(String firstName, String lastName) {
return new Person(ID_SEQUENCE.incrementAndGet(), firstName, lastName);
}
public Person find(Long id) {
return getPersonRepository().findOne(id);
}
public Person save(Person person) {
return getPersonRepository().save(person);
}
public boolean delete(Person person) {
getPersonRepository().delete(person);
return (find(person.getId()) == null);
}
}

View File

@@ -0,0 +1,38 @@
/*
* 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.repository.cdi;
import org.springframework.data.gemfire.mapping.Region;
import org.springframework.data.gemfire.repository.GemfireRepository;
import org.springframework.data.gemfire.repository.sample.Person;
/**
* The SamplePersonRepository class is a {@link GemfireRepository} implementation for performing data access (CRUD)
* operations on instances of {@link Person}.
*
* @author John Blum
* @see org.springframework.data.gemfire.repository.GemfireRepository
* @see org.springframework.data.gemfire.repository.cdi.CustomPersonRepository
* @see org.springframework.data.gemfire.repository.cdi.SamplePersonRepositoryImpl
* @see org.springframework.data.gemfire.repository.sample.Person
* @since 1.8.0
*/
@Region("People")
public interface SamplePersonRepository extends GemfireRepository<Person, Long>, CustomPersonRepository {
}

View File

@@ -0,0 +1,34 @@
/*
* 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.repository.cdi;
/**
* The SamplePersonRepositoryImpl class is an implementation of the {@link CustomPersonRepository} extension interface
* supporting additional data access (CRUD) operations on people.
*
* @author John Blum
* @see org.springframework.data.gemfire.repository.cdi.CustomPersonRepository
* @since 1.8.0
*/
public class SamplePersonRepositoryImpl implements CustomPersonRepository {
public int returnOne() {
return 1;
}
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

View File

@@ -2,14 +2,14 @@ Bundle-ManifestVersion: 2
Bundle-Name: Spring Data GemFire
Bundle-SymbolicName: org.springframework.data.gemfire
Bundle-Vendor: Pivotal Software, Inc.
Import-Package:
sun.reflect;version="0";resolution:=optional
Import-Template:
Import-Package: sun.reflect;version="0";resolution:=optional
Import-Template: javax.enterprise.*;version="[1.0,2.0)";resolution:=optional,
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,
org.aspectj.*;version="[1.8.2, 2.0.0)";resolution:=optional,
com.fasterxml.jackson.*;version="[2.4.1,3.0.0)";resolution:=optional,
com.gemstone.*;version="[8.0.0,9.0.0)",
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
org.aspectj.*;version="[1.8.2, 2.0.0)";resolution:=optional,
org.slf4j.*;version="[1.7.0,2.0)",
org.springframework.*;version="[4.0.6, 5.0.0)",
org.springframework.data.*;version="[1.9.0,2.0.0)",
org.w3c.dom.*;version="0"