/* * 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; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.sameInstance; import static org.junit.Assert.assertThat; import java.util.Properties; import org.apache.geode.cache.Cache; import org.apache.geode.cache.query.Index; import org.apache.geode.cache.query.IndexExistsException; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.Import; /** * The IndexConflictsIntegrationTest class... * * @author John Blum * @see org.junit.Test * @link https://jira.spring.io/browse/SGF-432 * @since 1.6.3 */ public class IndexConflictsIntegrationTest { protected void assertIndex(Index index, String expectedName, String expectedExpression, String expectedFromClause, IndexType expectedType) { assertThat(index, is(notNullValue())); assertThat(index.getName(), is(equalTo(expectedName))); assertThat(index.getIndexedExpression(), is(equalTo(expectedExpression))); assertThat(index.getFromClause(), is(equalTo(expectedFromClause))); assertThat(IndexType.valueOf(index.getType()), is(equalTo(expectedType))); } protected boolean close(ConfigurableApplicationContext applicationContext) { if (applicationContext != null) { applicationContext.close(); return !(applicationContext.isActive() || applicationContext.isRunning()); } return true; } @Before public void setup() { System.getProperties().remove("gemfire.cache.region.index.override"); assertThat(System.getProperties().containsKey("gemfire.cache.region.index.override"), is(false)); } @Test(expected = BeanCreationException.class) public void indexDefinitionConflictThrowsException() { ConfigurableApplicationContext applicationContext = null; try { applicationContext = new AnnotationConfigApplicationContext( IndexDefinitionConflictGemFireConfiguration.class); } catch (BeanCreationException expected) { assertThat(expected.getMessage(), containsString("Error creating bean with name 'customerIdentityIndex'" + " defined in org.springframework.data.gemfire.IndexConflictsIntegrationTest$IndexDefinitionConflictGemFireConfiguration:" + " Invocation of init method failed")); assertThat(expected.getCause(), is(instanceOf(GemfireIndexException.class))); assertThat(expected.getCause().getMessage(), containsString("An Index with a different name having the same definition" + " as this Index (customerIdentityIndex) already exists")); assertThat(expected.getCause().getCause(), is(instanceOf(IndexExistsException.class))); assertThat(expected.getCause().getCause().getMessage(), is(equalTo("Similar Index Exists"))); throw expected; } finally { assertThat(close(applicationContext), is(true)); } } @Test public void indexNameConflictOverridesExistingIndex() { ConfigurableApplicationContext applicationContext = null; try { applicationContext = new AnnotationConfigApplicationContext(IndexNameConflictGemFireConfiguration.class); assertThat(applicationContext.getBeansOfType(Index.class).size(), is(equalTo(2))); Cache gemfireCache = applicationContext.getBean("gemfireCache", Cache.class); assertThat(gemfireCache.getQueryService().getIndexes().size(), is(equalTo(1))); Index customerLastNameIndex = applicationContext.getBean("customerLastNameIndex", Index.class); assertIndex(customerLastNameIndex, IndexNameConflictGemFireConfiguration.INDEX_NAME, "lastName", "/Customers", IndexType.HASH); Index customerFirstNameIndex = applicationContext.getBean("customerFirstNameIndex", Index.class); assertIndex(customerFirstNameIndex, IndexNameConflictGemFireConfiguration.INDEX_NAME, "firstName", "/Customers", IndexType.FUNCTIONAL); assertThat(customerFirstNameIndex, is(not(sameInstance(customerLastNameIndex)))); assertThat(gemfireCache.getQueryService().getIndexes().iterator().next(), is(sameInstance(customerFirstNameIndex))); } finally { assertThat(close(applicationContext), is(true)); } } @Test public void indexNameConflictReturnsExistingIndex() { ConfigurableApplicationContext applicationContext = null; try { System.setProperty("gemfire.cache.region.index.override", Boolean.FALSE.toString()); assertThat(System.getProperty("gemfire.cache.region.index.override", "true"), is(equalTo(Boolean.FALSE.toString()))); applicationContext = new AnnotationConfigApplicationContext(IndexNameConflictGemFireConfiguration.class); assertThat(applicationContext.getBeansOfType(Index.class).size(), is(equalTo(2))); Cache gemfireCache = applicationContext.getBean("gemfireCache", Cache.class); assertThat(gemfireCache.getQueryService().getIndexes().size(), is(equalTo(1))); Index customerLastNameIndex = applicationContext.getBean("customerLastNameIndex", Index.class); assertIndex(customerLastNameIndex, IndexNameConflictGemFireConfiguration.INDEX_NAME, "lastName", "/Customers", IndexType.HASH); Index customerFirstNameIndex = applicationContext.getBean("customerFirstNameIndex", Index.class); assertIndex(customerFirstNameIndex, IndexNameConflictGemFireConfiguration.INDEX_NAME, "lastName", "/Customers", IndexType.HASH); assertThat(customerFirstNameIndex, is(sameInstance(customerLastNameIndex))); assertThat(gemfireCache.getQueryService().getIndexes().iterator().next(), is(sameInstance(customerLastNameIndex))); } finally { System.getProperties().remove("gemfire.cache.region.index.override"); if (applicationContext != null) { applicationContext.close(); } } } @Configuration @SuppressWarnings("unused") public static class BaseGemFireConfiguration { @Bean public Properties gemfireProperties() { Properties gemfireProperties = new Properties(); gemfireProperties.setProperty("name", IndexConflictsIntegrationTest.class.getSimpleName()); gemfireProperties.setProperty("mcast-port", "0"); gemfireProperties.setProperty("log-level", "warning"); return gemfireProperties; } @Bean public CacheFactoryBean gemfireCache() { CacheFactoryBean cacheFactoryBean = new CacheFactoryBean(); cacheFactoryBean.setProperties(gemfireProperties()); cacheFactoryBean.setUseBeanFactoryLocator(false); return cacheFactoryBean; } @Bean(name = "Customers") public ReplicatedRegionFactoryBean customersRegion(Cache gemfireCache) { ReplicatedRegionFactoryBean customersRegionFactory = new ReplicatedRegionFactoryBean(); customersRegionFactory.setCache(gemfireCache); customersRegionFactory.setName("Customers"); customersRegionFactory.setPersistent(false); return customersRegionFactory; } } @Configuration @Import(BaseGemFireConfiguration.class) @SuppressWarnings("unused") public static class IndexDefinitionConflictGemFireConfiguration { @Bean public IndexFactoryBean customerIdIndex(Cache gemfireCache) { IndexFactoryBean indexFactoryBean = new IndexFactoryBean(); indexFactoryBean.setCache(gemfireCache); indexFactoryBean.setExpression("id"); indexFactoryBean.setFrom("/Customers"); indexFactoryBean.setType(IndexType.PRIMARY_KEY); return indexFactoryBean; } @Bean @DependsOn("customerIdIndex") public IndexFactoryBean customerIdentityIndex(Cache gemfireCache) { IndexFactoryBean indexFactoryBean = new IndexFactoryBean(); indexFactoryBean.setCache(gemfireCache); indexFactoryBean.setExpression("id"); indexFactoryBean.setFrom("/Customers"); indexFactoryBean.setType(IndexType.PRIMARY_KEY); return indexFactoryBean; } } @Configuration @Import(BaseGemFireConfiguration.class) @SuppressWarnings("unused") public static class IndexNameConflictGemFireConfiguration { protected static final String INDEX_NAME = "CustomerNameIdx"; @Bean public PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() { return new PropertyPlaceholderConfigurer(); } @Bean public IndexFactoryBean customerLastNameIndex(Cache gemfireCache, @Value("${gemfire.cache.region.index.override:true}") boolean override) { IndexFactoryBean indexFactoryBean = new IndexFactoryBean(); indexFactoryBean.setCache(gemfireCache); indexFactoryBean.setExpression("lastName"); indexFactoryBean.setFrom("/Customers"); indexFactoryBean.setName(INDEX_NAME); indexFactoryBean.setOverride(override); indexFactoryBean.setType(IndexType.HASH); return indexFactoryBean; } @Bean @DependsOn("customerLastNameIndex") public IndexFactoryBean customerFirstNameIndex(Cache gemfireCache, @Value("${gemfire.cache.region.index.override:true}") boolean override) { IndexFactoryBean indexFactoryBean = new IndexFactoryBean(); indexFactoryBean.setCache(gemfireCache); indexFactoryBean.setExpression("firstName"); indexFactoryBean.setFrom("/Customers"); indexFactoryBean.setName(INDEX_NAME); indexFactoryBean.setOverride(override); indexFactoryBean.setType(IndexType.FUNCTIONAL); return indexFactoryBean; } } }