From 3063046e53e84a7d0dbf5d46e068a87f25267aad Mon Sep 17 00:00:00 2001 From: John Blum Date: Mon, 9 Mar 2015 23:35:16 -0700 Subject: [PATCH] SGF-381 - Enable RegionFactoryBean to respect the Data Policy specified on a nested or referenced RegionAttributes bean definition. --- build.gradle | 2 +- gradle.properties | 18 +- .../data/gemfire/RegionFactoryBean.java | 230 ++++++++++-------- .../gemfire/LocalRegionFactoryBeanTest.java | 7 +- .../data/gemfire/RegionFactoryBeanTest.java | 226 +++++++++++------ ...gionDefinitionUsingBeansNamespaceTest.java | 71 ++++++ .../AbstractRegionFactoryBeanTest.java | 72 +++--- .../data/gemfire/test/MockRegionFactory.java | 6 + .../data/gemfire/test/support/ArrayUtils.java | 44 ++++ ...initionUsingBeansNamespaceTest-context.xml | 34 +++ 10 files changed, 486 insertions(+), 224 deletions(-) create mode 100644 src/test/java/org/springframework/data/gemfire/config/RegionDefinitionUsingBeansNamespaceTest.java create mode 100644 src/test/java/org/springframework/data/gemfire/test/support/ArrayUtils.java create mode 100644 src/test/resources/org/springframework/data/gemfire/config/RegionDefinitionUsingBeansNamespaceTest-context.xml diff --git a/build.gradle b/build.gradle index 92a8ff3b..845dca9f 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ description = 'Spring Data GemFire' group = 'org.springframework.data' repositories { - maven { url "https://repo.spring.io/libs-milestone" } + maven { url "https://repo.spring.io/libs-snapshot" } maven { url "https://repo.spring.io/plugins-release"} } diff --git a/gradle.properties b/gradle.properties index 189270ca..5360ef98 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,14 +1,14 @@ antlrVersion=2.7.7 -slf4jVersion=1.7.7 -junitVersion=4.11 -gemfireVersion=8.0.0 -spring.range="[4.0.0, 5.0.0)" aspectjVersion=1.8.4 -springDataBuildVersion=1.6.0.RC1 -springVersion=4.0.9.RELEASE -springDataCommonsVersion=1.10.0.BUILD-SNAPSHOT -log4jVersion=1.2.17 +gemfireVersion=8.0.0 hamcrestVersion=1.3 -version=1.6.0.BUILD-SNAPSHOT jacksonVersion=2.4.1 +junitVersion=4.11 +log4jVersion=1.2.17 mockitoVersion=1.10.10 +slf4jVersion=1.7.7 +spring.range="[4.0.0, 5.0.0)" +springVersion=4.0.9.RELEASE +springDataBuildVersion=1.6.0.RC1 +springDataCommonsVersion=1.10.0.BUILD-SNAPSHOT +version=1.6.0.BUILD-SNAPSHOT diff --git a/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java index 8cae3c9a..baa18677 100644 --- a/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java @@ -29,6 +29,7 @@ import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; +import com.gemstone.gemfire.cache.AttributesFactory; import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.cache.CacheListener; import com.gemstone.gemfire.cache.CacheLoader; @@ -104,7 +105,8 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple @Override @SuppressWarnings("deprecation") protected Region lookupFallback(GemFireCache gemfireCache, String regionName) throws Exception { - Assert.isTrue(gemfireCache instanceof Cache, "Unable to create Regions from " + gemfireCache); + Assert.isTrue(gemfireCache instanceof Cache, String.format("Unable to create Regions from '%1$s'.", + gemfireCache)); Cache cache = (Cache) gemfireCache; @@ -112,7 +114,7 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple if (hubId != null) { enableGateway = (enableGateway == null || enableGateway); - Assert.isTrue(enableGateway, "The 'hubId' requires the 'enableGateway' property to be true"); + Assert.isTrue(enableGateway, "The 'hubId' requires the 'enableGateway' property to be true."); regionFactory.setGatewayHubId(hubId); } @@ -193,77 +195,6 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple return region; } - private boolean isDiskStoreConfigurationAllowed() { - boolean allow = (diskStoreName != null); - - allow &= (getDataPolicy().withPersistence() || (getAttributes() != null - && getAttributes().getEvictionAttributes() != null - && EvictionAction.OVERFLOW_TO_DISK.equals(attributes.getEvictionAttributes().getAction()))); - - return allow; - } - - /** - * Validates that the settings for Data Policy and the 'persistent' attribute in <gfe:*-region> elements - * are compatible. - * - * @param resolvedDataPolicy the GemFire Data Policy resolved form the Spring GemFire XML namespace configuration - * meta-data. - * @see #isPersistent() - * @see #isNotPersistent() - * @see com.gemstone.gemfire.cache.DataPolicy - */ - protected void assertDataPolicyAndPersistentAttributesAreCompatible(DataPolicy resolvedDataPolicy) { - if (resolvedDataPolicy.withPersistence()) { - Assert.isTrue(isPersistentUnspecified() || isPersistent(), String.format( - "Data Policy '%1$s' is invalid when persistent is false.", resolvedDataPolicy)); - } - else { - // NOTE otherwise, the Data Policy is not persistent, so... - Assert.isTrue(isPersistentUnspecified() || isNotPersistent(), String.format( - "Data Policy '%1$s' is invalid when persistent is true.", resolvedDataPolicy)); - } - } - - /** - * Determines whether the user explicitly set the 'persistent' attribute or not. - * - * @return a boolean value indicating whether the user explicitly set the 'persistent' attribute to true or false. - * @see #isPersistent() - * @see #isNotPersistent() - */ - protected boolean isPersistentUnspecified() { - return (persistent == null); - } - - /** - * Returns true when the user explicitly specified a value for the persistent attribute and it is true. If the - * persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined - * and will be determined by the Data Policy. - * - * @return true when the user specified an explicit value for the persistent attribute and it is true; - * false otherwise. - * @see #isNotPersistent() - * @see #isPersistentUnspecified() - */ - protected boolean isPersistent() { - return Boolean.TRUE.equals(persistent); - } - - /** - * Returns true when the user explicitly specified a value for the persistent attribute and it is false. If the - * persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined - * and will be determined by the Data Policy. - * - * @return true when the user specified an explicit value for the persistent attribute and it is false; - * false otherwise. - * @see #isPersistent() - * @see #isPersistentUnspecified() - */ - protected boolean isNotPersistent() { - return Boolean.FALSE.equals(persistent); - } - /** * Creates an instance of RegionFactory using the given Cache instance used to configure and construct the Region * created by this FactoryBean. @@ -291,7 +222,14 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple } /* - * (non-Javadoc) - this method is meant strictly to be overridden for testing purposes! + * (non-Javadoc) - This method should not be considered part of the RegionFactoryBean API + * and is strictly for testing purposes! + * + * NOTE cannot pass RegionAttributes.class as the "targetType" in the second invocation of getFieldValue(..) + * since the "regionAttributes" field is naively declared as a instance of the implementation class type + * (RegionAttributesImpl) rather than the interface type (RegionAttributes)... + * so much for 'programming to interfaces' in GemFire! + * * @see com.gemstone.gemfire.cache.RegionFactory#attrsFactory * @see com.gemstone.gemfire.cache.AttributesFactory#regionAttributes * @see com.gemstone.gemfire.cache.RegionAttributes#getDataPolicy @@ -299,16 +237,11 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple */ @SuppressWarnings({ "deprecation", "unchecked" }) DataPolicy getDataPolicy(final RegionFactory regionFactory) { - // NOTE cannot pass RegionAttributes.class as the "targetType" on the second invocation of getFieldValue(..) - // since the "regionAttributes" field is naively of the implementation class type rather than the interface - // type... so much for programming to interfaces. - return ((RegionAttributes) getFieldValue(getFieldValue(regionFactory, "attrsFactory", - com.gemstone.gemfire.cache.AttributesFactory.class), "regionAttributes", null)).getDataPolicy(); + return ((RegionAttributes) getFieldValue(getFieldValue(regionFactory, "attrsFactory", AttributesFactory.class), + "regionAttributes", null)).getDataPolicy(); } - /* - * (non-Javadoc) - */ + /* (non-Javadoc) */ @SuppressWarnings("unchecked") private T getFieldValue(final Object source, final String fieldName, final Class targetType) { Field field = ReflectionUtils.findField(source.getClass(), fieldName, targetType); @@ -330,7 +263,7 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple * @param regionAttributes the RegionAttributes containing the Region configuration settings to merge to the * RegionFactory. * @return the RegionFactory with the configuration settings of the RegionAttributes merged. - * @see #hasUserSpecifiedEvictionAttributes(com.gemstone.gemfire.cache.RegionAttributes) + * @see #isUserSpecifiedEvictionAttributes(com.gemstone.gemfire.cache.RegionAttributes) * @see #validateRegionAttributes(com.gemstone.gemfire.cache.RegionAttributes) * @see com.gemstone.gemfire.cache.RegionAttributes * @see com.gemstone.gemfire.cache.RegionFactory @@ -357,7 +290,7 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple regionFactory.setEntryTimeToLive(regionAttributes.getEntryTimeToLive()); // NOTE EvictionAttributes are created by certain RegionShortcuts; need the null check! - if (hasUserSpecifiedEvictionAttributes(regionAttributes)) { + if (isUserSpecifiedEvictionAttributes(regionAttributes)) { regionFactory.setEvictionAttributes(regionAttributes.getEvictionAttributes()); } @@ -381,7 +314,9 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple return regionFactory; } - protected void mergePartitionAttributes(final RegionFactory regionFactory, final RegionAttributes regionAttributes) { + protected void mergePartitionAttributes(final RegionFactory regionFactory, + final RegionAttributes regionAttributes) { + // NOTE PartitionAttributes are created by certain RegionShortcuts; need the null check since RegionAttributes // can technically return null! // NOTE most likely, the PartitionAttributes will never be null since the PartitionRegionFactoryBean always @@ -410,17 +345,9 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple } /* - * (non-Javadoc) - this method is meant strictly to be overridden for testing purposes! - * NOTE unfortunately, must resort to using a GemFire internal class, ugh! - * @see com.gemstone.gemfire.internal.cache.UserSpecifiedRegionAttributes#hasEvictionAttributes - */ - boolean hasUserSpecifiedEvictionAttributes(final RegionAttributes regionAttributes) { - return (regionAttributes instanceof UserSpecifiedRegionAttributes - && ((UserSpecifiedRegionAttributes) regionAttributes).hasEvictionAttributes()); - } - - /* - * (non-Javadoc) - this method is meant strictly to be overridden for testing purposes! + * (non-Javadoc) - This method should not be considered part of the RegionFactoryBean API + * and is strictly for testing purposes! + * * @see com.gemstone.gemfire.cache.AttributesFactory#validateAttributes(:RegionAttributes) */ @SuppressWarnings("deprecation") @@ -428,6 +355,90 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple com.gemstone.gemfire.cache.AttributesFactory.validateAttributes(regionAttributes); } + /* + * (non-Javadoc) - This method should not be considered part of the RegionFactoryBean API + * and is strictly for testing purposes! + * + * NOTE unfortunately, must resort to using a GemFire internal class, ugh! + * @see com.gemstone.gemfire.internal.cache.UserSpecifiedRegionAttributes#hasEvictionAttributes + */ + boolean isUserSpecifiedEvictionAttributes(final RegionAttributes regionAttributes) { + return (regionAttributes instanceof UserSpecifiedRegionAttributes + && ((UserSpecifiedRegionAttributes) regionAttributes).hasEvictionAttributes()); + } + + /* (non-Javadoc) */ + private boolean isDiskStoreConfigurationAllowed() { + boolean allow = (diskStoreName != null); + + allow &= (getDataPolicy().withPersistence() || (getAttributes() != null + && getAttributes().getEvictionAttributes() != null + && EvictionAction.OVERFLOW_TO_DISK.equals(attributes.getEvictionAttributes().getAction()))); + + return allow; + } + + /** + * Returns true when the user explicitly specified a value for the persistent attribute and it is true. If the + * persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined + * and will be determined by the Data Policy. + * + * @return true when the user specified an explicit value for the persistent attribute and it is true; + * false otherwise. + * @see #isNotPersistent() + * @see #isPersistentUnspecified() + */ + protected boolean isPersistent() { + return Boolean.TRUE.equals(persistent); + } + + /** + * Determines whether the user explicitly set the 'persistent' attribute or not. + * + * @return a boolean value indicating whether the user explicitly set the 'persistent' attribute to true or false. + * @see #isPersistent() + * @see #isNotPersistent() + */ + protected boolean isPersistentUnspecified() { + return (persistent == null); + } + + /** + * Returns true when the user explicitly specified a value for the persistent attribute and it is false. If the + * persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined + * and will be determined by the Data Policy. + * + * @return true when the user specified an explicit value for the persistent attribute and it is false; + * false otherwise. + * @see #isPersistent() + * @see #isPersistentUnspecified() + */ + protected boolean isNotPersistent() { + return Boolean.FALSE.equals(persistent); + } + + /** + * Validates that the settings for Data Policy and the 'persistent' attribute in <gfe:*-region> elements + * are compatible. + * + * @param resolvedDataPolicy the GemFire Data Policy resolved form the Spring GemFire XML namespace configuration + * meta-data. + * @see #isPersistent() + * @see #isNotPersistent() + * @see com.gemstone.gemfire.cache.DataPolicy + */ + protected void assertDataPolicyAndPersistentAttributesAreCompatible(DataPolicy resolvedDataPolicy) { + if (resolvedDataPolicy.withPersistence()) { + Assert.isTrue(isPersistentUnspecified() || isPersistent(), String.format( + "Data Policy '%1$s' is invalid when persistent is false.", resolvedDataPolicy)); + } + else { + // NOTE otherwise, the Data Policy is not persistent, so... + Assert.isTrue(isPersistentUnspecified() || isNotPersistent(), String.format( + "Data Policy '%1$s' is invalid when persistent is true.", resolvedDataPolicy)); + } + } + /** * Post-process the RegionFactory used to create the GemFire Region for this factory bean during the initialization * process. The RegionFactory is already configured and initialized by the factory bean before this method @@ -493,13 +504,22 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple setDataPolicy(resolvedDataPolicy); } else { - DataPolicy resolvedDataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.DEFAULT); + DataPolicy regionAttributesDataPolicy = getDataPolicy(getAttributes(), DataPolicy.DEFAULT); + DataPolicy resolvedDataPolicy = (isPersistent() && DataPolicy.DEFAULT.equals(regionAttributesDataPolicy) + ? DataPolicy.PERSISTENT_REPLICATE : regionAttributesDataPolicy); + + assertDataPolicyAndPersistentAttributesAreCompatible(resolvedDataPolicy); regionFactory.setDataPolicy(resolvedDataPolicy); setDataPolicy(resolvedDataPolicy); } } + /* (non-Javadoc) */ + private DataPolicy getDataPolicy(final RegionAttributes regionAttributes, final DataPolicy defaultDataPolicy) { + return (regionAttributes != null ? regionAttributes.getDataPolicy() : defaultDataPolicy); + } + @Override public void destroy() throws Exception { if (getRegion() != null) { @@ -620,8 +640,9 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple * @see #setDataPolicy(com.gemstone.gemfire.cache.DataPolicy) * @deprecated as of 1.4.0, use setDataPolicy(:DataPolicy) instead. */ + @Deprecated public void setDataPolicy(String dataPolicyName) { - this.dataPolicy = new DataPolicyConverter().convert(dataPolicyName); + setDataPolicy(new DataPolicyConverter().convert(dataPolicyName)); } /** @@ -677,13 +698,6 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple this.scope = scope; } - /* - * (non-Javadoc) - */ - protected final RegionShortcut getShortcut() { - return shortcut; - } - /** * Configures the Region with a RegionShortcut. * @@ -695,6 +709,11 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple this.shortcut = shortcut; } + /* (non-Javadoc) */ + protected final RegionShortcut getShortcut() { + return shortcut; + } + /** * Sets the snapshots used for loading a newly created region. That * is, the snapshot will be used only when a new region is created - @@ -723,6 +742,7 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple } } } + this.running = true; } diff --git a/src/test/java/org/springframework/data/gemfire/LocalRegionFactoryBeanTest.java b/src/test/java/org/springframework/data/gemfire/LocalRegionFactoryBeanTest.java index 00ce1aea..5c6e5662 100644 --- a/src/test/java/org/springframework/data/gemfire/LocalRegionFactoryBeanTest.java +++ b/src/test/java/org/springframework/data/gemfire/LocalRegionFactoryBeanTest.java @@ -35,12 +35,11 @@ import com.gemstone.gemfire.cache.RegionShortcut; * The PartitionedRegionFactoryBeanTest class is a test suite of test cases testing the component functionality * and correct behavior of the PartitionedRegionFactoryBean class. * - * * @author David Turanski * @author John Blum * @see org.mockito.Mockito * @see org.junit.Test - * @see org.springframework.data.gemfire.PartitionedRegionFactoryBean + * @see org.springframework.data.gemfire.LocalRegionFactoryBean * @since 1.3.x */ @SuppressWarnings("unchecked") @@ -83,8 +82,8 @@ public class LocalRegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { @Override protected void createRegionFactoryBeanConfigs() { - addRFBConfig(defaultConfig()); - addRFBConfig(invalidConfig()); + add(defaultConfig()); + add(invalidConfig()); } protected RegionFactory createMockRegionFactory() { diff --git a/src/test/java/org/springframework/data/gemfire/RegionFactoryBeanTest.java b/src/test/java/org/springframework/data/gemfire/RegionFactoryBeanTest.java index 43eaeda1..517ef3d5 100644 --- a/src/test/java/org/springframework/data/gemfire/RegionFactoryBeanTest.java +++ b/src/test/java/org/springframework/data/gemfire/RegionFactoryBeanTest.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.data.gemfire; import static org.junit.Assert.assertEquals; @@ -36,6 +37,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.junit.After; import org.junit.Test; import org.springframework.data.gemfire.support.AbstractRegionFactoryBeanTest; +import org.springframework.data.gemfire.test.support.ArrayUtils; import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.cache.CustomExpiry; @@ -82,13 +84,13 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { private RegionFactoryBeanConfig defaultConfig() { return new RegionFactoryBeanConfig(new RegionFactoryBean(), "default") { @Override - public void verify() { - Region region = regionFactoryBean.getRegion(); - assertEquals(DataPolicy.DEFAULT, region.getAttributes().getDataPolicy()); + public void configureRegionFactoryBean() { } @Override - public void configureRegionFactoryBean() { + public void verify() { + Region region = regionFactoryBean.getRegion(); + assertEquals(DataPolicy.DEFAULT, region.getAttributes().getDataPolicy()); } }; } @@ -97,14 +99,14 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { private RegionFactoryBeanConfig persistentConfig() { return new RegionFactoryBeanConfig(new RegionFactoryBean(), "persistent") { @Override - public void verify() { - Region region = regionFactoryBean.getRegion(); - assertEquals(DataPolicy.PERSISTENT_REPLICATE, region.getAttributes().getDataPolicy()); + public void configureRegionFactoryBean() { + regionFactoryBean.setPersistent(true); } @Override - public void configureRegionFactoryBean() { - regionFactoryBean.setPersistent(true); + public void verify() { + Region region = regionFactoryBean.getRegion(); + assertEquals(DataPolicy.PERSISTENT_REPLICATE, region.getAttributes().getDataPolicy()); } }; } @@ -129,14 +131,15 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { @Override protected void createRegionFactoryBeanConfigs() { - addRFBConfig(defaultConfig()); - addRFBConfig(persistentConfig()); - addRFBConfig(invalidPersistentConfig()); + add(defaultConfig()); + add(persistentConfig()); + add(invalidPersistentConfig()); } protected PartitionAttributes createPartitionAttributes(final String colocatedWith, final int localMaxMemory, - final long recoveryDelay, final int redundantCopies, final long startupRecoveryDelay, - final long totalMaxMemory, final int totalNumberOfBuckets) throws Exception { + final long recoveryDelay, final int redundantCopies, final long startupRecoveryDelay, + final long totalMaxMemory, final int totalNumberOfBuckets) throws Exception { + PartitionAttributesFactoryBean partitionAttributesFactoryBean = new PartitionAttributesFactoryBean(); partitionAttributesFactoryBean.setColocatedWith(colocatedWith); @@ -151,6 +154,12 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { return partitionAttributesFactoryBean.getObject(); } + protected RegionAttributes createMockRegionAttributes(final DataPolicy... dataPolicies) { + RegionAttributes mockRegionAttributes = mock(RegionAttributes.class); + when(mockRegionAttributes.getDataPolicy()).thenReturn(ArrayUtils.getFirst(DataPolicy.DEFAULT, dataPolicies)); + return mockRegionAttributes; + } + protected RegionFactory createMockRegionFactory() { return mock(RegionFactory.class); } @@ -189,7 +198,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { } @Test(expected = IllegalArgumentException.class) - public void testAssertPersistentDataPolicyWithNotPersistentAttribute() { + public void testAssertPersistentDataPolicyWithNonPersistentAttribute() { try { RegionFactoryBean factoryBean = new RegionFactoryBean(); factoryBean.setPersistent(false); @@ -202,21 +211,6 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { } } - @Test - public void testIsPersistentUnspecified() { - RegionFactoryBean factoryBean = new RegionFactoryBean(); - - assertTrue(factoryBean.isPersistentUnspecified()); - - factoryBean.setPersistent(false); - - assertFalse(factoryBean.isPersistentUnspecified()); - - factoryBean.setPersistent(true); - - assertFalse(factoryBean.isPersistentUnspecified()); - } - @Test public void testIsPersistent() { RegionFactoryBean factoryBean = new RegionFactoryBean(); @@ -232,6 +226,25 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { assertTrue(factoryBean.isPersistent()); } + @Test + public void testIsPersistentUnspecified() { + RegionFactoryBean factoryBean = new RegionFactoryBean(); + + assertTrue(factoryBean.isPersistentUnspecified()); + + factoryBean.setPersistent(false); + + assertFalse(factoryBean.isPersistentUnspecified()); + + factoryBean.setPersistent(true); + + assertFalse(factoryBean.isPersistentUnspecified()); + + factoryBean.setPersistent(null); + + assertTrue(factoryBean.isPersistentUnspecified()); + } + @Test public void testIsNotPersistent() { RegionFactoryBean factoryBean = new RegionFactoryBean(); @@ -250,6 +263,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { @Test public void testCreateRegionFactoryWithShortcut() { Cache mockCache = mock(Cache.class); + RegionAttributes mockRegionAttributes = mock(RegionAttributes.class); final RegionFactory mockRegionFactory = createMockRegionFactory(); @@ -284,31 +298,27 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { assertSame(mockRegionFactory, factoryBean.createRegionFactory(mockCache)); assertTrue(setDataPolicyCalled.get()); - verify(mockCache).createRegionFactory(eq(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW)); + verify(mockCache, times(1)).createRegionFactory(eq(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW)); } @Test public void testCreateRegionFactoryWithAttributes() { Cache mockCache = mock(Cache.class); + RegionAttributes mockRegionAttributes = mock(RegionAttributes.class); final RegionFactory mockRegionFactory = createMockRegionFactory(); when(mockCache.createRegionFactory(eq(mockRegionAttributes))).thenReturn(mockRegionFactory); - RegionFactoryBean factoryBean = new RegionFactoryBean() { - @Override - protected RegionFactory mergeRegionAttributes(RegionFactory regionFactory, RegionAttributes regionAttributes) { - return mockRegionFactory; - } - }; + RegionFactoryBean factoryBean = new RegionFactoryBean(); factoryBean.setAttributes(mockRegionAttributes); factoryBean.setShortcut(null); assertSame(mockRegionFactory, factoryBean.createRegionFactory(mockCache)); - verify(mockCache).createRegionFactory(eq(mockRegionAttributes)); + verify(mockCache, times(1)).createRegionFactory(eq(mockRegionAttributes)); } @Test @@ -319,12 +329,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { when(mockCache.createRegionFactory()).thenReturn(mockRegionFactory); - RegionFactoryBean factoryBean = new RegionFactoryBean() { - @Override - protected RegionFactory mergeRegionAttributes(RegionFactory regionFactory, RegionAttributes regionAttributes) { - return mockRegionFactory; - } - }; + RegionFactoryBean factoryBean = new RegionFactoryBean(); factoryBean.setAttributes(null); factoryBean.setShortcut(null); @@ -373,7 +378,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { when(mockRegionAttributes.getSubscriptionAttributes()).thenReturn(testSubscriptionAttributes); RegionFactoryBean factoryBean = new RegionFactoryBean() { - @Override boolean hasUserSpecifiedEvictionAttributes(final RegionAttributes regionAttributes) { + @Override boolean isUserSpecifiedEvictionAttributes(final RegionAttributes regionAttributes) { return true; } @@ -479,7 +484,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { when(mockRegionAttributes.getSubscriptionAttributes()).thenReturn(null); RegionFactoryBean factoryBean = new RegionFactoryBean() { - @Override boolean hasUserSpecifiedEvictionAttributes(final RegionAttributes regionAttributes) { + @Override boolean isUserSpecifiedEvictionAttributes(final RegionAttributes regionAttributes) { return false; } @@ -712,9 +717,9 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { factoryBean.setPersistent(true); factoryBean.resolveDataPolicy(mockRegionFactory, true, " "); } - catch (IllegalArgumentException e) { - assertEquals("Data Policy ' ' is invalid.", e.getMessage()); - throw e; + catch (IllegalArgumentException expected) { + assertEquals("Data Policy ' ' is invalid.", expected.getMessage()); + throw expected; } finally { verify(mockRegionFactory, never()).setDataPolicy(null); @@ -731,9 +736,9 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { factoryBean.setPersistent(true); factoryBean.resolveDataPolicy(mockRegionFactory, true, ""); } - catch (IllegalArgumentException e) { - assertEquals("Data Policy '' is invalid.", e.getMessage()); - throw e; + catch (IllegalArgumentException expected) { + assertEquals("Data Policy '' is invalid.", expected.getMessage()); + throw expected; } finally { verify(mockRegionFactory, never()).setDataPolicy(null); @@ -750,9 +755,9 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { factoryBean.setPersistent(true); factoryBean.resolveDataPolicy(mockRegionFactory, true, "CSV"); } - catch (IllegalArgumentException e) { - assertEquals("Data Policy 'CSV' is invalid.", e.getMessage()); - throw e; + catch (IllegalArgumentException expected) { + assertEquals("Data Policy 'CSV' is invalid.", expected.getMessage()); + throw expected; } finally { verify(mockRegionFactory, never()).setDataPolicy(null); @@ -784,9 +789,9 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { factoryBean.setPersistent(true); factoryBean.resolveDataPolicy(mockRegionFactory, true, "EMPTY"); } - catch (IllegalArgumentException e) { - assertEquals("Data Policy 'EMPTY' is invalid when persistent is true.", e.getMessage()); - throw e; + catch (IllegalArgumentException expected) { + assertEquals("Data Policy 'EMPTY' is invalid when persistent is true.", expected.getMessage()); + throw expected; } finally { verify(mockRegionFactory, never()).setDataPolicy(null); @@ -817,11 +822,10 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { try { factoryBean.setPersistent(false); factoryBean.resolveDataPolicy(mockRegionFactory, false, "PERSISTENT_PARTITION"); - fail("Setting the 'persistent' attribute to FALSE and 'Data Policy' to PERSISTENT_PARTITION should have thrown an IllegalArgumentException!"); } - catch (IllegalArgumentException e) { - assertEquals("Data Policy 'PERSISTENT_PARTITION' is invalid when persistent is false.", e.getMessage()); - throw e; + catch (IllegalArgumentException expected) { + assertEquals("Data Policy 'PERSISTENT_PARTITION' is invalid when persistent is false.", expected.getMessage()); + throw expected; } finally { verify(mockRegionFactory, never()).setDataPolicy(null); @@ -838,11 +842,12 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { try { factoryBean.setPersistent(true); factoryBean.resolveDataPolicy(mockRegionFactory, true, "PARTITION"); - fail("Setting the 'persistent' attribute to TRUE and 'Data Policy' to PARTITION should have thrown an IllegalArgumentException!"); + fail( + "Setting the 'persistent' attribute to TRUE and 'Data Policy' to PARTITION should have thrown an IllegalArgumentException!"); } - catch (IllegalArgumentException e) { - assertEquals("Data Policy 'PARTITION' is invalid when persistent is true.", e.getMessage()); - throw e; + catch (IllegalArgumentException expected) { + assertEquals("Data Policy 'PARTITION' is invalid when persistent is true.", expected.getMessage()); + throw expected; } finally { verify(mockRegionFactory, never()).setDataPolicy(null); @@ -869,9 +874,84 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { verify(mockRegionFactory).setDataPolicy(eq(DataPolicy.PERSISTENT_PARTITION)); } + @Test + public void testResolveDataPolicyWhenPersistentUnspecifiedAndRegionAttributesPreloadedDataPolicy() { + RegionFactory mockRegionFactory = createMockRegionFactory(); + factoryBean.setAttributes(createMockRegionAttributes(DataPolicy.PRELOADED)); + factoryBean.setDataPolicy((DataPolicy) null); + factoryBean.resolveDataPolicy(mockRegionFactory, null, (String) null); + verify(mockRegionFactory, times(1)).setDataPolicy(eq(DataPolicy.PRELOADED)); + assertEquals(DataPolicy.PRELOADED, factoryBean.getDataPolicy()); + } + + @Test + public void testResolveDataPolicyWhenNotPersistentAndRegionAttributesPartitionDataPolicy() { + RegionFactory mockRegionFactory = createMockRegionFactory(); + factoryBean.setAttributes(createMockRegionAttributes(DataPolicy.PARTITION)); + factoryBean.setDataPolicy((DataPolicy) null); + factoryBean.setPersistent(false); + factoryBean.resolveDataPolicy(mockRegionFactory, false, (String) null); + verify(mockRegionFactory, times(1)).setDataPolicy(eq(DataPolicy.PARTITION)); + assertEquals(DataPolicy.PARTITION, factoryBean.getDataPolicy()); + } + + @Test + public void testResolveDataPolicyWhenPersistentAndRegionAttributesPersistentPartitionDataPolicy() { + RegionFactory mockRegionFactory = createMockRegionFactory(); + factoryBean.setAttributes(createMockRegionAttributes(DataPolicy.PERSISTENT_PARTITION)); + factoryBean.setDataPolicy((DataPolicy) null); + factoryBean.setPersistent(true); + factoryBean.resolveDataPolicy(mockRegionFactory, true, (String) null); + verify(mockRegionFactory, times(1)).setDataPolicy(eq(DataPolicy.PERSISTENT_PARTITION)); + assertEquals(DataPolicy.PERSISTENT_PARTITION, factoryBean.getDataPolicy()); + } + + @Test(expected = IllegalArgumentException.class) + public void testResolveDataPolicyWhenNotPersistentAndRegionAttributesPersistentPartitionDataPolicy() { + RegionFactory mockRegionFactory = createMockRegionFactory(); + + try { + factoryBean.setAttributes(createMockRegionAttributes(DataPolicy.PERSISTENT_PARTITION)); + factoryBean.setPersistent(false); + factoryBean.resolveDataPolicy(mockRegionFactory, false, (String) null); + } + catch (IllegalArgumentException expected) { + assertEquals("Data Policy 'PERSISTENT_PARTITION' is invalid when persistent is false.", expected.getMessage()); + throw expected; + } + finally { + verify(mockRegionFactory, never()).setDataPolicy(null); + verify(mockRegionFactory, never()).setDataPolicy(eq(DataPolicy.DEFAULT)); + verify(mockRegionFactory, never()).setDataPolicy(eq(DataPolicy.PERSISTENT_PARTITION)); + verify(mockRegionFactory, never()).setDataPolicy(eq(DataPolicy.PERSISTENT_REPLICATE)); + } + } + + @Test(expected = IllegalArgumentException.class) + public void testResolveDataPolicyWhenPersistentAndRegionAttributesPartitionDataPolicy() { + RegionFactory mockRegionFactory = createMockRegionFactory(); + + try { + factoryBean.setAttributes(createMockRegionAttributes(DataPolicy.PARTITION)); + factoryBean.setPersistent(true); + factoryBean.resolveDataPolicy(mockRegionFactory, true, (String) null); + } + catch (IllegalArgumentException expected) { + assertEquals("Data Policy 'PARTITION' is invalid when persistent is true.", expected.getMessage()); + throw expected; + } + finally { + verify(mockRegionFactory, never()).setDataPolicy(null); + verify(mockRegionFactory, never()).setDataPolicy(eq(DataPolicy.DEFAULT)); + verify(mockRegionFactory, never()).setDataPolicy(eq(DataPolicy.PARTITION)); + verify(mockRegionFactory, never()).setDataPolicy(eq(DataPolicy.PERSISTENT_REPLICATE)); + } + } + @Test public void testResolveDataPolicyWhenPersistentUnspecifiedAndUnspecifiedDataPolicy() { RegionFactory mockRegionFactory = createMockRegionFactory(); + factoryBean.setAttributes(createMockRegionAttributes()); factoryBean.setPersistent(null); factoryBean.resolveDataPolicy(mockRegionFactory, null, (DataPolicy) null); verify(mockRegionFactory).setDataPolicy(eq(DataPolicy.DEFAULT)); @@ -880,6 +960,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { @Test public void testResolveDataPolicyWhenNotPersistentAndUnspecifiedDataPolicy() { RegionFactory mockRegionFactory = createMockRegionFactory(); + factoryBean.setAttributes(createMockRegionAttributes()); factoryBean.setPersistent(false); factoryBean.resolveDataPolicy(mockRegionFactory, false, (DataPolicy) null); verify(mockRegionFactory).setDataPolicy(eq(DataPolicy.DEFAULT)); @@ -888,6 +969,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { @Test public void testResolveDataPolicyWhenPersistentAndUnspecifiedDataPolicy() { RegionFactory mockRegionFactory = createMockRegionFactory(); + factoryBean.setAttributes(createMockRegionAttributes()); factoryBean.setPersistent(true); factoryBean.resolveDataPolicy(mockRegionFactory, true, (DataPolicy) null); verify(mockRegionFactory).setDataPolicy(eq(DataPolicy.PERSISTENT_REPLICATE)); @@ -916,9 +998,9 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { factoryBean.resolveDataPolicy(mockRegionFactory, false, DataPolicy.PERSISTENT_REPLICATE); fail("Setting the 'persistent' attribute to FALSE and 'Data Policy' to PERSISTENT_REPLICATE should have thrown an IllegalArgumentException!"); } - catch (IllegalArgumentException e) { - assertEquals("Data Policy 'PERSISTENT_REPLICATE' is invalid when persistent is false.", e.getMessage()); - throw e; + catch (IllegalArgumentException expected) { + assertEquals("Data Policy 'PERSISTENT_REPLICATE' is invalid when persistent is false.", expected.getMessage()); + throw expected; } finally { verify(mockRegionFactory, never()).setDataPolicy(null); @@ -937,9 +1019,9 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTest { factoryBean.resolveDataPolicy(mockRegionFactory, true, "REPLICATE"); fail("Setting the 'persistent' attribute to TRUE and 'Data Policy' to REPLICATE should have thrown an IllegalArgumentException!"); } - catch (IllegalArgumentException e) { - assertEquals("Data Policy 'REPLICATE' is invalid when persistent is true.", e.getMessage()); - throw e; + catch (IllegalArgumentException expected) { + assertEquals("Data Policy 'REPLICATE' is invalid when persistent is true.", expected.getMessage()); + throw expected; } finally { verify(mockRegionFactory, never()).setDataPolicy(null); diff --git a/src/test/java/org/springframework/data/gemfire/config/RegionDefinitionUsingBeansNamespaceTest.java b/src/test/java/org/springframework/data/gemfire/config/RegionDefinitionUsingBeansNamespaceTest.java new file mode 100644 index 00000000..53fc8fa4 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/config/RegionDefinitionUsingBeansNamespaceTest.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.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import javax.annotation.Resource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.gemstone.gemfire.cache.DataPolicy; +import com.gemstone.gemfire.cache.Region; + +/** + * The RawRegionBeanDefinitionTest class is a test suite of test cases testing the contract and functionality + * of the SDG RegionFactoryBean class, and specifically the specification of the GemFire Region DataPolicy, + * when used as raw bean definition in Spring XML configuration meta-data. + * + * @author John Blum + * @see org.springframework.data.gemfire.PartitionAttributesFactoryBean + * @see org.springframework.data.gemfire.RegionAttributesFactoryBean + * @see org.springframework.data.gemfire.RegionFactoryBean + * @see org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer + * @see org.springframework.test.context.ContextConfiguration + * @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner + * @see com.gemstone.gemfire.cache.DataPolicy + * @see com.gemstone.gemfire.cache.Region + * @since 1.6.0 + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(initializers = GemfireTestApplicationContextInitializer.class) +@SuppressWarnings("unused") +public class RegionDefinitionUsingBeansNamespaceTest { + + @Resource(name = "Example") + private Region example; + + @Test + public void testExampleRegionBeanDefinitionConfiguration() { + assertNotNull("The 'Example' Region was not properly configured and initialized!", example); + assertEquals("Example", example.getName()); + assertEquals("/Example", example.getFullPath()); + assertNotNull(example.getAttributes()); + assertEquals(DataPolicy.PERSISTENT_PARTITION, example.getAttributes().getDataPolicy()); + assertTrue(example.getAttributes().getStatisticsEnabled()); + assertNotNull(example.getAttributes().getPartitionAttributes()); + assertEquals(1, example.getAttributes().getPartitionAttributes().getRedundantCopies()); + assertEquals(0, example.getAttributes().getPartitionAttributes().getRecoveryDelay()); + } + +} diff --git a/src/test/java/org/springframework/data/gemfire/support/AbstractRegionFactoryBeanTest.java b/src/test/java/org/springframework/data/gemfire/support/AbstractRegionFactoryBeanTest.java index 49d3e9aa..e1d6b7bd 100644 --- a/src/test/java/org/springframework/data/gemfire/support/AbstractRegionFactoryBeanTest.java +++ b/src/test/java/org/springframework/data/gemfire/support/AbstractRegionFactoryBeanTest.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.data.gemfire.support; import java.io.File; @@ -31,33 +32,18 @@ import com.gemstone.gemfire.cache.GemFireCache; /** * @author David Turanski - * + * @author John Blum */ public abstract class AbstractRegionFactoryBeanTest { - protected GemFireCache cache; - Map regionFactoryBeanConfigs = new HashMap(); + private GemFireCache cache; - @Before - public void setUp() throws Exception { - - cache = new StubCache(); - } - - @Test - public void testAll() throws Exception { - createRegionFactoryBeanConfigs(); - for (RegionFactoryBeanConfig rfbc : regionFactoryBeanConfigs.values()) { - rfbc.test(); - } - } + private Map regionFactoryBeanConfigs = new HashMap(); @AfterClass public static void cleanUp() { for (String name : new File(".").list(new FilenameFilter() { - - @Override - public boolean accept(File dir, String name) { + @Override public boolean accept(File dir, String name) { return name.startsWith("BACKUP"); } })) { @@ -65,49 +51,69 @@ public abstract class AbstractRegionFactoryBeanTest { } } - protected void addRFBConfig(RegionFactoryBeanConfig rfbc) { - if (regionFactoryBeanConfigs.containsKey(rfbc.regionName)) { - throw new RuntimeException("duplicate region name " + rfbc.regionName); - } - regionFactoryBeanConfigs.put(rfbc.regionName, rfbc); + @Before + public void setUp() throws Exception { + cache = new StubCache(); } @After public void tearDown() { cache.close(); + cache = null; } + @Test + public void testAll() throws Exception { + createRegionFactoryBeanConfigs(); + + for (RegionFactoryBeanConfig regionFactoryBeanConfig : regionFactoryBeanConfigs.values()) { + regionFactoryBeanConfig.test(); + } + } + + protected void add(RegionFactoryBeanConfig regionFactoryBeanConfig) { + if (regionFactoryBeanConfigs.containsKey(regionFactoryBeanConfig.regionName)) { + throw new RuntimeException("duplicate region name " + regionFactoryBeanConfig.regionName); + } + + regionFactoryBeanConfigs.put(regionFactoryBeanConfig.regionName, regionFactoryBeanConfig); + } + + protected abstract void createRegionFactoryBeanConfigs(); + public abstract class RegionFactoryBeanConfig { + + public Exception exception; + @SuppressWarnings("rawtypes") public final RegionFactoryBean regionFactoryBean; public final String regionName; - public Exception exception; - @SuppressWarnings("rawtypes") - public RegionFactoryBeanConfig(RegionFactoryBean rfb, String regionName) { - this.regionFactoryBean = rfb; + public RegionFactoryBeanConfig(RegionFactoryBean regionFactoryBean, String regionName) { + this.regionFactoryBean = regionFactoryBean; this.regionName = regionName; - rfb.setBeanName(regionName); - rfb.setCache(cache); + regionFactoryBean.setBeanName(regionName); + regionFactoryBean.setCache(cache); } + public abstract void configureRegionFactoryBean(); + public void test() { configureRegionFactoryBean(); + try { regionFactoryBean.afterPropertiesSet(); } catch (Exception e) { this.exception = e; } + verify(); } - public abstract void configureRegionFactoryBean(); - public abstract void verify(); } - protected abstract void createRegionFactoryBeanConfigs(); } diff --git a/src/test/java/org/springframework/data/gemfire/test/MockRegionFactory.java b/src/test/java/org/springframework/data/gemfire/test/MockRegionFactory.java index 1f0d85d0..a02b09c6 100644 --- a/src/test/java/org/springframework/data/gemfire/test/MockRegionFactory.java +++ b/src/test/java/org/springframework/data/gemfire/test/MockRegionFactory.java @@ -21,9 +21,11 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.File; +import java.lang.reflect.Field; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import org.springframework.util.ReflectionUtils; import com.gemstone.gemfire.cache.CacheListener; import com.gemstone.gemfire.cache.CacheLoader; @@ -79,6 +81,10 @@ public class MockRegionFactory { final RegionFactory regionFactory = mock(RegionFactory.class); + Field attrsFactory = ReflectionUtils.findField(RegionFactory.class, "attrsFactory"); + ReflectionUtils.makeAccessible(attrsFactory); + ReflectionUtils.setField(attrsFactory, regionFactory, attributesFactory); + when(regionFactory.create(anyString())).thenAnswer(new Answer() { @Override public Region answer(InvocationOnMock invocation) throws Throwable { String name = (String) invocation.getArguments()[0]; diff --git a/src/test/java/org/springframework/data/gemfire/test/support/ArrayUtils.java b/src/test/java/org/springframework/data/gemfire/test/support/ArrayUtils.java new file mode 100644 index 00000000..fce0b8a3 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/test/support/ArrayUtils.java @@ -0,0 +1,44 @@ +/* + * 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.test.support; + +/** + * ArrayUtils is a utility class for working with Java arrays. + * + * @author John Blum + * @since 1.6.0 + */ +@SuppressWarnings("unused") +public class ArrayUtils { + + public static T getFirst(T... array) { + return getFirst(null, array); + } + + public static T getFirst(T defaultValue, T... array) { + return (isEmpty(array) ? defaultValue : array[0]); + } + + public static boolean isEmpty(final Object... array) { + return (array == null || array.length == 0); + } + + public static int length(final Object... array) { + return (array != null ? array.length : 0); + } + +} diff --git a/src/test/resources/org/springframework/data/gemfire/config/RegionDefinitionUsingBeansNamespaceTest-context.xml b/src/test/resources/org/springframework/data/gemfire/config/RegionDefinitionUsingBeansNamespaceTest-context.xml new file mode 100644 index 00000000..bbe8ec53 --- /dev/null +++ b/src/test/resources/org/springframework/data/gemfire/config/RegionDefinitionUsingBeansNamespaceTest-context.xml @@ -0,0 +1,34 @@ + + + + + RawRegionBeanDefinitionTest + 0 + warning + + + + + + + + + + + + + + +