Improve GemFire SessionRepository, Session copy logic to avoid issues with delta propagation on updates

Fixes #gh-755

(cherry picked from commit dcc0c079817f733fea25b41003f9672689c4c4db)
Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
John Blum
2017-04-20 17:39:00 -07:00
parent 9b30726805
commit 25ded686ac
8 changed files with 571 additions and 217 deletions

View File

@@ -80,7 +80,7 @@ public abstract class AbstractGemFireIntegrationTests {
System.getProperty("spring.session.data.gemfire.log-file", "server.log"); System.getProperty("spring.session.data.gemfire.log-file", "server.log");
protected static final String GEMFIRE_LOG_LEVEL = protected static final String GEMFIRE_LOG_LEVEL =
System.getProperty("spring.session.data.gemfire.log-level", "warning"); System.getProperty("spring.session.data.gemfire.log-level", "error");
@Autowired @Autowired
protected Cache gemfireCache; protected Cache gemfireCache;
@@ -255,7 +255,7 @@ public abstract class AbstractGemFireIntegrationTests {
/* (non-Javadoc) */ /* (non-Javadoc) */
protected static int waitForProcessToStop(Process process, File directory, long duration) { protected static int waitForProcessToStop(Process process, File directory, long duration) {
final long timeout = (System.currentTimeMillis() + duration); long timeout = (System.currentTimeMillis() + duration);
try { try {
while (process.isAlive() && System.currentTimeMillis() < timeout) { while (process.isAlive() && System.currentTimeMillis() < timeout) {
@@ -279,7 +279,7 @@ public abstract class AbstractGemFireIntegrationTests {
/* (non-Javadoc) */ /* (non-Javadoc) */
@SuppressWarnings("all") @SuppressWarnings("all")
protected static boolean waitOnCondition(Condition condition, long duration) { protected static boolean waitOnCondition(Condition condition, long duration) {
final long timeout = (System.currentTimeMillis() + duration); long timeout = (System.currentTimeMillis() + duration);
try { try {
while (!condition.evaluate() && System.currentTimeMillis() < timeout) { while (!condition.evaluate() && System.currentTimeMillis() < timeout) {

View File

@@ -31,6 +31,7 @@ import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.Region; import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes; import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.client.ClientCache; import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass; import org.junit.AfterClass;
@@ -59,7 +60,7 @@ import org.springframework.session.events.SessionDeletedEvent;
import org.springframework.session.events.SessionExpiredEvent; import org.springframework.session.events.SessionExpiredEvent;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.util.FileSystemUtils; import org.springframework.util.FileSystemUtils;
import org.springframework.util.SocketUtils; import org.springframework.util.SocketUtils;
@@ -67,28 +68,30 @@ import org.springframework.util.SocketUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* The ClientServerGemFireOperationsSessionRepositoryIntegrationTests class is a test * Integration tests to test the functionality of GemFire-backed Spring Sessions using
* suite of test cases testing the functionality of GemFire-backed Spring Sessions using a * the GemFire client-server topology.
* GemFire client-server topology.
* *
* @author John Blum * @author John Blum
* @since 1.1.0 * @since 1.1.0
* @see org.junit.Test * @see org.junit.Test
* @see org.junit.runner.RunWith * @see org.junit.runner.RunWith
* @see org.springframework.context.ConfigurableApplicationContext
* @see org.springframework.session.ExpiringSession
* @see org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests * @see org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests
* @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession * @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration * @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
* @see org.springframework.test.annotation.DirtiesContext * @see org.springframework.test.annotation.DirtiesContext
* @see org.springframework.test.context.ContextConfiguration * @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner * @see org.springframework.test.context.junit4.SpringRunner
* @see org.springframework.test.context.web.WebAppConfiguration * @see org.springframework.test.context.web.WebAppConfiguration
* @see org.apache.geode.cache.Cache * @see org.apache.geode.cache.Cache
* @see org.apache.geode.cache.client.ClientCache * @see org.apache.geode.cache.client.ClientCache
* @see org.apache.geode.cache.client.Pool * @see org.apache.geode.cache.client.Pool
* @see org.apache.geode.cache.server.CacheServer * @see org.apache.geode.cache.server.CacheServer
*/ */
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringRunner.class)
@ContextConfiguration(classes = ClientServerGemFireOperationsSessionRepositoryIntegrationTests.SpringSessionGemFireClientConfiguration.class) @ContextConfiguration(classes =
ClientServerGemFireOperationsSessionRepositoryIntegrationTests.SpringSessionDataGemFireClientConfiguration.class)
@DirtiesContext @DirtiesContext
@WebAppConfiguration @WebAppConfiguration
public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
@@ -109,24 +112,25 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
@BeforeClass @BeforeClass
public static void startGemFireServer() throws IOException { public static void startGemFireServer() throws IOException {
final long t0 = System.currentTimeMillis(); long t0 = System.currentTimeMillis();
final int port = SocketUtils.findAvailableTcpPort(); int port = SocketUtils.findAvailableTcpPort();
System.err.printf("Starting a GemFire Server on [%1$s] listening on port [%2$d]%n", System.err.printf("Starting a GemFire Server running on host [%1$s] listening on port [%2$d]%n",
SpringSessionGemFireServerConfiguration.SERVER_HOSTNAME, port); SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port);
System.setProperty("spring.session.data.gemfire.port", String.valueOf(port)); System.setProperty("spring.session.data.gemfire.port", String.valueOf(port));
String processWorkingDirectoryPathname = String.format("gemfire-client-server-tests-%1$s", String processWorkingDirectoryPathname =
TIMESTAMP.format(new Date())); String.format("gemfire-client-server-tests-%1$s", TIMESTAMP.format(new Date()));
processWorkingDirectory = createDirectory(processWorkingDirectoryPathname); processWorkingDirectory = createDirectory(processWorkingDirectoryPathname);
gemfireServer = run(SpringSessionGemFireServerConfiguration.class, processWorkingDirectory, gemfireServer = run(SpringSessionDataGemFireServerConfiguration.class, processWorkingDirectory,
String.format("-Dspring.session.data.gemfire.port=%1$d", port)); String.format("-Dspring.session.data.gemfire.port=%1$d", port));
assertThat(waitForCacheServerToStart(SpringSessionGemFireServerConfiguration.SERVER_HOSTNAME, port)).isTrue(); assertThat(waitForCacheServerToStart(SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port))
.isTrue();
System.err.printf("GemFire Server [startup time = %1$d ms]%n", System.currentTimeMillis() - t0); System.err.printf("GemFire Server [startup time = %1$d ms]%n", System.currentTimeMillis() - t0);
} }
@@ -134,7 +138,7 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
@AfterClass @AfterClass
public static void stopGemFireServerAndDeleteArtifacts() { public static void stopGemFireServerAndDeleteArtifacts() {
if (gemfireServer != null) { if (gemfireServer != null) {
gemfireServer.destroyForcibly(); gemfireServer.destroy();
System.err.printf("GemFire Server [exit code = %1$d]%n", System.err.printf("GemFire Server [exit code = %1$d]%n",
waitForProcessToStop(gemfireServer, processWorkingDirectory)); waitForProcessToStop(gemfireServer, processWorkingDirectory));
} }
@@ -159,7 +163,7 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
springSessionGemFireRegion.getAttributes(); springSessionGemFireRegion.getAttributes();
assertThat(springSessionGemFireRegionAttributes).isNotNull(); assertThat(springSessionGemFireRegionAttributes).isNotNull();
assertThat(springSessionGemFireRegionAttributes.getDataPolicy()).isEqualTo(DataPolicy.EMPTY); assertThat(springSessionGemFireRegionAttributes.getDataPolicy()).isEqualTo(DataPolicy.NORMAL);
} }
@After @After
@@ -169,7 +173,7 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
@Test @Test
public void createSessionFiresSessionCreatedEvent() { public void createSessionFiresSessionCreatedEvent() {
final long beforeOrAtCreationTime = System.currentTimeMillis(); long beforeOrAtCreationTime = System.currentTimeMillis();
ExpiringSession expectedSession = save(createSession()); ExpiringSession expectedSession = save(createSession());
@@ -179,12 +183,19 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
ExpiringSession createdSession = sessionEvent.getSession(); ExpiringSession createdSession = sessionEvent.getSession();
assertThat(createdSession).isEqualTo(expectedSession); assertThat(createdSession.getId()).isEqualTo(expectedSession.getId());
assertThat(createdSession.getId()).isNotNull();
assertThat(createdSession.getCreationTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime); assertThat(createdSession.getCreationTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime);
assertThat(createdSession.getLastAccessedTime()).isEqualTo(createdSession.getCreationTime()); assertThat(createdSession.getLastAccessedTime()).isEqualTo(createdSession.getCreationTime());
assertThat(createdSession.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS); assertThat(createdSession.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
createdSession.setAttribute("attrOne", 1);
assertThat(save(touch(createdSession)).getAttribute("attrOne")).isEqualTo(1);
sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
assertThat(sessionEvent).isNull();
this.gemfireSessionRepository.delete(expectedSession.getId()); this.gemfireSessionRepository.delete(expectedSession.getId());
} }
@@ -195,19 +206,13 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
AbstractSessionEvent sessionEvent = this.sessionEventListener.waitForSessionEvent(500); AbstractSessionEvent sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
assertThat(sessionEvent).isInstanceOf(SessionCreatedEvent.class); assertThat(sessionEvent).isInstanceOf(SessionCreatedEvent.class);
assertThat(sessionEvent.<ExpiringSession>getSession()).isEqualTo(expectedSession); assertThat(sessionEvent.getSession()).isEqualTo(expectedSession);
assertThat(this.sessionEventListener.getSessionEvent()).isNull(); assertThat(this.sessionEventListener.getSessionEvent()).isNull();
ExpiringSession savedSession = this.gemfireSessionRepository.getSession(expectedSession.getId()); ExpiringSession savedSession = this.gemfireSessionRepository.getSession(expectedSession.getId());
assertThat(savedSession).isEqualTo(expectedSession); assertThat(savedSession).isEqualTo(expectedSession);
// NOTE for some reason or another, performing a GemFire (Client)Cache
// Region.get(key)
// causes a Region CREATE event... o.O
// calling sessionEventListener.getSessionEvent() here to clear the event
this.sessionEventListener.getSessionEvent();
sessionEvent = this.sessionEventListener.waitForSessionEvent( sessionEvent = this.sessionEventListener.waitForSessionEvent(
TimeUnit.SECONDS.toMillis(MAX_INACTIVE_INTERVAL_IN_SECONDS + 1)); TimeUnit.SECONDS.toMillis(MAX_INACTIVE_INTERVAL_IN_SECONDS + 1));
@@ -241,11 +246,12 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
} }
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME, @EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME,
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS) clientRegionShortcut = ClientRegionShortcut.CACHING_PROXY,
static class SpringSessionGemFireClientConfiguration { maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
static class SpringSessionDataGemFireClientConfiguration {
@Bean @Bean
static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() { static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer(); return new PropertySourcesPlaceholderConfigurer();
} }
@@ -271,17 +277,14 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
PoolFactoryBean poolFactory = new PoolFactoryBean(); PoolFactoryBean poolFactory = new PoolFactoryBean();
poolFactory.setFreeConnectionTimeout(5000); // 5 seconds
poolFactory.setKeepAlive(false); poolFactory.setKeepAlive(false);
poolFactory.setMaxConnections(SpringSessionGemFireServerConfiguration.MAX_CONNECTIONS);
poolFactory.setPingInterval(TimeUnit.SECONDS.toMillis(5)); poolFactory.setPingInterval(TimeUnit.SECONDS.toMillis(5));
poolFactory.setReadTimeout(2000); // 2 seconds poolFactory.setReadTimeout(2000); // 2 seconds
poolFactory.setRetryAttempts(1); poolFactory.setRetryAttempts(1);
poolFactory.setSubscriptionEnabled(true); poolFactory.setSubscriptionEnabled(true);
poolFactory.setThreadLocalConnections(false);
poolFactory.setServers(Collections.singletonList(new ConnectionEndpoint( poolFactory.setServers(Collections.singletonList(new ConnectionEndpoint(
SpringSessionGemFireServerConfiguration.SERVER_HOSTNAME, port))); SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port)));
return poolFactory; return poolFactory;
} }
@@ -293,9 +296,9 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
// used for debugging purposes // used for debugging purposes
@SuppressWarnings("resource") @SuppressWarnings("resource")
public static void main(final String[] args) { public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = ConfigurableApplicationContext applicationContext = new AnnotationConfigApplicationContext(
new AnnotationConfigApplicationContext(SpringSessionGemFireClientConfiguration.class); SpringSessionDataGemFireClientConfiguration.class);
applicationContext.registerShutdownHook(); applicationContext.registerShutdownHook();
@@ -310,30 +313,27 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME, @EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME,
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS) maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
static class SpringSessionGemFireServerConfiguration { static class SpringSessionDataGemFireServerConfiguration {
static final int MAX_CONNECTIONS = 50;
static final String SERVER_HOSTNAME = "localhost"; static final String SERVER_HOSTNAME = "localhost";
@Bean @Bean
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer(); return new PropertySourcesPlaceholderConfigurer();
} }
@Bean
Properties gemfireProperties() { Properties gemfireProperties() {
Properties gemfireProperties = new Properties(); Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", name()); gemfireProperties.setProperty("name", name());
gemfireProperties.setProperty("mcast-port", "0"); gemfireProperties.setProperty("mcast-port", "0");
gemfireProperties.setProperty("log-file", "server.log");
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL); gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
return gemfireProperties; return gemfireProperties;
} }
String name() { String name() {
return SpringSessionGemFireServerConfiguration.class.getName(); return SpringSessionDataGemFireServerConfiguration.class.getName();
} }
@Bean @Bean
@@ -352,20 +352,21 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
CacheServerFactoryBean cacheServerFactory = new CacheServerFactoryBean(); CacheServerFactoryBean cacheServerFactory = new CacheServerFactoryBean();
cacheServerFactory.setCache(gemfireCache);
cacheServerFactory.setAutoStartup(true); cacheServerFactory.setAutoStartup(true);
cacheServerFactory.setBindAddress(SERVER_HOSTNAME); cacheServerFactory.setBindAddress(SERVER_HOSTNAME);
cacheServerFactory.setCache(gemfireCache);
cacheServerFactory.setMaxConnections(MAX_CONNECTIONS);
cacheServerFactory.setPort(port); cacheServerFactory.setPort(port);
return cacheServerFactory; return cacheServerFactory;
} }
@SuppressWarnings("resource") @SuppressWarnings("resource")
public static void main(final String[] args) throws IOException { public static void main(String[] args) throws IOException {
AnnotationConfigApplicationContext context = AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(SpringSessionGemFireServerConfiguration.class); new AnnotationConfigApplicationContext(SpringSessionDataGemFireServerConfiguration.class);
context.registerShutdownHook(); context.registerShutdownHook();
writeProcessControlFile(WORKING_DIRECTORY); writeProcessControlFile(WORKING_DIRECTORY);
} }
} }

View File

@@ -0,0 +1,285 @@
/*
* Copyright 2014-2016 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;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.client.ClientCache;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
import org.springframework.data.gemfire.client.PoolFactoryBean;
import org.springframework.data.gemfire.server.CacheServerFactoryBean;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
import org.springframework.session.ExpiringSession;
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.SocketUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests testing the addition/removal of HTTP Session Attributes
* and the proper persistence of the HTTP Session state in a GemFire cache
* across a client/server topology.
*
* @author John Blum
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.springframework.context.ConfigurableApplicationContext
* @see org.springframework.session.ExpiringSession
* @see org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests
* @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringRunner
* @see org.apache.geode.cache.Cache
* @see org.apache.geode.cache.Region
* @see org.apache.geode.cache.client.ClientCache
* @since 1.3.1
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes =
ClientServerHttpSessionAttributesDeltaIntegrationTests.SpringSessionDataGemFireClientConfiguration.class)
public class ClientServerHttpSessionAttributesDeltaIntegrationTests extends AbstractGemFireIntegrationTests {
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 1;
private static final DateFormat TIMESTAMP = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
private static File processWorkingDirectory;
private static Process gemfireServer;
@BeforeClass
public static void startGemFireServer() throws IOException {
long t0 = System.currentTimeMillis();
int port = SocketUtils.findAvailableTcpPort();
System.err.printf("Starting a GemFire Server running on host [%1$s] listening on port [%2$d]%n",
SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port);
System.setProperty("spring.session.data.gemfire.port", String.valueOf(port));
String processWorkingDirectoryPathname =
String.format("gemfire-client-server-tests-%1$s", TIMESTAMP.format(new Date()));
processWorkingDirectory = createDirectory(processWorkingDirectoryPathname);
gemfireServer = run(SpringSessionDataGemFireServerConfiguration.class, processWorkingDirectory,
String.format("-Dspring.session.data.gemfire.port=%1$d", port));
assertThat(waitForCacheServerToStart(SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port))
.isTrue();
System.err.printf("GemFire Server [startup time = %1$d ms]%n", System.currentTimeMillis() - t0);
}
@AfterClass
public static void stopGemFireServerAndDeleteArtifacts() {
if (gemfireServer != null) {
gemfireServer.destroy();
System.err.printf("GemFire Server [exit code = %1$d]%n",
waitForProcessToStop(gemfireServer, processWorkingDirectory));
}
if (Boolean.valueOf(System.getProperty("spring.session.data.gemfire.fork.clean", Boolean.TRUE.toString()))) {
FileSystemUtils.deleteRecursively(processWorkingDirectory);
}
assertThat(waitForClientCacheToClose(DEFAULT_WAIT_DURATION)).isTrue();
}
@Test
public void sessionCreationAndAccessIsSuccessful() {
ExpiringSession session = save(touch(createSession()));
assertThat(session).isNotNull();
assertThat(session.isExpired()).isFalse();
session.setAttribute("attrOne", 1);
session.setAttribute("attrTwo", 2);
save(touch(session));
ExpiringSession loadedSession = get(session.getId());
assertThat(loadedSession).isNotNull();
assertThat(loadedSession.isExpired()).isFalse();
assertThat(loadedSession).isNotSameAs(session);
assertThat(loadedSession.getId()).isEqualTo(session.getId());
assertThat(loadedSession.<Integer>getAttribute("attrOne")).isEqualTo(1);
assertThat(loadedSession.<Integer>getAttribute("attrTwo")).isEqualTo(2);
loadedSession.removeAttribute("attrTwo");
assertThat(loadedSession.getAttributeNames()).doesNotContain("attrTwo");
assertThat(loadedSession.getAttributeNames()).hasSize(1);
save(touch(loadedSession));
ExpiringSession reloadedSession = get(loadedSession.getId());
assertThat(reloadedSession).isNotNull();
assertThat(reloadedSession.isExpired()).isFalse();
assertThat(reloadedSession).isNotSameAs(loadedSession);
assertThat(reloadedSession.getId()).isEqualTo(loadedSession.getId());
assertThat(reloadedSession.getAttributeNames()).hasSize(1);
assertThat(reloadedSession.getAttributeNames()).doesNotContain("attrTwo");
assertThat(reloadedSession.<Integer>getAttribute("attrOne")).isEqualTo(1);
}
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
static class SpringSessionDataGemFireClientConfiguration {
@Bean
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Properties gemfireProperties() {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
return gemfireProperties;
}
@Bean
ClientCacheFactoryBean gemfireCache() {
ClientCacheFactoryBean clientCacheFactory = new ClientCacheFactoryBean();
clientCacheFactory.setClose(true);
clientCacheFactory.setProperties(gemfireProperties());
return clientCacheFactory;
}
@Bean
PoolFactoryBean gemfirePool(@Value("${spring.session.data.gemfire.port:"
+ DEFAULT_GEMFIRE_SERVER_PORT + "}") int port) {
PoolFactoryBean poolFactory = new PoolFactoryBean();
poolFactory.setKeepAlive(false);
poolFactory.setPingInterval(TimeUnit.SECONDS.toMillis(5));
poolFactory.setReadTimeout(2000); // 2 seconds
poolFactory.setRetryAttempts(1);
poolFactory.setSubscriptionEnabled(true);
poolFactory.setServers(Collections.singletonList(new ConnectionEndpoint(
SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port)));
return poolFactory;
}
// used for debugging purposes
@SuppressWarnings("resource")
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext =
new AnnotationConfigApplicationContext(SpringSessionDataGemFireClientConfiguration.class);
applicationContext.registerShutdownHook();
ClientCache clientCache = applicationContext.getBean(ClientCache.class);
for (InetSocketAddress server : clientCache.getCurrentServers()) {
System.err.printf("GemFire Server [host: %1$s, port: %2$d]%n",
server.getHostName(), server.getPort());
}
}
}
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
static class SpringSessionDataGemFireServerConfiguration {
static final String SERVER_HOSTNAME = "localhost";
@Bean
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Properties gemfireProperties() {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", name());
gemfireProperties.setProperty("mcast-port", "0");
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
return gemfireProperties;
}
String name() {
return SpringSessionDataGemFireServerConfiguration.class.getName();
}
@Bean
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setProperties(gemfireProperties());
return gemfireCache;
}
@Bean
CacheServerFactoryBean gemfireCacheServer(Cache gemfireCache,
@Value("${spring.session.data.gemfire.port:" + DEFAULT_GEMFIRE_SERVER_PORT + "}") int port) {
CacheServerFactoryBean cacheServerFactory = new CacheServerFactoryBean();
cacheServerFactory.setCache(gemfireCache);
cacheServerFactory.setAutoStartup(true);
cacheServerFactory.setBindAddress(SERVER_HOSTNAME);
cacheServerFactory.setPort(port);
return cacheServerFactory;
}
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(SpringSessionDataGemFireServerConfiguration.class);
context.registerShutdownHook();
writeProcessControlFile(WORKING_DIRECTORY);
}
}
}

View File

@@ -276,6 +276,19 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
handleExpired(event.getKey().toString(), toExpiringSession(event.getOldValue())); handleExpired(event.getKey().toString(), toExpiringSession(event.getOldValue()));
} }
/**
* Deletes the given {@link Session} from GemFire.
*
* @param session {@link Session} to delete.
* @return {@literal null}.
* @see org.springframework.session.Session
* @see #delete(String)
*/
protected ExpiringSession delete(Session session) {
delete(session.getId());
return null;
}
/** /**
* Causes Session created events to be published to the Spring application context. * Causes Session created events to be published to the Spring application context.
* *
@@ -344,10 +357,23 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
getApplicationEventPublisher().publishEvent(event); getApplicationEventPublisher().publishEvent(event);
} }
catch (Throwable t) { catch (Throwable t) {
this.logger.error(String.format("error occurred publishing event (%1$s)", event), t); this.logger.error(String.format("Error occurred publishing event [%s]", event), t);
} }
} }
/**
* Updates the {@link ExpiringSession#setLastAccessedTime(long)} property of the {@link ExpiringSession}.
*
* @param <T> {@link Class} sub-type of the {@link ExpiringSession}.
* @param expiringSession {@link ExpiringSession} to touch.
* @return the {@link ExpiringSession}.
* @see org.springframework.session.ExpiringSession#setLastAccessedTime(long)
*/
protected <T extends ExpiringSession> T touch(T expiringSession) {
expiringSession.setLastAccessedTime(System.currentTimeMillis());
return expiringSession;
}
/** /**
* GemFireSession is a GemFire representation model of a Spring {@link ExpiringSession} * GemFireSession is a GemFire representation model of a Spring {@link ExpiringSession}
* that stores and manages Session state information in GemFire. This class implements * that stores and manages Session state information in GemFire. This class implements
@@ -407,11 +433,13 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
return session; return session;
} }
public static GemFireSession copy(ExpiringSession session) {
return new GemFireSession(session);
}
/* (non-Javadoc) */ /* (non-Javadoc) */
public static GemFireSession from(ExpiringSession expiringSession) { public static GemFireSession from(ExpiringSession session) {
GemFireSession session = new GemFireSession(expiringSession); return (session instanceof GemFireSession ? (GemFireSession) session : copy(session));
session.setLastAccessedTime(System.currentTimeMillis());
return session;
} }
/* (non-Javadoc) */ /* (non-Javadoc) */

View File

@@ -122,15 +122,12 @@ public class GemFireOperationsSessionRepository extends AbstractGemFireOperation
ExpiringSession storedSession = getTemplate().get(sessionId); ExpiringSession storedSession = getTemplate().get(sessionId);
if (storedSession != null) { if (storedSession != null) {
if (storedSession.isExpired()) { storedSession = storedSession.isExpired()
delete(storedSession.getId()); ? delete(storedSession)
} : touch(GemFireSession.from(storedSession));
else {
return GemFireSession.from(storedSession);
}
} }
return null; return storedSession;
} }
/** /**
@@ -141,7 +138,7 @@ public class GemFireOperationsSessionRepository extends AbstractGemFireOperation
* @see org.springframework.session.ExpiringSession * @see org.springframework.session.ExpiringSession
*/ */
public void save(ExpiringSession session) { public void save(ExpiringSession session) {
getTemplate().put(session.getId(), new GemFireSession(session)); getTemplate().put(session.getId(), GemFireSession.from(session));
} }
/** /**

View File

@@ -101,7 +101,7 @@ import org.springframework.context.annotation.Import;
* *
* @author John Blum * @author John Blum
* @see org.springframework.session.config.annotation.web.http.EnableSpringHttpSession * @see org.springframework.session.config.annotation.web.http.EnableSpringHttpSession
* @see GemFireHttpSessionConfiguration * @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
* @since 1.1.0 * @since 1.1.0
*/ */
@Documented @Documented

View File

@@ -32,14 +32,13 @@ import java.util.concurrent.TimeUnit;
import edu.umd.cs.mtc.MultithreadedTestCase; import edu.umd.cs.mtc.MultithreadedTestCase;
import edu.umd.cs.mtc.TestFramework; import edu.umd.cs.mtc.TestFramework;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.geode.cache.AttributesMutator; import org.apache.geode.cache.AttributesMutator;
import org.apache.geode.cache.EntryEvent; import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.Region; import org.apache.geode.cache.Region;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock; import org.mockito.invocation.InvocationOnMock;
@@ -70,14 +69,17 @@ import static org.mockito.ArgumentMatchers.same;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willAnswer; import static org.mockito.BDDMockito.willAnswer;
import static org.mockito.BDDMockito.willThrow; import static org.mockito.BDDMockito.willThrow;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset; import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
/** /**
* Unit tests for {@link AbstractGemFireOperationsSessionRepository} class. * Unit tests for {@link AbstractGemFireOperationsSessionRepository}.
* *
* @author John Blum * @author John Blum
* @since 1.1.0 * @since 1.1.0
@@ -88,6 +90,7 @@ import static org.mockito.Mockito.verify;
* @see org.mockito.Mock * @see org.mockito.Mock
* @see org.mockito.Mockito * @see org.mockito.Mockito
* @see org.mockito.junit.MockitoJUnitRunner * @see org.mockito.junit.MockitoJUnitRunner
* @see org.mockito.Spy
* @see org.springframework.data.gemfire.GemfireOperations * @see org.springframework.data.gemfire.GemfireOperations
* @see org.springframework.data.gemfire.GemfireTemplate * @see org.springframework.data.gemfire.GemfireTemplate
* @see org.springframework.session.ExpiringSession * @see org.springframework.session.ExpiringSession
@@ -103,8 +106,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
protected static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600; protected static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600;
@Rule private AbstractGemFireOperationsSessionRepository sessionRepository;
public ExpectedException expectedException = ExpectedException.none();
@Mock @Mock
private GemfireOperations mockGemfireOperations; private GemfireOperations mockGemfireOperations;
@@ -112,16 +114,14 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Mock @Mock
private Log mockLog; private Log mockLog;
private AbstractGemFireOperationsSessionRepository sessionRepository;
@Before @Before
public void setup() { public void setup() {
this.sessionRepository = new TestGemFireOperationsSessionRepository(this.mockGemfireOperations) { this.sessionRepository = spy(new TestGemFireOperationsSessionRepository(this.mockGemfireOperations) {
@Override @Override
Log newLogger() { Log newLogger() {
return AbstractGemFireOperationsSessionRepositoryTest.this.mockLog; return AbstractGemFireOperationsSessionRepositoryTest.this.mockLog;
} }
}; });
} }
protected static <E> Set<E> asSet(E... elements) { protected static <E> Set<E> asSet(E... elements) {
@@ -133,12 +133,12 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
protected ExpiringSession mockSession(String sessionId, long creationAndLastAccessedTime, protected ExpiringSession mockSession(String sessionId, long creationAndLastAccessedTime,
int maxInactiveIntervalInSeconds) { int maxInactiveIntervalInSeconds) {
return mockSession(sessionId, creationAndLastAccessedTime, return mockSession(sessionId, creationAndLastAccessedTime, creationAndLastAccessedTime,
creationAndLastAccessedTime, maxInactiveIntervalInSeconds); maxInactiveIntervalInSeconds);
} }
protected ExpiringSession mockSession(String sessionId, long creationTime, protected ExpiringSession mockSession(String sessionId, long creationTime, long lastAccessedTime,
long lastAccessedTime, int maxInactiveIntervalInSeconds) { int maxInactiveIntervalInSeconds) {
ExpiringSession mockSession = mock(ExpiringSession.class, sessionId); ExpiringSession mockSession = mock(ExpiringSession.class, sessionId);
@@ -150,12 +150,17 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
return mockSession; return mockSession;
} }
@Test @Test(expected = IllegalArgumentException.class)
public void constructGemFireOperationsSessionRepositoryWithNullTemplate() { public void constructGemFireOperationsSessionRepositoryWithNullTemplate() {
this.expectedException.expect(IllegalArgumentException.class); try {
this.expectedException.expectMessage("GemfireOperations must not be null"); new TestGemFireOperationsSessionRepository(null);
}
catch (IllegalArgumentException expected) {
assertThat(expected).hasMessage("GemfireOperations must not be null");
assertThat(expected).hasNoCause();
new TestGemFireOperationsSessionRepository(null); throw expected;
}
} }
@Test @Test
@@ -208,9 +213,9 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(this.sessionRepository.getMaxInactiveIntervalInSeconds()).isEqualTo(Integer.MIN_VALUE); assertThat(this.sessionRepository.getMaxInactiveIntervalInSeconds()).isEqualTo(Integer.MIN_VALUE);
this.sessionRepository.setMaxInactiveIntervalInSeconds(3600); this.sessionRepository.setMaxInactiveIntervalInSeconds(1024000);
assertThat(this.sessionRepository.getMaxInactiveIntervalInSeconds()).isEqualTo(3600); assertThat(this.sessionRepository.getMaxInactiveIntervalInSeconds()).isEqualTo(1024000);
this.sessionRepository.setMaxInactiveIntervalInSeconds(Integer.MAX_VALUE); this.sessionRepository.setMaxInactiveIntervalInSeconds(Integer.MAX_VALUE);
@@ -258,7 +263,8 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
verify(mockEntryEvent, times(2)).getNewValue(); verify(mockEntryEvent, times(2)).getNewValue();
verify(mockEntryEvent, never()).getOldValue(); verify(mockEntryEvent, never()).getOldValue();
verify(mockSession, times(1)).getId(); verify(mockSession, times(1)).getId();
verify(mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionCreatedEvent.class)); verify(mockApplicationEventPublisher, times(1))
.publishEvent(isA(SessionCreatedEvent.class));
} }
@Test @Test
@@ -298,7 +304,8 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
verify(mockEntryEvent, times(1)).getKey(); verify(mockEntryEvent, times(1)).getKey();
verify(mockEntryEvent, times(2)).getNewValue(); verify(mockEntryEvent, times(2)).getNewValue();
verify(mockEntryEvent, never()).getOldValue(); verify(mockEntryEvent, never()).getOldValue();
verify(mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionCreatedEvent.class)); verify(mockApplicationEventPublisher, times(1))
.publishEvent(isA(SessionCreatedEvent.class));
} }
@Test @Test
@@ -364,7 +371,8 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
verify(mockEntryEvent, never()).getNewValue(); verify(mockEntryEvent, never()).getNewValue();
verify(mockEntryEvent, times(1)).getOldValue(); verify(mockEntryEvent, times(1)).getOldValue();
verify(mockSession, times(1)).getId(); verify(mockSession, times(1)).getId();
verify(mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionDestroyedEvent.class)); verify(mockApplicationEventPublisher, times(1))
.publishEvent(isA(SessionDestroyedEvent.class));
} }
@Test @Test
@@ -404,7 +412,8 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
verify(mockEntryEvent, times(1)).getKey(); verify(mockEntryEvent, times(1)).getKey();
verify(mockEntryEvent, never()).getNewValue(); verify(mockEntryEvent, never()).getNewValue();
verify(mockEntryEvent, times(1)).getOldValue(); verify(mockEntryEvent, times(1)).getOldValue();
verify(mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionDestroyedEvent.class)); verify(mockApplicationEventPublisher, times(1))
.publishEvent(isA(SessionDestroyedEvent.class));
} }
@Test @Test
@@ -444,7 +453,8 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
verify(mockEntryEvent, times(1)).getKey(); verify(mockEntryEvent, times(1)).getKey();
verify(mockEntryEvent, never()).getNewValue(); verify(mockEntryEvent, never()).getNewValue();
verify(mockEntryEvent, times(1)).getOldValue(); verify(mockEntryEvent, times(1)).getOldValue();
verify(mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionDestroyedEvent.class)); verify(mockApplicationEventPublisher, times(1))
.publishEvent(isA(SessionDestroyedEvent.class));
} }
@Test @Test
@@ -528,7 +538,8 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
verify(mockEntryEvent, times(1)).getKey(); verify(mockEntryEvent, times(1)).getKey();
verify(mockEntryEvent, never()).getNewValue(); verify(mockEntryEvent, never()).getNewValue();
verify(mockEntryEvent, times(1)).getOldValue(); verify(mockEntryEvent, times(1)).getOldValue();
verify(mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionExpiredEvent.class)); verify(mockApplicationEventPublisher, times(1))
.publishEvent(isA(SessionExpiredEvent.class));
} }
@Test @Test
@@ -568,7 +579,20 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
verify(mockEntryEvent, times(1)).getKey(); verify(mockEntryEvent, times(1)).getKey();
verify(mockEntryEvent, never()).getNewValue(); verify(mockEntryEvent, never()).getNewValue();
verify(mockEntryEvent, times(1)).getOldValue(); verify(mockEntryEvent, times(1)).getOldValue();
verify(mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionExpiredEvent.class)); verify(mockApplicationEventPublisher, times(1))
.publishEvent(isA(SessionExpiredEvent.class));
}
@Test
public void deleteSessionCallsDeleteSessionId() {
Session mockSession = mock(Session.class);
doNothing().when(this.sessionRepository).delete(anyString());
given(mockSession.getId()).willReturn("2");
assertThat(this.sessionRepository.delete(mockSession)).isNull();
verify(this.sessionRepository, times(1)).delete(eq("2"));
} }
@Test @Test
@@ -603,7 +627,8 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(this.sessionRepository.getApplicationEventPublisher()).isSameAs(mockApplicationEventPublisher); assertThat(this.sessionRepository.getApplicationEventPublisher()).isSameAs(mockApplicationEventPublisher);
verify(mockSession, times(1)).getId(); verify(mockSession, times(1)).getId();
verify(mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionDeletedEvent.class)); verify(mockApplicationEventPublisher, times(1))
.publishEvent(isA(SessionDeletedEvent.class));
} }
@Test @Test
@@ -634,7 +659,8 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(this.sessionRepository.getApplicationEventPublisher()).isSameAs(mockApplicationEventPublisher); assertThat(this.sessionRepository.getApplicationEventPublisher()).isSameAs(mockApplicationEventPublisher);
verify(mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionDeletedEvent.class)); verify(mockApplicationEventPublisher, times(1))
.publishEvent(isA(SessionDeletedEvent.class));
} }
@Test @Test
@@ -652,13 +678,23 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(this.sessionRepository.getApplicationEventPublisher()).isSameAs(mockApplicationEventPublisher); assertThat(this.sessionRepository.getApplicationEventPublisher()).isSameAs(mockApplicationEventPublisher);
verify(mockApplicationEventPublisher, times(1)).publishEvent(eq(mockApplicationEvent)); verify(mockApplicationEventPublisher, times(1)).publishEvent(eq(mockApplicationEvent));
verify(this.mockLog, times(1)).error(eq(String.format("error occurred publishing event (%s)", verify(this.mockLog, times(1))
mockApplicationEvent)), isA(IllegalStateException.class)); .error(eq(String.format("Error occurred publishing event [%s]", mockApplicationEvent)),
isA(IllegalStateException.class));
}
@Test
public void touchSetsLastAccessedTime() {
ExpiringSession mockSession = mock(ExpiringSession.class);
assertThat(this.sessionRepository.touch(mockSession)).isSameAs(mockSession);
verify(mockSession, times(1)).setLastAccessedTime(anyInt());
} }
@Test @Test
public void constructGemFireSessionWithDefaultInitialization() { public void constructGemFireSessionWithDefaultInitialization() {
final long beforeOrAtCreationTime = System.currentTimeMillis(); long beforeOrAtCreationTime = System.currentTimeMillis();
AbstractGemFireOperationsSessionRepository.GemFireSession session = AbstractGemFireOperationsSessionRepository.GemFireSession session =
new AbstractGemFireOperationsSessionRepository.GemFireSession(); new AbstractGemFireOperationsSessionRepository.GemFireSession();
@@ -668,12 +704,12 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(session.getLastAccessedTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime); assertThat(session.getLastAccessedTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime);
assertThat(session.getMaxInactiveIntervalInSeconds()).isEqualTo(0); assertThat(session.getMaxInactiveIntervalInSeconds()).isEqualTo(0);
assertThat(session.getAttributeNames()).isNotNull(); assertThat(session.getAttributeNames()).isNotNull();
assertThat(session.getAttributeNames().isEmpty()).isTrue(); assertThat(session.getAttributeNames()).isEmpty();
} }
@Test @Test
public void constructGemFireSessionWithId() { public void constructGemFireSessionWithId() {
final long beforeOrAtCreationTime = System.currentTimeMillis(); long beforeOrAtCreationTime = System.currentTimeMillis();
AbstractGemFireOperationsSessionRepository.GemFireSession session = AbstractGemFireOperationsSessionRepository.GemFireSession session =
new AbstractGemFireOperationsSessionRepository.GemFireSession("1"); new AbstractGemFireOperationsSessionRepository.GemFireSession("1");
@@ -683,16 +719,29 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(session.getLastAccessedTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime); assertThat(session.getLastAccessedTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime);
assertThat(session.getMaxInactiveIntervalInSeconds()).isEqualTo(0); assertThat(session.getMaxInactiveIntervalInSeconds()).isEqualTo(0);
assertThat(session.getAttributeNames()).isNotNull(); assertThat(session.getAttributeNames()).isNotNull();
assertThat(session.getAttributeNames().isEmpty()).isTrue(); assertThat(session.getAttributeNames()).isEmpty();
}
@Test(expected = IllegalArgumentException.class)
public void constructGemFireSessionWithUnspecifiedId() {
try {
new AbstractGemFireOperationsSessionRepository.GemFireSession(" ");
}
catch (IllegalArgumentException expected) {
assertThat(expected).hasMessage("ID must be specified");
assertThat(expected).hasNoCause();
throw expected;
}
} }
@Test @Test
public void constructGemFireSessionWithSession() { public void constructGemFireSessionWithSession() {
final long expectedCreationTime = 1L; long expectedCreationTime = 1L;
final long expectedLastAccessTime = 2L; long expectedLastAccessTime = 2L;
ExpiringSession mockSession = mockSession("2", expectedCreationTime, expectedLastAccessTime, ExpiringSession mockSession =
MAX_INACTIVE_INTERVAL_IN_SECONDS); mockSession("2", expectedCreationTime, expectedLastAccessTime, MAX_INACTIVE_INTERVAL_IN_SECONDS);
Set<String> expectedAttributedNames = asSet("attrOne", "attrTwo"); Set<String> expectedAttributedNames = asSet("attrOne", "attrTwo");
@@ -720,25 +769,22 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
verify(mockSession, times(1)).getAttribute(eq("attrTwo")); verify(mockSession, times(1)).getAttribute(eq("attrTwo"));
} }
@Test @Test(expected = IllegalArgumentException.class)
public void constructGemFireSessionWithNullSession() { public void constructGemFireSessionWithNullSession() {
this.expectedException.expect(IllegalArgumentException.class); try {
this.expectedException.expectMessage("The ExpiringSession to copy cannot be null"); new AbstractGemFireOperationsSessionRepository.GemFireSession((ExpiringSession) null);
}
catch (IllegalArgumentException expected) {
assertThat(expected).hasMessage("The ExpiringSession to copy cannot be null");
assertThat(expected).hasNoCause();
new AbstractGemFireOperationsSessionRepository.GemFireSession((ExpiringSession) null); throw expected;
} }
@Test
public void constructGemFireSessionWithUnspecifiedId() {
this.expectedException.expect(IllegalArgumentException.class);
this.expectedException.expectMessage("ID must be specified");
new AbstractGemFireOperationsSessionRepository.GemFireSession(" ");
} }
@Test @Test
public void createNewGemFireSession() { public void createNewGemFireSession() {
final long beforeOrAtCreationTime = System.currentTimeMillis(); long beforeOrAtCreationTime = System.currentTimeMillis();
AbstractGemFireOperationsSessionRepository.GemFireSession session = AbstractGemFireOperationsSessionRepository.GemFireSession session =
AbstractGemFireOperationsSessionRepository.GemFireSession.create(120); AbstractGemFireOperationsSessionRepository.GemFireSession.create(120);
@@ -754,8 +800,8 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test @Test
public void fromExistingSession() { public void fromExistingSession() {
final long expectedCreationTime = 1L; long expectedCreationTime = 1L;
final long expectedLastAccessedTime = 2L; long expectedLastAccessedTime = 2L;
ExpiringSession mockSession = mockSession("4", expectedCreationTime, expectedLastAccessedTime, ExpiringSession mockSession = mockSession("4", expectedCreationTime, expectedLastAccessedTime,
MAX_INACTIVE_INTERVAL_IN_SECONDS); MAX_INACTIVE_INTERVAL_IN_SECONDS);
@@ -768,9 +814,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(gemfireSession).isNotNull(); assertThat(gemfireSession).isNotNull();
assertThat(gemfireSession.getId()).isEqualTo("4"); assertThat(gemfireSession.getId()).isEqualTo("4");
assertThat(gemfireSession.getCreationTime()).isEqualTo(expectedCreationTime); assertThat(gemfireSession.getCreationTime()).isEqualTo(expectedCreationTime);
assertThat(gemfireSession.getLastAccessedTime()).isNotEqualTo(expectedLastAccessedTime); assertThat(gemfireSession.getLastAccessedTime()).isEqualTo(expectedLastAccessedTime);
assertThat(gemfireSession.getLastAccessedTime()).isGreaterThanOrEqualTo(expectedCreationTime);
assertThat(gemfireSession.getLastAccessedTime()).isLessThanOrEqualTo(System.currentTimeMillis());
assertThat(gemfireSession.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS); assertThat(gemfireSession.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
assertThat(gemfireSession.getAttributeNames()).isNotNull(); assertThat(gemfireSession.getAttributeNames()).isNotNull();
assertThat(gemfireSession.getAttributeNames().isEmpty()).isTrue(); assertThat(gemfireSession.getAttributeNames().isEmpty()).isTrue();
@@ -783,6 +827,17 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
verify(mockSession, never()).getAttribute(anyString()); verify(mockSession, never()).getAttribute(anyString());
} }
@Test
public void fromExistingGemFireSessionIsGemFireSession() {
AbstractGemFireOperationsSessionRepository.GemFireSession gemfireSession =
AbstractGemFireOperationsSessionRepository.GemFireSession.create(300);
AbstractGemFireOperationsSessionRepository.GemFireSession fromGemFireSession =
AbstractGemFireOperationsSessionRepository.GemFireSession.from(gemfireSession);
assertThat(fromGemFireSession).isSameAs(gemfireSession);
}
@Test @Test
public void setGetAndRemoveAttribute() { public void setGetAndRemoveAttribute() {
AbstractGemFireOperationsSessionRepository.GemFireSession session = AbstractGemFireOperationsSessionRepository.GemFireSession session =
@@ -918,17 +973,18 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
verify(mockDataOutput, times(1)).writeUTF(eq("1")); verify(mockDataOutput, times(1)).writeUTF(eq("1"));
verify(mockDataOutput, times(1)).writeLong(eq(session.getCreationTime())); verify(mockDataOutput, times(1)).writeLong(eq(session.getCreationTime()));
verify(mockDataOutput, times(1)).writeLong(eq(session.getLastAccessedTime())); verify(mockDataOutput, times(1)).writeLong(eq(session.getLastAccessedTime()));
verify(mockDataOutput, times(1)).writeInt(eq(session.getMaxInactiveIntervalInSeconds())); verify(mockDataOutput, times(1))
.writeInt(eq(session.getMaxInactiveIntervalInSeconds()));
verify(mockDataOutput, times(1)).writeInt(eq("jblum".length())); verify(mockDataOutput, times(1)).writeInt(eq("jblum".length()));
verify(mockDataOutput, times(1)).writeUTF(eq(session.getPrincipalName())); verify(mockDataOutput, times(1)).writeUTF(eq(session.getPrincipalName()));
} }
@Test @Test
public void sessionFromData() throws Exception { public void sessionFromData() throws Exception {
final long expectedCreationTime = 1L; long expectedCreationTime = 1L;
final long expectedLastAccessedTime = 2L; long expectedLastAccessedTime = 2L;
final int expectedMaxInactiveIntervalInSeconds = (int) TimeUnit.HOURS.toSeconds(6); int expectedMaxInactiveIntervalInSeconds = (int) TimeUnit.HOURS.toSeconds(6);
final String expectedPrincipalName = "jblum"; final String expectedPrincipalName = "jblum";
@@ -958,8 +1014,8 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
session.fromData(mockDataInput); session.fromData(mockDataInput);
Set<String> expectedAttributeNames = asSet("attrOne", "attrTwo", Set<String> expectedAttributeNames =
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME); asSet("attrOne", "attrTwo", FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
assertThat(session.getId()).isEqualTo("2"); assertThat(session.getId()).isEqualTo("2");
assertThat(session.getCreationTime()).isEqualTo(expectedCreationTime); assertThat(session.getCreationTime()).isEqualTo(expectedCreationTime);
@@ -1044,7 +1100,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test @Test
public void hasDeltaWhenSessionLastAccessedTimeIsUpdatedIsTrue() { public void hasDeltaWhenSessionLastAccessedTimeIsUpdatedIsTrue() {
final long expectedLastAccessTime = 1L; long expectedLastAccessTime = 1L;
AbstractGemFireOperationsSessionRepository.GemFireSession session = AbstractGemFireOperationsSessionRepository.GemFireSession session =
new AbstractGemFireOperationsSessionRepository.GemFireSession(); new AbstractGemFireOperationsSessionRepository.GemFireSession();
@@ -1065,7 +1121,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test @Test
public void hasDeltaWhenSessionMaxInactiveIntervalInSecondsIsUpdatedIsTrue() { public void hasDeltaWhenSessionMaxInactiveIntervalInSecondsIsUpdatedIsTrue() {
final int expectedMaxInactiveIntervalInSeconds = 300; int expectedMaxInactiveIntervalInSeconds = 300;
AbstractGemFireOperationsSessionRepository.GemFireSession session = AbstractGemFireOperationsSessionRepository.GemFireSession session =
new AbstractGemFireOperationsSessionRepository.GemFireSession(); new AbstractGemFireOperationsSessionRepository.GemFireSession();
@@ -1146,7 +1202,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test @Test
public void sessionComparisons() { public void sessionComparisons() {
final long twoHoursAgo = (System.currentTimeMillis() - TimeUnit.HOURS.toMillis(2)); long twoHoursAgo = (System.currentTimeMillis() - TimeUnit.HOURS.toMillis(2));
AbstractGemFireOperationsSessionRepository.GemFireSession sessionOne = AbstractGemFireOperationsSessionRepository.GemFireSession sessionOne =
new AbstractGemFireOperationsSessionRepository.GemFireSession( new AbstractGemFireOperationsSessionRepository.GemFireSession(
@@ -1528,8 +1584,9 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(this.session.getMaxInactiveIntervalInSeconds()).isEqualTo(60); assertThat(this.session.getMaxInactiveIntervalInSeconds()).isEqualTo(60);
assertThat(this.session.getPrincipalName()).isEqualTo("jblum"); assertThat(this.session.getPrincipalName()).isEqualTo("jblum");
assertThat(this.session.getAttributeNames().size()).isEqualTo(1); assertThat(this.session.getAttributeNames().size()).isEqualTo(1);
assertThat(String.valueOf(this.session.getAttribute( assertThat(String.valueOf(
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME))).isEqualTo("jblum"); this.session.getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME)))
.isEqualTo("jblum");
this.session.setAttribute("tennis", "ping"); this.session.setAttribute("tennis", "ping");
this.session.setAttribute("junk", "test"); this.session.setAttribute("junk", "test");
@@ -1595,24 +1652,24 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
super(gemfireOperations); super(gemfireOperations);
} }
public Map<String, ExpiringSession> findByIndexNameAndIndexValue(String indexName, String indexValue) { public ExpiringSession createSession() {
throw new UnsupportedOperationException("not implemented"); throw new UnsupportedOperationException("Not Implemented");
} }
public ExpiringSession createSession() { public Map<String, ExpiringSession> findByIndexNameAndIndexValue(String indexName, String indexValue) {
throw new UnsupportedOperationException("not implemented"); throw new UnsupportedOperationException("Not Implemented");
} }
public ExpiringSession getSession(String id) { public ExpiringSession getSession(String id) {
throw new UnsupportedOperationException("not implemented"); throw new UnsupportedOperationException("Not Implemented");
} }
public void save(ExpiringSession session) { public void save(ExpiringSession session) {
throw new UnsupportedOperationException("not implemented"); throw new UnsupportedOperationException("Not Implemented");
} }
public void delete(String id) { public void delete(String id) {
throw new UnsupportedOperationException("not implemented"); throw new UnsupportedOperationException("Not Implemented");
} }
} }
} }

View File

@@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.geode.cache.AttributesMutator; import org.apache.geode.cache.AttributesMutator;
import org.apache.geode.cache.Region; import org.apache.geode.cache.Region;
import org.apache.geode.cache.query.SelectResults; import org.apache.geode.cache.query.SelectResults;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -65,6 +66,7 @@ import static org.mockito.Mockito.verify;
* @see org.mockito.Mock * @see org.mockito.Mock
* @see org.mockito.Mockito * @see org.mockito.Mockito
* @see org.mockito.junit.MockitoJUnitRunner * @see org.mockito.junit.MockitoJUnitRunner
* @see org.springframework.data.gemfire.GemfireOperations
* @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository * @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository
* @see org.apache.geode.cache.Region * @see org.apache.geode.cache.Region
*/ */
@@ -79,34 +81,28 @@ public class GemFireOperationsSessionRepositoryTest {
@Mock @Mock
private AttributesMutator<Object, ExpiringSession> mockAttributesMutator; private AttributesMutator<Object, ExpiringSession> mockAttributesMutator;
@Mock
private Region<Object, ExpiringSession> mockRegion;
@Mock @Mock
private GemfireOperationsAccessor mockTemplate; private GemfireOperationsAccessor mockTemplate;
private GemFireOperationsSessionRepository sessionRepository; private GemFireOperationsSessionRepository sessionRepository;
@Mock
private Region<Object, ExpiringSession> mockRegion;
@Before @Before
public void setup() throws Exception { public void setup() throws Exception {
given(this.mockRegion.getAttributesMutator()).willReturn(this.mockAttributesMutator); given(this.mockRegion.getAttributesMutator()).willReturn(this.mockAttributesMutator);
given(this.mockRegion.getFullPath()).willReturn("/Example"); given(this.mockRegion.getFullPath()).willReturn("/Example");
given(this.mockTemplate.<Object, ExpiringSession>getRegion()).willReturn(this.mockRegion); given(this.mockTemplate.<Object, ExpiringSession>getRegion()).willReturn(this.mockRegion);
this.sessionRepository = new GemFireOperationsSessionRepository( this.sessionRepository = new GemFireOperationsSessionRepository(this.mockTemplate);
this.mockTemplate); this.sessionRepository.setApplicationEventPublisher(this.mockApplicationEventPublisher);
this.sessionRepository this.sessionRepository.setMaxInactiveIntervalInSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS);
.setApplicationEventPublisher(this.mockApplicationEventPublisher);
this.sessionRepository
.setMaxInactiveIntervalInSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS);
this.sessionRepository.afterPropertiesSet(); this.sessionRepository.afterPropertiesSet();
assertThat(this.sessionRepository.getApplicationEventPublisher()) assertThat(this.sessionRepository.getApplicationEventPublisher()).isSameAs(this.mockApplicationEventPublisher);
.isSameAs(this.mockApplicationEventPublisher); assertThat(this.sessionRepository.getFullyQualifiedRegionName()).isEqualTo("/Example");
assertThat(this.sessionRepository.getFullyQualifiedRegionName()) assertThat(this.sessionRepository.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
.isEqualTo("/Example");
assertThat(this.sessionRepository.getMaxInactiveIntervalInSeconds())
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
} }
@After @After
@@ -130,14 +126,13 @@ public class GemFireOperationsSessionRepositoryTest {
String indexName = "vip"; String indexName = "vip";
String indexValue = "rwinch"; String indexValue = "rwinch";
String expectedQql = String.format( String expectedQql = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_INDEX_NAME_VALUE_QUERY,
GemFireOperationsSessionRepository.FIND_SESSIONS_BY_INDEX_NAME_VALUE_QUERY, this.sessionRepository.getFullyQualifiedRegionName(), indexName);
this.sessionRepository.getFullyQualifiedRegionName(), indexName);
given(this.mockTemplate.find(eq(expectedQql), eq(indexValue))).willReturn(mockSelectResults); given(this.mockTemplate.find(eq(expectedQql), eq(indexValue))).willReturn(mockSelectResults);
Map<String, ExpiringSession> sessions = Map<String, ExpiringSession> sessions =
this.sessionRepository.findByIndexNameAndIndexValue(indexName, indexValue); this.sessionRepository.findByIndexNameAndIndexValue(indexName, indexValue);
assertThat(sessions).isNotNull(); assertThat(sessions).isNotNull();
assertThat(sessions.size()).isEqualTo(1); assertThat(sessions.size()).isEqualTo(1);
@@ -161,22 +156,18 @@ public class GemFireOperationsSessionRepositoryTest {
SelectResults<Object> mockSelectResults = mock(SelectResults.class); SelectResults<Object> mockSelectResults = mock(SelectResults.class);
given(mockSelectResults.asList()).willReturn( given(mockSelectResults.asList())
Arrays.<Object>asList(mockSessionOne, mockSessionTwo, mockSessionThree)); .willReturn(Arrays.<Object>asList(mockSessionOne, mockSessionTwo, mockSessionThree));
String principalName = "jblum"; String principalName = "jblum";
String expectedOql = String.format( String expectedOql = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY, this.sessionRepository.getFullyQualifiedRegionName());
this.sessionRepository.getFullyQualifiedRegionName());
given(this.mockTemplate.find(eq(expectedOql), eq(principalName))) given(this.mockTemplate.find(eq(expectedOql), eq(principalName))).willReturn(mockSelectResults);
.willReturn(mockSelectResults);
Map<String, ExpiringSession> sessions = this.sessionRepository Map<String, ExpiringSession> sessions = this.sessionRepository.findByIndexNameAndIndexValue(
.findByIndexNameAndIndexValue( FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
principalName);
assertThat(sessions).isNotNull(); assertThat(sessions).isNotNull();
assertThat(sessions.size()).isEqualTo(3); assertThat(sessions.size()).isEqualTo(3);
@@ -200,15 +191,13 @@ public class GemFireOperationsSessionRepositoryTest {
String principalName = "jblum"; String principalName = "jblum";
String expectedOql = String.format( String expectedOql = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY, this.sessionRepository.getFullyQualifiedRegionName());
this.sessionRepository.getFullyQualifiedRegionName());
given(this.mockTemplate.find(eq(expectedOql), eq(principalName))) given(this.mockTemplate.find(eq(expectedOql), eq(principalName))).willReturn(mockSelectResults);
.willReturn(mockSelectResults);
Map<String, ExpiringSession> sessions = this.sessionRepository.findByIndexNameAndIndexValue( Map<String, ExpiringSession> sessions = this.sessionRepository.findByIndexNameAndIndexValue(
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName); FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
assertThat(sessions).isNotNull(); assertThat(sessions).isNotNull();
assertThat(sessions.isEmpty()).isTrue(); assertThat(sessions.isEmpty()).isTrue();
@@ -219,12 +208,11 @@ public class GemFireOperationsSessionRepositoryTest {
@Test @Test
public void prepareQueryReturnsPrincipalNameOql() { public void prepareQueryReturnsPrincipalNameOql() {
String actualQql = this.sessionRepository.prepareQuery( String actualQql =
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME); this.sessionRepository.prepareQuery(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
String expectedOql = String.format( String expectedOql = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY, this.sessionRepository.getFullyQualifiedRegionName());
this.sessionRepository.getFullyQualifiedRegionName());
assertThat(actualQql).isEqualTo(expectedOql); assertThat(actualQql).isEqualTo(expectedOql);
} }
@@ -233,21 +221,19 @@ public class GemFireOperationsSessionRepositoryTest {
public void prepareQueryReturnsIndexNameValueOql() { public void prepareQueryReturnsIndexNameValueOql() {
String attributeName = "testAttributeName"; String attributeName = "testAttributeName";
String actualOql = this.sessionRepository.prepareQuery(attributeName); String actualOql = this.sessionRepository.prepareQuery(attributeName);
String expectedOql = String.format( String expectedOql = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_INDEX_NAME_VALUE_QUERY,
GemFireOperationsSessionRepository.FIND_SESSIONS_BY_INDEX_NAME_VALUE_QUERY, this.sessionRepository.getFullyQualifiedRegionName(), attributeName);
this.sessionRepository.getFullyQualifiedRegionName(), attributeName);
assertThat(actualOql).isEqualTo(expectedOql); assertThat(actualOql).isEqualTo(expectedOql);
} }
@Test @Test
public void createProperlyInitializedSession() { public void createProperlyInitializedSession() {
final long beforeOrAtCreationTime = System.currentTimeMillis(); long beforeOrAtCreationTime = System.currentTimeMillis();
ExpiringSession session = this.sessionRepository.createSession(); ExpiringSession session = this.sessionRepository.createSession();
assertThat(session).isInstanceOf( assertThat(session).isInstanceOf(AbstractGemFireOperationsSessionRepository.GemFireSession.class);
AbstractGemFireOperationsSessionRepository.GemFireSession.class);
assertThat(session.getId()).isNotNull(); assertThat(session.getId()).isNotNull();
assertThat(session.getAttributeNames().isEmpty()).isTrue(); assertThat(session.getAttributeNames().isEmpty()).isTrue();
assertThat(session.getCreationTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime); assertThat(session.getCreationTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime);
@@ -274,8 +260,8 @@ public class GemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent; AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource()).isSameAs( assertThat(sessionEvent.getSource())
GemFireOperationsSessionRepositoryTest.this.sessionRepository); .isSameAs(GemFireOperationsSessionRepositoryTest.this.sessionRepository);
assertThat(sessionEvent.getSession()).isSameAs(mockSession); assertThat(sessionEvent.getSession()).isSameAs(mockSession);
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId); assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);
@@ -289,16 +275,16 @@ public class GemFireOperationsSessionRepositoryTest {
verify(this.mockTemplate, times(1)).remove(eq(expectedSessionId)); verify(this.mockTemplate, times(1)).remove(eq(expectedSessionId));
verify(mockSession, times(1)).isExpired(); verify(mockSession, times(1)).isExpired();
verify(mockSession, times(2)).getId(); verify(mockSession, times(2)).getId();
verify(this.mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionDeletedEvent.class)); verify(this.mockApplicationEventPublisher, times(1))
.publishEvent(isA(SessionDeletedEvent.class));
} }
@Test @Test
public void getSessionFindsMatchingNonExpiredSessionById() { public void getSessionFindsMatchingNonExpiredSessionById() {
final String expectedId = "1"; String expectedId = "1";
final long expectedCreationTime = System.currentTimeMillis(); long expectedCreationTime = System.currentTimeMillis();
final long currentLastAccessedTime = (expectedCreationTime long currentLastAccessedTime = (expectedCreationTime + TimeUnit.MINUTES.toMillis(5));
+ TimeUnit.MINUTES.toMillis(5));
ExpiringSession mockSession = mock(ExpiringSession.class); ExpiringSession mockSession = mock(ExpiringSession.class);
@@ -340,8 +326,7 @@ public class GemFireOperationsSessionRepositoryTest {
final String expectedSessionId = "1"; final String expectedSessionId = "1";
final long expectedCreationTime = System.currentTimeMillis(); final long expectedCreationTime = System.currentTimeMillis();
final long expectedLastAccessTime = (expectedCreationTime final long expectedLastAccessTime = (expectedCreationTime + TimeUnit.MINUTES.toMillis(5));
+ TimeUnit.MINUTES.toMillis(5));
ExpiringSession mockSession = mock(ExpiringSession.class); ExpiringSession mockSession = mock(ExpiringSession.class);
@@ -353,22 +338,22 @@ public class GemFireOperationsSessionRepositoryTest {
given(mockSession.getAttributeNames()).willReturn(Collections.<String>emptySet()); given(mockSession.getAttributeNames()).willReturn(Collections.<String>emptySet());
given(this.mockTemplate.put(eq(expectedSessionId), given(this.mockTemplate.put(eq(expectedSessionId),
isA(AbstractGemFireOperationsSessionRepository.GemFireSession.class))) isA(AbstractGemFireOperationsSessionRepository.GemFireSession.class)))
.willAnswer(new Answer<ExpiringSession>() { .willAnswer(new Answer<ExpiringSession>() {
public ExpiringSession answer(InvocationOnMock invocation) throws Throwable { public ExpiringSession answer(InvocationOnMock invocation) throws Throwable {
ExpiringSession session = invocation.getArgument(1); ExpiringSession session = invocation.getArgument(1);
assertThat(session).isNotNull(); assertThat(session).isNotNull();
assertThat(session.getId()).isEqualTo(expectedSessionId); assertThat(session.getId()).isEqualTo(expectedSessionId);
assertThat(session.getCreationTime()).isEqualTo(expectedCreationTime); assertThat(session.getCreationTime()).isEqualTo(expectedCreationTime);
assertThat(session.getLastAccessedTime()).isEqualTo(expectedLastAccessTime); assertThat(session.getLastAccessedTime()).isEqualTo(expectedLastAccessTime);
assertThat(session.getMaxInactiveIntervalInSeconds()) assertThat(session.getMaxInactiveIntervalInSeconds())
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS); .isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
assertThat(session.getAttributeNames().isEmpty()).isTrue(); assertThat(session.getAttributeNames().isEmpty()).isTrue();
return null; return null;
} }
}); });
this.sessionRepository.save(mockSession); this.sessionRepository.save(mockSession);
@@ -378,7 +363,7 @@ public class GemFireOperationsSessionRepositoryTest {
verify(mockSession, times(1)).getMaxInactiveIntervalInSeconds(); verify(mockSession, times(1)).getMaxInactiveIntervalInSeconds();
verify(mockSession, times(1)).getAttributeNames(); verify(mockSession, times(1)).getAttributeNames();
verify(this.mockTemplate, times(1)).put(eq(expectedSessionId), verify(this.mockTemplate, times(1)).put(eq(expectedSessionId),
isA(AbstractGemFireOperationsSessionRepository.GemFireSession.class)); isA(AbstractGemFireOperationsSessionRepository.GemFireSession.class));
} }
@Test @Test
@@ -398,8 +383,8 @@ public class GemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent; AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource()).isSameAs( assertThat(sessionEvent.getSource())
GemFireOperationsSessionRepositoryTest.this.sessionRepository); .isSameAs(GemFireOperationsSessionRepositoryTest.this.sessionRepository);
assertThat(sessionEvent.getSession()).isSameAs(mockSession); assertThat(sessionEvent.getSession()).isSameAs(mockSession);
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId); assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);
@@ -411,7 +396,8 @@ public class GemFireOperationsSessionRepositoryTest {
verify(mockSession, times(1)).getId(); verify(mockSession, times(1)).getId();
verify(this.mockTemplate, times(1)).remove(eq(expectedSessionId)); verify(this.mockTemplate, times(1)).remove(eq(expectedSessionId));
verify(this.mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionDeletedEvent.class)); verify(this.mockApplicationEventPublisher, times(1))
.publishEvent(isA(SessionDeletedEvent.class));
} }
@Test @Test
@@ -428,20 +414,20 @@ public class GemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent; AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource()).isSameAs( assertThat(sessionEvent.getSource()).
GemFireOperationsSessionRepositoryTest.this.sessionRepository); isSameAs(GemFireOperationsSessionRepositoryTest.this.sessionRepository);
assertThat(sessionEvent.getSession()).isNull(); assertThat(sessionEvent.getSession()).isNull();
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId); assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);
return null; return null;
} }
}).given(this.mockApplicationEventPublisher) }).given(this.mockApplicationEventPublisher).publishEvent(isA(SessionDeletedEvent.class));
.publishEvent(isA(SessionDeletedEvent.class));
this.sessionRepository.delete(expectedSessionId); this.sessionRepository.delete(expectedSessionId);
verify(this.mockTemplate, times(1)).remove(eq(expectedSessionId)); verify(this.mockTemplate, times(1)).remove(eq(expectedSessionId));
verify(this.mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionDeletedEvent.class)); verify(this.mockApplicationEventPublisher, times(1))
.publishEvent(isA(SessionDeletedEvent.class));
} }
protected abstract class GemfireOperationsAccessor extends GemfireAccessor protected abstract class GemfireOperationsAccessor extends GemfireAccessor