Add generic GemFire findByIndexNameAndIndexValue support

Fixes gh-353
This commit is contained in:
John Blum
2016-02-03 23:04:20 -08:00
committed by Rob Winch
parent 7de11753a9
commit c2b407189e
13 changed files with 611 additions and 50 deletions

View File

@@ -43,6 +43,7 @@ import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.query.Index;
import com.gemstone.gemfire.cache.server.CacheServer;
/**
@@ -105,7 +106,7 @@ public class AbstractGemFireIntegrationTests {
}
/* (non-Javadoc) */
protected static List<String> createJavaProcessCommandLine(Class<? extends Object> type, String... args) {
protected static List<String> createJavaProcessCommandLine(Class<?> type, String... args) {
List<String> commandLine = new ArrayList<String>();
String javaHome = System.getProperty("java.home");
@@ -155,7 +156,7 @@ public class AbstractGemFireIntegrationTests {
}
/* (non-Javadoc) */
protected static Process run(Class<? extends Object> type, File directory, String... args) throws IOException {
protected static Process run(Class<?> type, File directory, String... args) throws IOException {
return new ProcessBuilder()
.command(createJavaProcessCommandLine(type, args))
.directory(directory)
@@ -318,6 +319,13 @@ public class AbstractGemFireIntegrationTests {
assertThat(actualRegion.getAttributes().getDataPolicy()).isEqualTo(expectedDataPolicy);
}
/* (non-Javadoc) */
protected void assertIndex(Index index, String expectedExpression, String expectedFromClause) {
assertThat(index).isNotNull();
assertThat(index.getIndexedExpression()).isEqualTo(expectedExpression);
assertThat(index.getFromClause()).isEqualTo(expectedFromClause);
}
/* (non-Javadoc) */
protected void assertEntryIdleTimeout(Region<?, ?> region, ExpirationAction expectedAction, int expectedTimeout) {
assertEntryIdleTimeout(region.getAttributes().getEntryIdleTimeout(), expectedAction, expectedTimeout);

View File

@@ -17,6 +17,7 @@
package org.springframework.session.data.gemfire;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME;
import static org.springframework.session.data.gemfire.GemFireOperationsSessionRepository.GemFireSession;
import java.util.Arrays;
@@ -72,11 +73,11 @@ import com.gemstone.gemfire.pdx.PdxWriter;
@ContextConfiguration
@WebAppConfiguration
public class GemFireOperationsSessionRepositoryIntegrationTests extends AbstractGemFireIntegrationTests {
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 300;
private static final String GEMFIRE_LOG_LEVEL = "warning";
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private static final String SPRING_SESSION_GEMFIRE_REGION_NAME = "TestPartitionedSessions";
SecurityContext context;
@@ -102,11 +103,15 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
assertEntryIdleTimeout(sessionRegion, ExpirationAction.INVALIDATE, MAX_INACTIVE_INTERVAL_IN_SECONDS);
}
protected Map<String, ExpiringSession> doFindByPrincipalName(String principalName) {
return gemfireSessionRepository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
protected Map<String, ExpiringSession> doFindByIndexNameAndIndexValue(String indexName, String indexValue) {
return gemfireSessionRepository.findByIndexNameAndIndexValue(indexName, indexValue);
}
@SuppressWarnings("unchecked")
protected Map<String, ExpiringSession> doFindByPrincipalName(String principalName) {
return doFindByIndexNameAndIndexValue(PRINCIPAL_NAME_INDEX_NAME, principalName);
}
@SuppressWarnings({ "unused", "unchecked" })
protected Map<String, ExpiringSession> doFindByPrincipalName(String regionName, String principalName) {
try {
Region<String, ExpiringSession> region = gemfireCache.getRegion(regionName);
@@ -115,7 +120,8 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
QueryService queryService = region.getRegionService().getQueryService();
String queryString = String.format("SELECT s FROM %1$s s WHERE s.principalName = $1", region.getFullPath());
String queryString = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
region.getFullPath());
Query query = queryService.newQuery(queryString);
@@ -140,6 +146,56 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
return true;
}
protected ExpiringSession setAttribute(ExpiringSession session, String attributeName, Object attributeValue) {
session.setAttribute(attributeName, attributeValue);
return session;
}
@Test
public void findSessionsByIndexedSessionAttributeNameValues() {
ExpiringSession johnBlumSession = save(touch(setAttribute(createSession("johnBlum"), "vip", "yes")));
ExpiringSession robWinchSession = save(touch(setAttribute(createSession("robWinch"), "vip", "yes")));
ExpiringSession jonDoeSession = save(touch(setAttribute(createSession("jonDoe"), "vip", "no")));
ExpiringSession pieDoeSession = save(touch(setAttribute(createSession("pieDoe"), "viper", "true")));
ExpiringSession sourDoeSession = save(touch(createSession("sourDoe")));
assertThat(get(johnBlumSession.getId())).isEqualTo(johnBlumSession);
assertThat(johnBlumSession.getAttribute("vip")).isEqualTo("yes");
assertThat(get(robWinchSession.getId())).isEqualTo(robWinchSession);
assertThat(robWinchSession.getAttribute("vip")).isEqualTo("yes");
assertThat(get(jonDoeSession.getId())).isEqualTo(jonDoeSession);
assertThat(jonDoeSession.getAttribute("vip")).isEqualTo("no");
assertThat(get(pieDoeSession.getId())).isEqualTo(pieDoeSession);
assertThat(pieDoeSession.getAttributeNames().contains("vip")).isFalse();
assertThat(get(sourDoeSession.getId())).isEqualTo(sourDoeSession);
assertThat(sourDoeSession.getAttributeNames().contains("vip")).isFalse();
Map<String, ExpiringSession> vipSessions = doFindByIndexNameAndIndexValue("vip", "yes");
assertThat(vipSessions).isNotNull();
assertThat(vipSessions.size()).isEqualTo(2);
assertThat(vipSessions.get(johnBlumSession.getId())).isEqualTo(johnBlumSession);
assertThat(vipSessions.get(robWinchSession.getId())).isEqualTo(robWinchSession);
assertThat(vipSessions.containsKey(jonDoeSession.getId()));
assertThat(vipSessions.containsKey(pieDoeSession.getId()));
assertThat(vipSessions.containsKey(sourDoeSession.getId()));
Map<String, ExpiringSession> nonVipSessions = doFindByIndexNameAndIndexValue("vip", "no");
assertThat(nonVipSessions).isNotNull();
assertThat(nonVipSessions.size()).isEqualTo(1);
assertThat(nonVipSessions.get(jonDoeSession.getId())).isEqualTo(jonDoeSession);
assertThat(nonVipSessions.containsKey(johnBlumSession.getId()));
assertThat(nonVipSessions.containsKey(robWinchSession.getId()));
assertThat(nonVipSessions.containsKey(pieDoeSession.getId()));
assertThat(nonVipSessions.containsKey(sourDoeSession.getId()));
Map<String, ExpiringSession> noSessions = doFindByIndexNameAndIndexValue("nonExistingAttribute", "test");
assertThat(noSessions).isNotNull();
assertThat(noSessions.isEmpty()).isTrue();
}
@Test
public void findSessionsByPrincipalName() {
ExpiringSession sessionOne = save(touch(createSession("robWinch")));
@@ -212,7 +268,7 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
}
@Test
public void doesNotFindAfterPrincipalRemoved() {
public void findsNoSessionsAfterPrincipalIsRemoved() {
String username = "doesNotFindAfterPrincipalRemoved";
ExpiringSession session = save(touch(createSession(username)));
session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, null);
@@ -271,6 +327,7 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME,
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
@SuppressWarnings("unused")
static class SpringSessionGemFireConfiguration {
@Bean
@@ -288,6 +345,7 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setLazyInitialize(false);
gemfireCache.setProperties(gemfireProperties());
gemfireCache.setUseBeanFactoryLocator(false);
@@ -296,7 +354,7 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
}
}
public static class Person implements PdxSerializable {
public static class Person implements Comparable<Person>, PdxSerializable {
private String firstName;
private String lastName;
@@ -336,6 +394,12 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
this.lastName = pdxReader.readString("lastName");
}
@SuppressWarnings("all")
public int compareTo(final Person person) {
int compareValue = getLastName().compareTo(person.getLastName());
return (compareValue != 0 ? compareValue : getFirstName().compareTo(person.getFirstName()));
}
@Override
public boolean equals(final Object obj) {
if (obj == this) {

View File

@@ -0,0 +1,130 @@
/*
* Copyright 2002-2015 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.session.data.gemfire.config.annotation.web.http;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Properties;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.session.ExpiringSession;
import org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests;
import org.springframework.session.data.gemfire.support.GemFireUtils;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.ExpirationAction;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionShortcut;
import com.gemstone.gemfire.cache.query.Index;
import com.gemstone.gemfire.cache.query.QueryService;
/**
* The GemFireHttpSessionJavaConfigurationTests class...
*
* @author John Blum
* @since 1.0.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@DirtiesContext
@WebAppConfiguration
public class GemFireHttpSessionJavaConfigurationTests extends AbstractGemFireIntegrationTests {
@Autowired
private Cache gemfireCache;
protected <K, V> Region<K, V> assertCacheAndRegion(Cache gemfireCache, String regionName, DataPolicy dataPolicy) {
assertThat(GemFireUtils.isPeer(gemfireCache)).isTrue();
Region<K, V> region = gemfireCache.getRegion(regionName);
assertRegion(region, regionName, dataPolicy);
return region;
}
@Test
public void gemfireCacheConfigurationIsValid() {
Region<Object, ExpiringSession> example = assertCacheAndRegion(gemfireCache, "Example",
DataPolicy.REPLICATE);
assertEntryIdleTimeout(example, ExpirationAction.INVALIDATE, 900);
}
@Test
public void verifyGemFireExampleCacheRegionPrincipalNameIndexWasCreatedSuccessfully() {
Region<Object, ExpiringSession> example = assertCacheAndRegion(gemfireCache, "Example",
DataPolicy.REPLICATE);
QueryService queryService = example.getRegionService().getQueryService();
assertThat(queryService).isNotNull();
Index principalNameIndex = queryService.getIndex(example, "principalNameIndex");
assertIndex(principalNameIndex, "principalName", example.getFullPath());
}
@Test
public void verifyGemFireExampleCacheRegionSessionAttributesIndexWasNotCreated() {
Region<Object, ExpiringSession> example = assertCacheAndRegion(gemfireCache, "Example",
DataPolicy.REPLICATE);
QueryService queryService = example.getRegionService().getQueryService();
assertThat(queryService).isNotNull();
Index sessionAttributesIndex = queryService.getIndex(example, "sessionAttributesIndex");
assertThat(sessionAttributesIndex).isNull();
}
@EnableGemFireHttpSession(indexableSessionAttributes = {}, maxInactiveIntervalInSeconds = 900,
regionName = "Example", serverRegionShortcut = RegionShortcut.REPLICATE)
public static class GemFireConfiguration {
@Bean
Properties gemfireProperties() {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", GemFireHttpSessionJavaConfigurationTests.class.getName());
gemfireProperties.setProperty("mcast-port", "0");
gemfireProperties.setProperty("log-level", "warning");
return gemfireProperties;
}
@Bean
CacheFactoryBean gemfireCache() {
CacheFactoryBean cacheFactory = new CacheFactoryBean();
cacheFactory.setClose(true);
cacheFactory.setProperties(gemfireProperties());
cacheFactory.setUseBeanFactoryLocator(false);
return cacheFactory;
}
}
}

View File

@@ -23,6 +23,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.session.ExpiringSession;
import org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests;
import org.springframework.session.data.gemfire.support.GemFireUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@@ -31,9 +32,11 @@ import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.ExpirationAction;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.query.Index;
import com.gemstone.gemfire.cache.query.QueryService;
/**
* The GemFireHttpSessionConfigurationXmlTests class is a test suite of test cases testing the configuration of
* The GemFireHttpSessionXmlConfigurationTests class is a test suite of test cases testing the configuration of
* Spring Session backed by GemFire using XML configuration meta-data.
*
* @author John Blum
@@ -48,19 +51,53 @@ import com.gemstone.gemfire.cache.Region;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class GemFireHttpSessionConfigurationXmlTests extends AbstractGemFireIntegrationTests {
public class GemFireHttpSessionXmlConfigurationTests extends AbstractGemFireIntegrationTests {
@Autowired
private Cache gemfireCache;
protected <K, V> Region<K, V> assertCacheAndRegion(Cache gemfireCache, String regionName, DataPolicy dataPolicy) {
assertThat(GemFireUtils.isPeer(gemfireCache)).isTrue();
Region<K, V> region = gemfireCache.getRegion(regionName);
assertRegion(region, regionName, dataPolicy);
return region;
}
@Test
public void gemfireCacheConfigurationIsValid() {
assertThat(gemfireCache).isNotNull();
Region<Object, ExpiringSession> example = assertCacheAndRegion(gemfireCache, "Example", DataPolicy.NORMAL);
Region<Object, ExpiringSession> example = gemfireCache.getRegion("Example");
assertRegion(example, "Example", DataPolicy.NORMAL);
assertEntryIdleTimeout(example, ExpirationAction.INVALIDATE, 3600);
}
@Test
public void verifyGemFireExampleCacheRegionPrincipalNameIndexWasCreatedSuccessfully() {
Region<Object, ExpiringSession> example = assertCacheAndRegion(gemfireCache, "Example", DataPolicy.NORMAL);
QueryService queryService = example.getRegionService().getQueryService();
assertThat(queryService).isNotNull();
Index principalNameIndex = queryService.getIndex(example, "principalNameIndex");
assertIndex(principalNameIndex, "principalName", example.getFullPath());
}
@Test
public void verifyGemFireExampleCacheRegionSessionAttributesIndexWasCreatedSuccessfully() {
Region<Object, ExpiringSession> example = assertCacheAndRegion(gemfireCache, "Example", DataPolicy.NORMAL);
QueryService queryService = example.getRegionService().getQueryService();
assertThat(queryService).isNotNull();
Index sessionAttributesIndex = queryService.getIndex(example, "sessionAttributesIndex");
assertIndex(sessionAttributesIndex, "s.attributes['one', 'two', 'three']",
String.format("%1$s s", example.getFullPath()));
}
}