SGF-469 - Add support for CDI.

(cherry picked from commit 34da7ec91044c9f01647d444ccbe12ed890b4cc6)
Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
John Blum
2016-02-17 09:08:16 -08:00
parent 4cdd9a04ba
commit b68c1f450c
17 changed files with 1231 additions and 10 deletions

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;
}
}