diff --git a/src/main/java/org/springframework/data/gemfire/repository/support/GemfireRepositoryFactory.java b/src/main/java/org/springframework/data/gemfire/repository/support/GemfireRepositoryFactory.java index 2ead125f..44327a3e 100644 --- a/src/main/java/org/springframework/data/gemfire/repository/support/GemfireRepositoryFactory.java +++ b/src/main/java/org/springframework/data/gemfire/repository/support/GemfireRepositoryFactory.java @@ -36,6 +36,7 @@ import org.springframework.data.repository.query.QueryLookupStrategy; import org.springframework.data.repository.query.QueryLookupStrategy.Key; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; import com.gemstone.gemfire.cache.Region; @@ -58,11 +59,9 @@ public class GemfireRepositoryFactory extends RepositoryFactorySupport { * @param regions must not be {@literal null}. * @param context */ - public GemfireRepositoryFactory(Iterable> regions, - MappingContext, GemfirePersistentProperty> context) { - + public GemfireRepositoryFactory(Iterable> regions, MappingContext, + GemfirePersistentProperty> context) { Assert.notNull(regions); - this.context = context == null ? new GemfireMappingContext() : context; this.regions = new Regions(regions, this.context); } @@ -70,14 +69,12 @@ public class GemfireRepositoryFactory extends RepositoryFactorySupport { /* * (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") public GemfireEntityInformation getEntityInformation(Class domainClass) { - GemfirePersistentEntity entity = (GemfirePersistentEntity) context.getPersistentEntity(domainClass); return new DefaultGemfireEntityInformation(entity); } @@ -85,64 +82,54 @@ 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.RepositoryMetadata) */ @Override @SuppressWarnings({ "rawtypes", "unchecked" }) protected Object getTargetRepository(RepositoryMetadata metadata) { - GemfireEntityInformation entityInformation = getEntityInformation(metadata.getDomainType()); GemfireTemplate gemfireTemplate = getTemplate(metadata); - return new SimpleGemfireRepository(gemfireTemplate, entityInformation); } private GemfireTemplate getTemplate(RepositoryMetadata metadata) { + GemfirePersistentEntity entity = context.getPersistentEntity(metadata.getDomainType()); - Class repositoryClass = metadata.getRepositoryInterface(); - Class domainClass = metadata.getDomainType(); - - GemfirePersistentEntity entity; - if (repositoryClass.isAnnotationPresent(org.springframework.data.gemfire.mapping.Region.class)) { - entity = context.getPersistentEntity(repositoryClass); - } - else { - entity = context.getPersistentEntity(domainClass); - } + String entityRegionName = entity.getRegionName(); + String repositoryRegionName = getRepositoryRegionName(metadata.getRepositoryInterface()); + String regionName = (StringUtils.hasText(repositoryRegionName) ? repositoryRegionName : entityRegionName); - Region region = regions.getRegion(entity.getRegionName()); + Region region = regions.getRegion(regionName); if (region == null) { - throw new IllegalStateException(String.format( - "No region '%s' found for domain class %s! Make sure you have " - + "configured a Gemfire region of that name in your application context!", - entity.getRegionName(), domainClass)); + throw new IllegalStateException(String.format("No region '%s' found for domain class %s!" + + " Make sure you have configured a Gemfire region of that name in your application context!", + regionName, metadata.getDomainType())); } Class regionKeyType = region.getAttributes().getKeyConstraint(); Class entityIdType = metadata.getIdType(); if (regionKeyType != null && entity.getIdProperty() != null) { - Assert.isTrue( - regionKeyType.isAssignableFrom(entityIdType), - String.format( - "The region referenced only supports keys of type %s but the entity to be stored has an id of type %s!", - regionKeyType, entityIdType)); + Assert.isTrue(regionKeyType.isAssignableFrom(entityIdType), String.format( + "The region referenced only supports keys of type %s but the entity to be stored has an id of type %s!", + regionKeyType, entityIdType)); } return new GemfireTemplate(region); } + private String getRepositoryRegionName(final Class repositoryClass) { + return (repositoryClass.isAnnotationPresent(org.springframework.data.gemfire.mapping.Region.class) ? + repositoryClass.getAnnotation(org.springframework.data.gemfire.mapping.Region.class).value() : null); + } + /* * (non-Javadoc) - * - * @see - * org.springframework.data.repository.core.support.RepositoryFactorySupport - * #getRepositoryBaseClass(org.springframework.data.repository.core. - * RepositoryMetadata) + * + * @see org.springframework.data.repository.core.support.RepositoryFactorySupport + * #getRepositoryBaseClass(org.springframework.data.repository.core.RepositoryMetadata) */ @Override protected Class getRepositoryBaseClass(RepositoryMetadata metadata) { @@ -152,10 +139,8 @@ public class GemfireRepositoryFactory extends RepositoryFactorySupport { /* * (non-Javadoc) * - * @see - * org.springframework.data.repository.core.support.RepositoryFactorySupport - * #getQueryLookupStrategy(org.springframework.data.repository.query. - * QueryLookupStrategy.Key) + * @see springframework.data.repository.core.support.RepositoryFactorySupport + * #getQueryLookupStrategy(org.springframework.data.repository.query.QueryLookupStrategy.Key) */ @Override protected QueryLookupStrategy getQueryLookupStrategy(Key key) { @@ -180,4 +165,5 @@ public class GemfireRepositoryFactory extends RepositoryFactorySupport { } }; } + } diff --git a/src/test/java/org/springframework/data/gemfire/repository/sample/Animal.java b/src/test/java/org/springframework/data/gemfire/repository/sample/Animal.java index 232e1502..bdaf8f7d 100644 --- a/src/test/java/org/springframework/data/gemfire/repository/sample/Animal.java +++ b/src/test/java/org/springframework/data/gemfire/repository/sample/Animal.java @@ -1,3 +1,19 @@ +/* + * Copyright 2010-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.data.gemfire.repository.sample; import org.springframework.data.annotation.Id; @@ -56,7 +72,7 @@ public class Animal { @Override public String toString() { - return String.format("{ type = %1$s, id = %2$d, name = %3$s }", getClass().getSimpleName(), getId(), getName()); + return String.format("{ @type = %1$s, id = %2$d, name = %3$s }", getClass().getSimpleName(), getId(), getName()); } } diff --git a/src/test/java/org/springframework/data/gemfire/repository/sample/AnimalRepositoryTest.java b/src/test/java/org/springframework/data/gemfire/repository/sample/AnimalRepositoryTest.java index 52f83fa4..8346871b 100644 --- a/src/test/java/org/springframework/data/gemfire/repository/sample/AnimalRepositoryTest.java +++ b/src/test/java/org/springframework/data/gemfire/repository/sample/AnimalRepositoryTest.java @@ -1,8 +1,23 @@ +/* + * Copyright 2010-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.data.gemfire.repository.sample; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; import org.junit.Test; import org.junit.runner.RunWith; @@ -11,11 +26,18 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** + * The AnimalRepositoryTest class is a test suite of test cases testing the functionality behind PR #55 involving + * persisting application domain object/entities to multiple Regions in GemFire's Cache. + *

* @author Stuart Williams * @author John Blum + * @see org.junit.Test + * @see org.junit.runner.RunWith + * @see org.springframework.test.context.ContextConfiguration + * @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner * @link https://github.com/spring-projects/spring-data-gemfire/pull/55 */ -@ContextConfiguration +@ContextConfiguration("AnimalRepositoryTest-context.xml") @RunWith(SpringJUnit4ClassRunner.class) @SuppressWarnings("unused") public class AnimalRepositoryTest { @@ -26,9 +48,6 @@ public class AnimalRepositoryTest { @Autowired private DogRepository dogRepo; - @Autowired - private RabbitRepository rabbitRepo; - protected static Animal createAnimal(final long id, final String name) { Animal animal = new Animal(); animal.setId(id); @@ -76,20 +95,4 @@ public class AnimalRepositoryTest { assertEquals(foundCerberusTheDog, dogRepo.findOne(3L)); } - @Test(expected = ClassCastException.class) - public void testStoreAnimalHavingLongIdInRabbitsRegionWithStringKey() { - try { - rabbitRepo.save(createAnimal(123L, "Harry")); - } - // NOTE the ClassCastException thrown from GemFire is expected; this is not correct and the identifying type - // mismatch should have been caught by GemfireRepositoryFactory.getTemplate(..) method on line 129 - // (appropriately throwing an IllegalArgumentException) after satisfying the condition on line 128, - // if only the @Region annotation were set on the domain class/entity! - catch (ClassCastException unexpected) { - //unexpected.printStackTrace(System.err); - assertTrue(unexpected.getMessage().contains("key ( java.lang.Long ) does not satisfy keyConstraint ( java.lang.String )")); - throw unexpected; - } - } - } diff --git a/src/test/java/org/springframework/data/gemfire/repository/sample/IncompatibleRegionKeyEntityIdAnimalRepositoryTest.java b/src/test/java/org/springframework/data/gemfire/repository/sample/IncompatibleRegionKeyEntityIdAnimalRepositoryTest.java new file mode 100644 index 00000000..50890ac7 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/repository/sample/IncompatibleRegionKeyEntityIdAnimalRepositoryTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.gemfire.repository.sample; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; + +import org.junit.Test; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * The IncompatibleRegionKeyEntityIdAnimalRepositoryTest class is a test suite of test cases testing the functionality + * behind PR #55 involving persisting application domain object/entities to multiple Regions in GemFire's Cache. + *

+ * @author John Blum + * @see org.junit.Test + * @see org.springframework.context.ConfigurableApplicationContext + * @since 1.4.0 + * @link https://github.com/spring-projects/spring-data-gemfire/pull/55 + */ +public class IncompatibleRegionKeyEntityIdAnimalRepositoryTest { + + protected static final String APPLICATION_CONTEXT_CONFIG_LOCATION = String.format("%1$s%2$s%1$s%3$s", + File.separator, AnimalRepositoryTest.class.getPackage().getName().replace('.', File.separatorChar), + "IncompatibleRegionKeyEntityIdAnimalRepositoryTest-context.xml"); + + @Test(expected = IllegalArgumentException.class) + public void testStoreAnimalHavingLongIdInRabbitsRegionWithStringKey() { + try { + ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext( + APPLICATION_CONTEXT_CONFIG_LOCATION); + applicationContext.getBean(RabbitRepository.class); + } + // NOTE the ClassCastException thrown from GemFire is unexpected; this is not correct and the identifying type + // mismatch should be caught and handled by GemfireRepositoryFactory.getTemplate(..) method on line 129 + // (appropriately throwing an IllegalArgumentException) after satisfying the condition on line 128, + // which always occurs with the @Region annotation set on the domain class/entity! + catch (ClassCastException unexpected) { + //unexpected.printStackTrace(System.err); + //assertTrue(unexpected.getMessage().contains("key ( java.lang.Long ) does not satisfy keyConstraint ( java.lang.String )")); + fail(unexpected.getMessage()); + } + catch (BeanCreationException expected) { + //expected.printStackTrace(System.err); + assertTrue(expected.getCause() instanceof IllegalArgumentException); + assertEquals(String.format("The region referenced only supports keys of type %1$s but the entity to be stored has an id of type %2$s!", + String.class, Long.class), expected.getCause().getMessage()); + throw (IllegalArgumentException) expected.getCause(); + } + } + +} diff --git a/src/test/java/org/springframework/data/gemfire/repository/sample/Plant.java b/src/test/java/org/springframework/data/gemfire/repository/sample/Plant.java index 026d3aa3..e1c6bfc5 100644 --- a/src/test/java/org/springframework/data/gemfire/repository/sample/Plant.java +++ b/src/test/java/org/springframework/data/gemfire/repository/sample/Plant.java @@ -79,7 +79,7 @@ public class Plant { @Override public String toString() { - return String.format("{ type = %1$s, id = %2$s, name = %3$s }", getClass().getSimpleName(), getId(), getName()); + return String.format("{ @type = %1$s, id = %2$s, name = %3$s }", getClass().getSimpleName(), getId(), getName()); } } diff --git a/src/test/java/org/springframework/data/gemfire/repository/sample/PlantRepositoryTest.java b/src/test/java/org/springframework/data/gemfire/repository/sample/PlantRepositoryTest.java index d4918c76..4ed2ea29 100644 --- a/src/test/java/org/springframework/data/gemfire/repository/sample/PlantRepositoryTest.java +++ b/src/test/java/org/springframework/data/gemfire/repository/sample/PlantRepositoryTest.java @@ -19,6 +19,8 @@ package org.springframework.data.gemfire.repository.sample; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.io.File; + import org.junit.Test; import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.ConfigurableApplicationContext; @@ -29,19 +31,22 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; * persisting application domain object/entities to multiple Regions in GemFire's Cache. *

* @author John Blum - * @see org.springframework.context.ApplicationContext + * @see org.junit.Test + * @see org.springframework.context.ConfigurableApplicationContext * @since 1.4.0 * @link https://github.com/spring-projects/spring-data-gemfire/pull/55 */ public class PlantRepositoryTest { - protected static final String APPLICATION_CONTEXT_CONFIG_LOCATION = - "/org/springframework/data/gemfire/repository/sample/PlantRepositoryTest-context.xml"; + protected static final String APPLICATION_CONTEXT_CONFIG_LOCATION = String.format("%1$s%2$s%1$s%3$s", + File.separator, PlantRepositoryTest.class.getPackage().getName().replace('.', File.separatorChar), + "PlantRepositoryTest-context.xml"); @Test(expected = IllegalArgumentException.class) public void testStorePlantHavingStringIdInPlantsRegionWithLongKey() { try { - ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(APPLICATION_CONTEXT_CONFIG_LOCATION); + ConfigurableApplicationContext context = new ClassPathXmlApplicationContext( + APPLICATION_CONTEXT_CONFIG_LOCATION); context.getBean(PlantRepository.class); } // NOTE technically, the IllegalArgumentException for incompatible Region 'Key' and Entity ID is thrown diff --git a/src/test/resources/org/springframework/data/gemfire/repository/sample/AnimalRepositoryTest-context.xml b/src/test/resources/org/springframework/data/gemfire/repository/sample/AnimalRepositoryTest-context.xml index e39a8304..ac42ea6f 100644 --- a/src/test/resources/org/springframework/data/gemfire/repository/sample/AnimalRepositoryTest-context.xml +++ b/src/test/resources/org/springframework/data/gemfire/repository/sample/AnimalRepositoryTest-context.xml @@ -31,12 +31,6 @@ key-constraint="java.lang.Long" value-constraint="org.springframework.data.gemfire.repository.sample.Animal"/> - - diff --git a/src/test/resources/org/springframework/data/gemfire/repository/sample/IncompatibleRegionKeyEntityIdAnimalRepositoryTest-context.xml b/src/test/resources/org/springframework/data/gemfire/repository/sample/IncompatibleRegionKeyEntityIdAnimalRepositoryTest-context.xml new file mode 100644 index 00000000..48d18854 --- /dev/null +++ b/src/test/resources/org/springframework/data/gemfire/repository/sample/IncompatibleRegionKeyEntityIdAnimalRepositoryTest-context.xml @@ -0,0 +1,30 @@ + + + + + springGemFireIncompatibleRegionKeyEntityIdAnimalRepositoryTest + config + 0 + + + + + + + + +