Remove DataSerializable serialization logic from GemFireSession and GemFireSessionAttributes classes.

Move Delta serialization logic to new DeltaCapableGemFireSession and DeltaCapableGemFireSessionAttributes subclasses.

Fix up all test class compilation issues and failures.

Resolves Issue #2.
This commit is contained in:
John Blum
2017-08-02 21:23:02 -07:00
parent 305a2d6255
commit ed8de1315a
18 changed files with 951 additions and 755 deletions

View File

@@ -17,6 +17,7 @@
package org.springframework.session.data.gemfire;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.data.gemfire.util.ArrayUtils.asArray;
import java.io.File;
import java.io.IOException;
@@ -25,9 +26,7 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.Collections;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.junit.After;
@@ -37,9 +36,7 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.client.ClientCache;
@@ -51,10 +48,10 @@ 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.config.annotation.CacheServerApplication;
import org.springframework.data.gemfire.config.annotation.CacheServerConfigurer;
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
import org.springframework.session.Session;
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
@@ -71,31 +68,36 @@ import org.springframework.util.FileSystemUtils;
import org.springframework.util.SocketUtils;
/**
* Integration tests to test the functionality of GemFire-backed Spring Sessions using
* the GemFire client-server topology.
* Integration tests testing the functionality of Apache Geode / Pivotal GemFire backed Spring Sessions
* using the GemFire client-server topology.
*
* @author John Blum
* @since 1.1.0
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.springframework.context.ConfigurableApplicationContext
* @see org.springframework.session.Session
* @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.annotation.DirtiesContext
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringRunner
* @see org.springframework.test.context.web.WebAppConfiguration
* @see org.apache.geode.cache.Cache
* @see org.apache.geode.cache.Region
* @see org.apache.geode.cache.client.ClientCache
* @see org.apache.geode.cache.client.Pool
* @see org.apache.geode.cache.server.CacheServer
* @see org.springframework.context.ConfigurableApplicationContext
* @see org.springframework.data.gemfire.config.annotation.CacheServerApplication
* @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication
* @see org.springframework.session.Session
* @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.session.events.SessionCreatedEvent
* @see org.springframework.session.events.SessionDeletedEvent
* @see org.springframework.session.events.SessionExpiredEvent
* @see org.springframework.test.annotation.DirtiesContext
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringRunner
* @see org.springframework.test.context.web.WebAppConfiguration
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes =
ClientServerGemFireOperationsSessionRepositoryIntegrationTests.SpringSessionDataGemFireClientConfiguration.class)
ClientServerGemFireOperationsSessionRepositoryIntegrationTests.TestGemFireClientConfiguration.class)
@DirtiesContext
@WebAppConfiguration
public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
@@ -109,9 +111,10 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
private static Process gemfireServer;
private static final String SPRING_SESSION_GEMFIRE_REGION_NAME = "TestClientServerSessions";
private static final String TEST_SESSION_REGION_NAME = "TestClientServerSessions";
@Autowired
@SuppressWarnings("all")
private SessionEventListener sessionEventListener;
@BeforeClass
@@ -122,7 +125,7 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
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);
TestGemFireServerConfiguration.SERVER_HOSTNAME, port);
System.setProperty("spring.session.data.gemfire.port", String.valueOf(port));
@@ -131,10 +134,10 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
processWorkingDirectory = createDirectory(processWorkingDirectoryPathname);
gemfireServer = run(SpringSessionDataGemFireServerConfiguration.class, processWorkingDirectory,
gemfireServer = run(TestGemFireServerConfiguration.class, processWorkingDirectory,
String.format("-Dspring.session.data.gemfire.port=%1$d", port));
assertThat(waitForCacheServerToStart(SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port))
assertThat(waitForCacheServerToStart(TestGemFireServerConfiguration.SERVER_HOSTNAME, port))
.isTrue();
System.err.printf("GemFire Server [startup time = %1$d ms]%n", System.currentTimeMillis() - t0);
@@ -164,7 +167,7 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
assertThat(GemFireUtils.isClient(gemfireCache)).isTrue();
Region<Object, Session> springSessionGemFireRegion =
gemfireCache.getRegion(SPRING_SESSION_GEMFIRE_REGION_NAME);
gemfireCache.getRegion(TEST_SESSION_REGION_NAME);
assertThat(springSessionGemFireRegion).isNotNull();
@@ -257,53 +260,25 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
assertThat(deletedSession).isNull();
}
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME,
@ClientCacheApplication(logLevel = "warning", pingInterval = 5000, readTimeout = 2500, retryAttempts = 1,
subscriptionEnabled = true)
@EnableGemFireHttpSession(regionName = TEST_SESSION_REGION_NAME, poolName = "DEFAULT",
clientRegionShortcut = ClientRegionShortcut.CACHING_PROXY,
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
@SuppressWarnings("unused")
static class SpringSessionDataGemFireClientConfiguration {
static class TestGemFireClientConfiguration {
@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(
ClientCacheConfigurer clientCacheDefaultPoolPortConfigurer(
@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;
return (beanName, clientCacheFactoryBean) ->
clientCacheFactoryBean.setServers(asArray(new ConnectionEndpoint("localhost", port)));
}
@Bean
@@ -316,7 +291,7 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new AnnotationConfigApplicationContext(
SpringSessionDataGemFireClientConfiguration.class);
TestGemFireClientConfiguration.class);
applicationContext.registerShutdownHook();
@@ -329,10 +304,12 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
}
}
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME,
@CacheServerApplication(name = "ClientServerGemFireOperationsSessionRepositoryIntegrationTests",
logLevel = "warning")
@EnableGemFireHttpSession(regionName = TEST_SESSION_REGION_NAME,
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
@SuppressWarnings("unused")
static class SpringSessionDataGemFireServerConfiguration {
static class TestGemFireServerConfiguration {
static final String SERVER_HOSTNAME = "localhost";
@@ -341,53 +318,20 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
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 ClientServerGemFireOperationsSessionRepositoryIntegrationTests.class.getName();
}
@Bean
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setProperties(gemfireProperties());
return gemfireCache;
}
@Bean
CacheServerFactoryBean gemfireCacheServer(GemFireCache gemfireCache,
CacheServerConfigurer cacheServerPortConfigurer(
@Value("${spring.session.data.gemfire.port:" + DEFAULT_GEMFIRE_SERVER_PORT + "}") int port) {
CacheServerFactoryBean cacheServerFactory = new CacheServerFactoryBean();
cacheServerFactory.setCache((Cache) gemfireCache);
cacheServerFactory.setAutoStartup(true);
cacheServerFactory.setBindAddress(SERVER_HOSTNAME);
cacheServerFactory.setPort(port);
return cacheServerFactory;
return (beanName, cacheServerFactoryBean) -> cacheServerFactoryBean.setPort(port);
}
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(SpringSessionDataGemFireServerConfiguration.class);
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(TestGemFireServerConfiguration.class);
context.registerShutdownHook();
applicationContext.registerShutdownHook();
writeProcessControlFile(WORKING_DIRECTORY);
}

View File

@@ -48,29 +48,33 @@ import org.springframework.session.Session;
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
import org.springframework.test.annotation.DirtiesContext;
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.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Integration test to test the {@code findByPrincipalName} query method
* on {@link GemFireOperationsSessionRepository}.
* Integration test to test the {@code findByPrincipalName} query method on {@link GemFireOperationsSessionRepository}.
*
* @author John Blum
* @since 1.1.0
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.apache.geode.cache.Region
* @see org.apache.geode.cache.query.QueryService
* @see org.apache.geode.pdx.PdxSerializable
* @see org.springframework.data.gemfire.config.annotation.PeerCacheApplication
* @see org.springframework.security.core.context.SecurityContext
* @see org.springframework.session.Session
* @see org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests
* @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository
* @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession
* @see org.springframework.test.annotation.DirtiesContext
* @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.apache.geode.cache.Cache
* @see org.apache.geode.cache.Region
*/
@RunWith(SpringJUnit4ClassRunner.class)
@RunWith(SpringRunner.class)
@ContextConfiguration
@DirtiesContext
@WebAppConfiguration
@@ -328,8 +332,8 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
((AbstractGemFireOperationsSessionRepository.GemFireSession) expectedSession).setPrincipalName("jblum");
List<String> expectedAttributeNames = Arrays.asList("booleanAttribute", "numericAttribute", "stringAttribute",
"personAttribute");
List<String> expectedAttributeNames =
Arrays.asList("booleanAttribute", "numericAttribute", "stringAttribute", "personAttribute");
Person jonDoe = new Person("Jon", "Doe");
@@ -406,13 +410,13 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
pdxWriter.writeString("lastName", getLastName());
}
public void fromData(final PdxReader pdxReader) {
public void fromData(PdxReader pdxReader) {
this.firstName = pdxReader.readString("firstName");
this.lastName = pdxReader.readString("lastName");
}
@SuppressWarnings("all")
public int compareTo(final Person person) {
public int compareTo(Person person) {
int compareValue = getLastName().compareTo(person.getLastName());
@@ -420,7 +424,7 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
}
@Override
public boolean equals(final Object obj) {
public boolean equals(Object obj) {
if (this == obj) {
return true;

View File

@@ -16,6 +16,8 @@
package org.springframework.session.data.gemfire;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@@ -32,6 +34,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.geode.DataSerializable;
import org.apache.geode.DataSerializer;
@@ -93,7 +96,7 @@ import org.apache.commons.logging.LogFactory;
public abstract class AbstractGemFireOperationsSessionRepository extends CacheListenerAdapter<Object, Session>
implements ApplicationEventPublisherAware, FindByIndexNameSessionRepository<Session>, InitializingBean {
private boolean usingDataSerialization = false;
private static final AtomicBoolean usingDataSerialization = new AtomicBoolean(false);
private ApplicationEventPublisher applicationEventPublisher = new ApplicationEventPublisher() {
@@ -246,7 +249,7 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
* @param useDataSerialization boolean indicating whether the DataSerialization framework has been configured.
*/
public void setUseDataSerialization(boolean useDataSerialization) {
this.usingDataSerialization = useDataSerialization;
usingDataSerialization.set(useDataSerialization);
}
/**
@@ -254,8 +257,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
*
* @return a boolean indicating whether the DataSerialization framework has been configured.
*/
protected boolean isUsingDataSerialization() {
return this.usingDataSerialization;
protected static boolean isUsingDataSerialization() {
return usingDataSerialization.get();
}
/**
@@ -292,9 +295,6 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
this.fullyQualifiedRegionName = region.getFullPath();
region.getAttributesMutator().addCacheListener(this);
Instantiator.register(GemFireSessionInstantiator.create());
Instantiator.register(GemFireSessionAttributesInstantiator.create());
}
/* (non-Javadoc) */
@@ -524,22 +524,57 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
return session;
}
@SuppressWarnings("unused")
public static class DeltaCapableGemFireSession extends GemFireSession<DeltaCapableGemFireSessionAttributes>
implements Delta {
public DeltaCapableGemFireSession() { }
public DeltaCapableGemFireSession(String id) {
super(id);
}
public DeltaCapableGemFireSession(Session session) {
super(session);
}
@Override
protected DeltaCapableGemFireSessionAttributes newSessionAttributes(Object lock) {
return new DeltaCapableGemFireSessionAttributes();
}
/* (non-Javadoc) */
public synchronized void toDelta(DataOutput out) throws IOException {
out.writeUTF(getId());
out.writeLong(getLastAccessedTime().toEpochMilli());
out.writeLong(getMaxInactiveInterval().getSeconds());
getAttributes().toDelta(out);
clearDelta();
}
/* (non-Javadoc) */
public synchronized void fromDelta(DataInput in) throws IOException {
setId(in.readUTF());
setLastAccessedTime(Instant.ofEpochMilli(in.readLong()));
setMaxInactiveInterval(Duration.ofSeconds(in.readLong()));
getAttributes().fromDelta(in);
clearDelta();
}
}
/**
* {@link GemFireSession} is a GemFire model for a Spring {@link Session} that stores and manages {@link Session}
* state in GemFire. This class implements GemFire's {@link DataSerializable} interface to better handle
* replication of {@link Session} state across the GemFire cluster.
* {@link GemFireSession} is a Abstract Data Type (ADT) for a Spring {@link Session} that stores and manages
* {@link Session} state in Apache Geode or Pivotal GemFire.
*
* @see java.lang.Comparable
* @see org.apache.geode.DataSerializable
* @see org.apache.geode.Delta
* @see org.springframework.session.Session
*/
@SuppressWarnings("serial")
public static class GemFireSession implements Comparable<Session>, DataSerializable, Delta, Session {
public static class GemFireSession<T extends GemFireSessionAttributes> implements Comparable<Session>, Session {
protected static final boolean DEFAULT_ALLOW_JAVA_SERIALIZATION = true;
private static final Duration DEFAULT_MAX_INACTIVE_INTERVAL = Duration.ZERO;
protected static final Duration DEFAULT_MAX_INACTIVE_INTERVAL = Duration.ZERO;
protected static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
@@ -547,8 +582,6 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
private Duration maxInactiveInterval = DEFAULT_MAX_INACTIVE_INTERVAL;
private transient final GemFireSessionAttributes sessionAttributes = new GemFireSessionAttributes(this);
private Instant creationTime;
private Instant lastAccessedTime;
@@ -556,6 +589,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
private String id;
private transient final T sessionAttributes = newSessionAttributes(this);
/* (non-Javadoc) */
protected GemFireSession() {
this(generateId());
@@ -582,13 +617,19 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
/* (non-Javadoc) */
public static GemFireSession copy(Session session) {
return new GemFireSession(session);
return (isUsingDataSerialization() ? new DeltaCapableGemFireSession(session) : new GemFireSession(session));
}
/* (non-Javadoc) */
public static GemFireSession create() {
return create(DEFAULT_MAX_INACTIVE_INTERVAL);
}
/* (non-Javadoc) */
public static GemFireSession create(Duration maxInactiveInterval) {
GemFireSession session = new GemFireSession();
GemFireSession session =
(isUsingDataSerialization() ? new DeltaCapableGemFireSession() : new GemFireSession());
session.setMaxInactiveInterval(maxInactiveInterval);
@@ -596,8 +637,9 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
}
/* (non-Javadoc) */
public static GemFireSession from(Session session) {
return (session instanceof GemFireSession ? (GemFireSession) session : copy(session));
@SuppressWarnings("unchecked")
public static <T extends GemFireSession> T from(Session session) {
return (T) (session instanceof GemFireSession ? (GemFireSession) session : copy(session));
}
/**
@@ -612,32 +654,53 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
/* (non-Javadoc) */
private static String validateId(String id) {
return Optional.ofNullable(id).filter(StringUtils::hasText)
.orElseThrow(() -> new IllegalArgumentException("ID is required"));
.orElseThrow(() -> newIllegalArgumentException("ID is required"));
}
@SuppressWarnings("unchecked")
protected T newSessionAttributes(Object lock) {
return (T) new GemFireSessionAttributes(lock);
}
/* (non-Javadoc) */
protected boolean allowJavaSerialization() {
return DEFAULT_ALLOW_JAVA_SERIALIZATION;
}
@Override
public synchronized String changeSessionId() {
this.id = generateId();
triggerDelta();
return getId();
}
/* (non-Javadoc) */
public synchronized String getId() {
return this.id;
public synchronized void clearDelta() {
this.delta = false;
}
/* (non-Javadoc) */
public synchronized Instant getCreationTime() {
return this.creationTime;
public synchronized boolean hasDelta() {
return (this.delta || this.sessionAttributes.hasDelta());
}
/* (non-Javadoc) */
@SuppressWarnings("unused")
protected void triggerDelta() {
triggerDelta(true);
}
/* (non-Javadoc) */
protected synchronized void triggerDelta(boolean condition) {
this.delta |= condition;
}
synchronized void setId(String id) {
this.id = validateId(id);
}
/* (non-Javadoc) */
public synchronized String getId() {
return this.id;
}
/* (non-Javadoc) */
@@ -661,10 +724,15 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
}
/* (non-Javadoc) */
public GemFireSessionAttributes getAttributes() {
public T getAttributes() {
return this.sessionAttributes;
}
/* (non-Javadoc) */
public synchronized Instant getCreationTime() {
return this.creationTime;
}
/* (non-Javadoc) */
public synchronized boolean isExpired() {
@@ -688,7 +756,7 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
/* (non-Javadoc) */
public synchronized void setLastAccessedTime(Instant lastAccessedTime) {
this.delta |= !ObjectUtils.nullSafeEquals(this.lastAccessedTime, lastAccessedTime);
triggerDelta(!ObjectUtils.nullSafeEquals(this.lastAccessedTime, lastAccessedTime));
this.lastAccessedTime = lastAccessedTime;
}
@@ -699,7 +767,7 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
/* (non-Javadoc) */
public synchronized void setMaxInactiveInterval(Duration maxInactiveIntervalInSeconds) {
this.delta |= !ObjectUtils.nullSafeEquals(this.maxInactiveInterval, maxInactiveIntervalInSeconds);
triggerDelta(!ObjectUtils.nullSafeEquals(this.maxInactiveInterval, maxInactiveIntervalInSeconds));
this.maxInactiveInterval = maxInactiveIntervalInSeconds;
}
@@ -733,79 +801,6 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
return principalName;
}
/* (non-Javadoc) */
public synchronized void toData(DataOutput out) throws IOException {
out.writeUTF(getId());
out.writeLong(getCreationTime().toEpochMilli());
out.writeLong(getLastAccessedTime().toEpochMilli());
out.writeLong(getMaxInactiveInterval().getSeconds());
String principalName = getPrincipalName();
int length = (StringUtils.hasText(principalName) ? principalName.length() : 0);
out.writeInt(length);
if (length > 0) {
out.writeUTF(principalName);
}
writeObject(this.sessionAttributes, out);
this.delta = false;
}
/* (non-Javadoc) */
void writeObject(Object obj, DataOutput out) throws IOException {
DataSerializer.writeObject(obj, out, allowJavaSerialization());
}
/* (non-Javadoc) */
public synchronized void fromData(DataInput in) throws ClassNotFoundException, IOException {
this.id = in.readUTF();
this.creationTime = Instant.ofEpochMilli(in.readLong());
setLastAccessedTime(Instant.ofEpochMilli(in.readLong()));
setMaxInactiveInterval(Duration.ofSeconds(in.readLong()));
int principalNameLength = in.readInt();
if (principalNameLength > 0) {
setPrincipalName(in.readUTF());
}
this.sessionAttributes.from(this.<GemFireSessionAttributes>readObject(in));
this.delta = false;
}
/* (non-Javadoc) */
<T> T readObject(DataInput in) throws ClassNotFoundException, IOException {
return DataSerializer.readObject(in);
}
/* (non-Javadoc) */
public synchronized boolean hasDelta() {
return (this.delta || this.sessionAttributes.hasDelta());
}
/* (non-Javadoc) */
public synchronized void toDelta(DataOutput out) throws IOException {
out.writeLong(getLastAccessedTime().toEpochMilli());
out.writeLong(getMaxInactiveInterval().getSeconds());
getAttributes().toDelta(out);
this.delta = false;
}
/* (non-Javadoc) */
public synchronized void fromDelta(DataInput in) throws IOException {
setLastAccessedTime(Instant.ofEpochMilli(in.readLong()));
setMaxInactiveInterval(Duration.ofSeconds(in.readLong()));
getAttributes().fromDelta(in);
this.delta = false;
}
/* (non-Javadoc) */
@SuppressWarnings("all")
public int compareTo(Session session) {
@@ -851,24 +846,120 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
}
}
/**
* GemFireSessionInstantiator is a GemFire {@link Instantiator} use to instantiate instances
* of the {@link GemFireSession} object used in GemFire's data serialization framework when
* persisting Session state in GemFire.
*/
public static class GemFireSessionInstantiator extends Instantiator {
@SuppressWarnings("unused")
public static class DeltaCapableGemFireSessionAttributes extends GemFireSessionAttributes implements Delta {
public static GemFireSessionInstantiator create() {
return new GemFireSessionInstantiator(GemFireSession.class, 800813552);
private transient final Map<String, Object> sessionAttributeDeltas = new HashMap<>();
public DeltaCapableGemFireSessionAttributes() {
}
public GemFireSessionInstantiator(Class<? extends DataSerializable> type, int id) {
super(type, id);
public DeltaCapableGemFireSessionAttributes(Object lock) {
super(lock);
}
/* (non-Javadoc) */
public Object setAttribute(String attributeName, Object attributeValue) {
synchronized (getLock()) {
if (attributeValue != null) {
Object previousAttributeValue = super.setAttribute(attributeName, attributeValue);
if (!attributeValue.equals(previousAttributeValue)) {
this.sessionAttributeDeltas.put(attributeName, attributeValue);
}
return previousAttributeValue;
}
else {
return removeAttribute(attributeName);
}
}
}
/* (non-Javadoc) */
@Override
public DataSerializable newInstance() {
return new GemFireSession();
public Object removeAttribute(String attributeName) {
synchronized (getLock()) {
return Optional.ofNullable(super.removeAttribute(attributeName))
.map(previousAttributeValue -> {
this.sessionAttributeDeltas.put(attributeName, null);
return previousAttributeValue;
})
.orElse(null);
}
}
/* (non-Javadoc) */
public void toDelta(DataOutput out) throws IOException {
synchronized (getLock()) {
out.writeInt(this.sessionAttributeDeltas.size());
for (Map.Entry<String, Object> entry : this.sessionAttributeDeltas.entrySet()) {
out.writeUTF(entry.getKey());
writeObject(entry.getValue(), out);
}
clearDelta();
}
}
/* (non-Javadoc) */
protected void writeObject(Object value, DataOutput out) throws IOException {
DataSerializer.writeObject(value, out);
}
/* (non-Javadoc) */
@Override
public boolean hasDelta() {
synchronized (getLock()) {
return !this.sessionAttributeDeltas.isEmpty();
}
}
/* (non-Javadoc) */
public void fromDelta(DataInput in) throws InvalidDeltaException, IOException {
synchronized (getLock()) {
try {
int count = in.readInt();
Map<String, Object> deltas = new HashMap<>(count);
while (count-- > 0) {
deltas.put(in.readUTF(), readObject(in));
}
deltas.forEach((key, value) -> {
setAttribute(key, value);
this.sessionAttributeDeltas.remove(key);
});
}
catch (ClassNotFoundException cause) {
throw new InvalidDeltaException("Class type in data not found", cause);
}
}
}
/* (non-Javadoc) */
protected <T> T readObject(DataInput in) throws ClassNotFoundException, IOException {
return DataSerializer.readObject(in);
}
/* (non-Javadoc) */
@Override
public void clearDelta() {
synchronized (getLock()) {
this.sessionAttributeDeltas.clear();
}
}
}
@@ -885,13 +976,9 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
* @see org.apache.geode.Delta
*/
@SuppressWarnings("serial")
public static class GemFireSessionAttributes extends AbstractMap<String, Object>
implements DataSerializable, Delta {
protected static final boolean DEFAULT_ALLOW_JAVA_SERIALIZATION = true;
public static class GemFireSessionAttributes extends AbstractMap<String, Object> {
private transient final Map<String, Object> sessionAttributes = new HashMap<>();
private transient final Map<String, Object> sessionAttributeDeltas = new HashMap<>();
private transient final Object lock;
@@ -916,52 +1003,40 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
}
/* (non-Javadoc) */
public void setAttribute(String attributeName, Object attributeValue) {
protected Object getLock() {
return this.lock;
}
synchronized (this.lock) {
if (attributeValue != null) {
if (!attributeValue.equals(this.sessionAttributes.put(attributeName, attributeValue))) {
this.sessionAttributeDeltas.put(attributeName, attributeValue);
}
}
else {
removeAttribute(attributeName);
}
/* (non-Javadoc) */
public Object setAttribute(String attributeName, Object attributeValue) {
synchronized (getLock()) {
return (attributeValue != null ? this.sessionAttributes.put(attributeName, attributeValue)
: removeAttribute(attributeName));
}
}
/* (non-Javadoc) */
public void removeAttribute(String attributeName) {
synchronized (this.lock) {
if (this.sessionAttributes.remove(attributeName) != null) {
this.sessionAttributeDeltas.put(attributeName, null);
}
public Object removeAttribute(String attributeName) {
synchronized (getLock()) {
return this.sessionAttributes.remove(attributeName);
}
}
/* (non-Javadoc) */
@SuppressWarnings("unchecked")
public <T> T getAttribute(String attributeName) {
synchronized (this.lock) {
synchronized (getLock()) {
return (T) this.sessionAttributes.get(attributeName);
}
}
/* (non-Javadoc) */
public Set<String> getAttributeNames() {
synchronized (this.lock) {
synchronized (getLock()) {
return Collections.unmodifiableSet(new HashSet<>(this.sessionAttributes.keySet()));
}
}
/* (non-Javadoc) */
protected boolean allowJavaSerialization() {
return DEFAULT_ALLOW_JAVA_SERIALIZATION;
}
/* (non-Javadoc); NOTE: entrySet implementation is not Thread-safe. */
@Override
@SuppressWarnings("all")
@@ -982,109 +1057,39 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
};
}
/* (non-Javadoc) */
public void clearDelta() {
}
/* (non-Javadoc) */
public void from(Session session) {
synchronized (this.lock) {
synchronized (getLock()) {
session.getAttributeNames().forEach(attributeName ->
setAttribute(attributeName, session.getAttribute(attributeName)));
}
}
/* (non-Javadoc) */
public void from(Map<String, Object> map) {
synchronized (getLock()) {
map.forEach(this::setAttribute);
}
}
/* (non-Javadoc) */
public void from(GemFireSessionAttributes sessionAttributes) {
synchronized (this.lock) {
synchronized (getLock()) {
sessionAttributes.getAttributeNames().forEach(attributeName ->
setAttribute(attributeName, sessionAttributes.getAttribute(attributeName)));
}
}
/* (non-Javadoc) */
public void toData(DataOutput out) throws IOException {
synchronized (this.lock) {
Set<String> attributeNames = getAttributeNames();
out.writeInt(attributeNames.size());
for (String attributeName : attributeNames) {
out.writeUTF(attributeName);
writeObject(getAttribute(attributeName), out);
}
}
}
/* (non-Javadoc) */
void writeObject(Object obj, DataOutput out) throws IOException {
DataSerializer.writeObject(obj, out, allowJavaSerialization());
}
/* (non-Javadoc) */
public void fromData(DataInput in) throws IOException, ClassNotFoundException {
synchronized (this.lock) {
for (int count = in.readInt(); count > 0; count--) {
setAttribute(in.readUTF(), readObject(in));
}
this.sessionAttributeDeltas.clear();
}
}
/* (non-Javadoc) */
<T> T readObject(DataInput in) throws ClassNotFoundException, IOException {
return DataSerializer.readObject(in);
}
/* (non-Javadoc) */
public boolean hasDelta() {
synchronized (this.lock) {
return !this.sessionAttributeDeltas.isEmpty();
}
}
/* (non-Javadoc) */
public void toDelta(DataOutput out) throws IOException {
synchronized (this.lock) {
out.writeInt(this.sessionAttributeDeltas.size());
for (Map.Entry<String, Object> entry : this.sessionAttributeDeltas.entrySet()) {
out.writeUTF(entry.getKey());
writeObject(entry.getValue(), out);
}
this.sessionAttributeDeltas.clear();
}
}
/* (non-Javadoc) */
public void fromDelta(DataInput in) throws InvalidDeltaException, IOException {
synchronized (this.lock) {
try {
int count = in.readInt();
Map<String, Object> deltas = new HashMap<>(count);
while (count-- > 0) {
deltas.put(in.readUTF(), readObject(in));
}
deltas.forEach((key, value) -> {
setAttribute(key, value);
this.sessionAttributeDeltas.remove(key);
});
}
catch (ClassNotFoundException e) {
throw new InvalidDeltaException("class type in data not found", e);
}
}
return false;
}
@Override
@@ -1092,25 +1097,4 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
return this.sessionAttributes.toString();
}
}
/**
* GemFireSessionAttributesInstantiator is a GemFire {@link Instantiator} use to instantiate instances
* of the {@link GemFireSessionAttributes} object used in GemFire's data serialization framework when
* persisting Session attributes state in GemFire.
*/
public static class GemFireSessionAttributesInstantiator extends Instantiator {
public static GemFireSessionAttributesInstantiator create() {
return new GemFireSessionAttributesInstantiator(GemFireSessionAttributes.class, 800828008);
}
public GemFireSessionAttributesInstantiator(Class<? extends DataSerializable> type, int id) {
super(type, id);
}
@Override
public DataSerializable newInstance() {
return new GemFireSessionAttributes();
}
}
}

View File

@@ -21,6 +21,8 @@ import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newI
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import org.apache.geode.DataSerializer;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.ExpirationAction;
@@ -43,7 +45,6 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Import;
@@ -408,6 +409,14 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
.orElse(DEFAULT_SESSION_SERIALIZER_BEAN_NAME);
}
/**
* Determine whether the configured serialization strategy is using Apache Geode / Pivotal GemFire's
* DataSerialization framework.
*
* @return a boolean value indicating whether the configured serialization strategy is using Apache Geode
* / Pivotal GemFire's DataSerialization framework.
* @see #getSessionSerializerBeanName()
*/
protected boolean isUsingDataSerialization() {
return SESSION_DATA_SERIALIZER_BEAN_NAME.equals(getSessionSerializerBeanName());
}
@@ -444,13 +453,20 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
setSessionSerializerBeanName(
enableGemFireHttpSessionAttributes.getString("sessionSerializerBeanName"));
}
@PostConstruct
public void init() {
System.err.printf("SETTING SYSTEM PROPERTY (%s) TO (%s) %n", SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME,
getSessionSerializerBeanName());
System.setProperty(SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME, getSessionSerializerBeanName());
getBeanFactory().registerAlias(getSessionSerializerBeanName(), SESSION_SERIALIZER_REGISTERED_ALIAS);
}
@Bean
@DependsOn({ SESSION_DATA_SERIALIZER_BEAN_NAME, SESSION_PDX_SERIALIZER_BEAN_NAME })
public ClientCacheConfigurer sessionClientCacheConfigurer(
@Qualifier(SESSION_SERIALIZER_REGISTERED_ALIAS) SessionSerializer sessionSerializer) {
@@ -458,6 +474,7 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
}
@Bean
@DependsOn({ SESSION_DATA_SERIALIZER_BEAN_NAME, SESSION_PDX_SERIALIZER_BEAN_NAME })
public PeerCacheConfigurer sessionPeerCacheConfigurer(
@Qualifier(SESSION_SERIALIZER_REGISTERED_ALIAS) SessionSerializer sessionSerializer) {
@@ -618,13 +635,13 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
}
@Bean(SESSION_DATA_SERIALIZER_BEAN_NAME)
@Conditional(DataSerializableSessionSerializerCondition.class)
//@Conditional(DataSerializableSessionSerializerCondition.class)
public Object sessionDataSerializer() {
return new PdxSerializableSessionSerializer();
}
@Bean(SESSION_PDX_SERIALIZER_BEAN_NAME)
@Conditional(PdxSerializableSessionSerializerCondition.class)
//@Conditional(PdxSerializableSessionSerializerCondition.class)
public Object sessionPdxSerializer() {
return new DataSerializableSessionSerializer();
}
@@ -683,6 +700,15 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
System.err.printf("%1$s-System.getProperty(%2$s) = '%3$s'%n", getClass().getSimpleName(),
SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME,
System.getProperty(SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME));
System.err.printf("%1$s-Environment.get(%2$s) = '%3$s'%n", getClass().getSimpleName(),
SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME,
context.getEnvironment().getProperty(SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME));
return SESSION_DATA_SERIALIZER_BEAN_NAME
.equals(context.getEnvironment().getProperty(SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME));
}
@@ -692,6 +718,15 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
System.err.printf("%1$s-System.getProperty(%2$s) = '%3$s'%n", getClass().getSimpleName(),
SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME,
System.getProperty(SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME));
System.err.printf("%1$s-Environment.get(%2$s) = '%3$s'%n", getClass().getSimpleName(),
SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME,
context.getEnvironment().getProperty(SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME));
return SESSION_PDX_SERIALIZER_BEAN_NAME
.equals(context.getEnvironment().getProperty(SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME));
}

View File

@@ -27,28 +27,6 @@ import java.util.Optional;
*/
public interface SessionSerializer<T, IN, OUT> {
/**
* Determines whether the given {@link Object} can be de/serialized by this {@link SessionSerializer}.
*
* @param obj {@link Object} to evaluate for whether de/serialization is supported.
* @return a boolean value indicating whether the specified {@link Object} can be de/serialized
* by this {@link SessionSerializer}.
* @see #canSerialize(Class)
*/
default boolean canSerialize(Object obj) {
return Optional.ofNullable(obj).map(Object::getClass).map(this::canSerialize).orElse(false);
}
/**
* Determines whether the given {@link Class type} can be de/serialized by this {@link SessionSerializer}.
*
* @param type {@link Class} to evaluate for whether de/serialization is supported.
* @return a boolean value indicating whether the specified {@link Class type} can be de/serialized
* by this {@link SessionSerializer}.
* @see #canSerialize(Object)
*/
boolean canSerialize(Class<?> type);
/**
* Serializes the given {@link Object} to the provided {@code out} stream.
*
@@ -65,4 +43,26 @@ public interface SessionSerializer<T, IN, OUT> {
*/
T deserialize(IN in);
/**
* Determines whether the given {@link Class type} can be de/serialized by this {@link SessionSerializer}.
*
* @param type {@link Class} to evaluate for whether de/serialization is supported.
* @return a boolean value indicating whether the specified {@link Class type} can be de/serialized
* by this {@link SessionSerializer}.
* @see #canSerialize(Object)
*/
boolean canSerialize(Class<?> type);
/**
* Determines whether the given {@link Object} can be de/serialized by this {@link SessionSerializer}.
*
* @param obj {@link Object} to evaluate for whether de/serialization is supported.
* @return a boolean value indicating whether the specified {@link Object} can be de/serialized
* by this {@link SessionSerializer}.
* @see #canSerialize(Class)
*/
default boolean canSerialize(Object obj) {
return Optional.ofNullable(obj).map(Object::getClass).map(this::canSerialize).orElse(false);
}
}

View File

@@ -42,6 +42,8 @@ import org.springframework.session.data.gemfire.serialization.SessionSerializer;
public abstract class AbstractDataSerializableSessionSerializer<T> extends DataSerializer
implements SessionSerializer<T, DataInput, DataOutput> {
protected static final boolean DEFAULT_ALLOW_JAVA_SERIALIZATION = true;
@Override
public int getId() {
return 0x0A11ACE5;
@@ -52,6 +54,10 @@ public abstract class AbstractDataSerializableSessionSerializer<T> extends DataS
return new Class[0];
}
protected boolean allowJavaSerialization() {
return DEFAULT_ALLOW_JAVA_SERIALIZATION;
}
@Override
@SuppressWarnings("unchecked")
public boolean canSerialize(Class<?> type) {
@@ -72,11 +78,23 @@ public abstract class AbstractDataSerializableSessionSerializer<T> extends DataS
.orElse(false);
}
public void serializeObject(Object obj, DataOutput out) throws IOException {
serializeObject(obj, out, allowJavaSerialization());
}
public void serializeObject(Object obj, DataOutput out, boolean allowJavaSerialization) throws IOException {
writeObject(obj, out, allowJavaSerialization);
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
return deserialize(in);
}
public <T> T deserializeObject(DataInput in) throws ClassNotFoundException, IOException {
return DataSerializer.readObject(in);
}
protected <T> T safeRead(DataInput in, DataInputReader<T> reader) {
try {
return reader.doRead(in);

View File

@@ -24,8 +24,6 @@ import java.io.DataInput;
import java.io.DataOutput;
import java.util.Set;
import org.apache.geode.DataSerializer;
import org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer;
/**
@@ -64,8 +62,10 @@ public class DataSerializableSessionAttributesSerializer
attributeNames.forEach(attributeName -> {
safeWrite(out, output -> output.writeUTF(attributeName));
safeWrite(out, output -> writeObject(sessionAttributes.getAttribute(attributeName), output));
safeWrite(out, output -> serializeObject(sessionAttributes.getAttribute(attributeName), output));
});
sessionAttributes.clearDelta();
}
}
@@ -75,9 +75,11 @@ public class DataSerializableSessionAttributesSerializer
GemFireSessionAttributes sessionAttributes = GemFireSessionAttributes.create();
for (int count = safeRead(in, DataInput::readInt); count > 0; count--) {
sessionAttributes.setAttribute(safeRead(in, DataInput::readUTF), safeRead(in, DataSerializer::readObject));
sessionAttributes.setAttribute(safeRead(in, DataInput::readUTF), safeRead(in, this::deserializeObject));
}
sessionAttributes.clearDelta();
return sessionAttributes;
}
}

View File

@@ -25,8 +25,6 @@ import java.time.Instant;
import java.util.Collections;
import java.util.Set;
import org.apache.geode.DataSerializer;
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSession;
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes;
import org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer;
@@ -78,7 +76,10 @@ public class DataSerializableSessionSerializer extends AbstractDataSerializableS
safeWrite(out, output -> output.writeUTF(principalName));
}
safeWrite(out, output -> writeObject(session.getAttributes(), out));
safeWrite(out, output -> serializeObject(session.getAttributes(), out));
session.clearDelta();
session.getAttributes().clearDelta();
}
}
@@ -119,7 +120,9 @@ public class DataSerializableSessionSerializer extends AbstractDataSerializableS
session.setPrincipalName(safeRead(in, DataInput::readUTF));
}
session.getAttributes().from(this.<GemFireSessionAttributes>safeRead(in, DataSerializer::readObject));
session.getAttributes().from(this.<GemFireSessionAttributes>safeRead(in, this::deserializeObject));
session.getAttributes().clearDelta();
session.clearDelta();
return session;
}

View File

@@ -17,11 +17,12 @@
package org.springframework.session.data.gemfire.serialization.pdx.provider;
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSession;
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes;
import java.time.Duration;
import java.time.Instant;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -56,11 +57,16 @@ public class PdxSerializableSessionSerializer extends AbstractPdxSerializableSes
writer.writeLong("lastAccessedTime", session.getLastAccessedTime().toEpochMilli());
writer.writeLong("maxInactiveIntervalInSeconds", session.getMaxInactiveInterval().getSeconds());
writer.writeString("principalName", session.getPrincipalName());
writer.writeObject("attributes", session.getAttributes());
writer.writeObject("attributes", newMap(session.getAttributes()));
}
}
protected <K, V> Map<K, V> newMap(Map<K, V> map) {
return new HashMap<>(map);
}
@Override
@SuppressWarnings("unchecked")
public GemFireSession deserialize(PdxReader reader) {
GemFireSession session = GemFireSession.from(new AbstractSession() {
@@ -92,7 +98,7 @@ public class PdxSerializableSessionSerializer extends AbstractPdxSerializableSes
});
session.setPrincipalName(reader.readString("principalName"));
session.getAttributes().from((GemFireSessionAttributes) reader.readObject("attributes"));
session.getAttributes().from((Map<String, Object>) reader.readObject("attributes"));
return session;
}

View File

@@ -25,6 +25,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@@ -57,7 +58,8 @@ public class ComposablePdxSerializer implements Iterable<PdxSerializer>, PdxSeri
public static PdxSerializer compose(Iterable<PdxSerializer> pdxSerializers) {
List<PdxSerializer> pdxSerializerList =
stream(nullSafeIterable(pdxSerializers).spliterator(), false).collect(Collectors.toList());
stream(nullSafeIterable(pdxSerializers).spliterator(), false)
.filter(Objects::nonNull).collect(Collectors.toList());
return (pdxSerializerList.isEmpty() ? null
: (pdxSerializerList.size() == 1 ? pdxSerializerList.get(0)

View File

@@ -23,80 +23,84 @@ import java.util.Set;
import org.springframework.session.Session;
/**
* The AbstractSession class...
* The {@link AbstractSession} abstract class is a base implementation of the {@link Session} interface
* to simplify the implementation of various {@link Session} types and their capabilities.
*
* @author John Blum
* @since 1.0.0
* @see org.springframework.session.data.gemfire.support.AbstractSession
* @since 2.0.0
*/
public class AbstractSession implements Session {
public static final String NOT_IMPLEMENTED = "Not Implemented";
@Override
public String getId() {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public void setAttribute(String attributeName, Object attributeValue) {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public <T> T getAttribute(String attributeName) {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public <T> T getAttributeOrDefault(String name, T defaultValue) {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public <T> T getRequiredAttribute(String name) {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public Set<String> getAttributeNames() {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public boolean isExpired() {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public Instant getCreationTime() {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public void setLastAccessedTime(Instant lastAccessedTime) {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public Instant getLastAccessedTime() {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public void setMaxInactiveInterval(Duration interval) {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public Duration getMaxInactiveInterval() {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public String changeSessionId() {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@Override
public void removeAttribute(String attributeName) {
throw new UnsupportedOperationException("Not Implemented");
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
}

View File

@@ -33,13 +33,14 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.springframework.data.gemfire.util.CollectionUtils.asSet;
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.DeltaCapableGemFireSession;
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.DeltaCapableGemFireSessionAttributes;
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSession;
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
@@ -104,7 +105,7 @@ import org.apache.commons.logging.Log;
* @see edu.umd.cs.mtc.TestFramework
*/
@RunWith(MockitoJUnitRunner.class)
public class AbstractGemFireOperationsSessionRepositoryTest {
public class AbstractGemFireOperationsSessionRepositoryTests {
protected static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600;
@@ -123,20 +124,11 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Override
Log newLogger() {
return AbstractGemFireOperationsSessionRepositoryTest.this.mockLog;
return mockLog;
}
});
}
private static <E> Set<E> asSet(E... elements) {
Set<E> set = new HashSet<>(elements.length);
Collections.addAll(set, elements);
return set;
}
@SuppressWarnings("unchecked")
protected <K, V> EntryEvent<K, V> mockEntryEvent(Operation operation, K key, V oldValue, V newValue) {
@@ -151,11 +143,11 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
}
@SuppressWarnings("unchecked")
protected <K, V> Region mockRegion(String name, DataPolicy dataPolicy) {
protected <K, V> Region<K, V> mockRegion(String name, DataPolicy dataPolicy) {
Region<K, V> mockRegion = mock(Region.class, name);
RegionAttributes<K, V> mockRegionAttributes = mock(RegionAttributes.class);
RegionAttributes<K, V> mockRegionAttributes = mockRegionAttributes(name);
given(mockRegion.getAttributes()).willReturn(mockRegionAttributes);
given(mockRegionAttributes.getDataPolicy()).willReturn(dataPolicy);
@@ -163,6 +155,11 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
return mockRegion;
}
@SuppressWarnings("unchecked")
protected <K, V> RegionAttributes<K, V> mockRegionAttributes(String name) {
return mock(RegionAttributes.class, name);
}
protected Session mockSession(String sessionId, long creationAndLastAccessedTime,
long maxInactiveIntervalInSeconds) {
@@ -387,7 +384,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource())
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTest.this.sessionRepository);
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isEqualTo(mockSession);
assertThat(sessionEvent.getSessionId()).isEqualTo(sessionId);
@@ -430,7 +427,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource())
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTest.this.sessionRepository);
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isNull();
assertThat(sessionEvent.getSessionId()).isEqualTo(sessionId);
@@ -553,7 +550,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource())
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTest.this.sessionRepository);
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isEqualTo(mockSession);
assertThat(sessionEvent.getSessionId()).isEqualTo(sessionId);
@@ -593,7 +590,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource())
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTest.this.sessionRepository);
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isNull();
assertThat(sessionEvent.getSessionId()).isEqualTo(sessionId);
@@ -632,7 +629,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource())
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTest.this.sessionRepository);
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isNull();
assertThat(sessionEvent.getSessionId()).isEqualTo(sessionId);
@@ -674,7 +671,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource())
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTest.this.sessionRepository);
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isEqualTo(mockSession);
assertThat(sessionEvent.getSessionId()).isEqualTo(sessionId);
@@ -713,7 +710,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource())
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTest.this.sessionRepository);
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isNull();
assertThat(sessionEvent.getSessionId()).isEqualTo(sessionId);
@@ -752,7 +749,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource())
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTest.this.sessionRepository);
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isNull();
assertThat(sessionEvent.getSessionId()).isEqualTo(sessionId);
@@ -802,7 +799,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource())
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTest.this.sessionRepository);
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isEqualTo(mockSession);
assertThat(sessionEvent.getSessionId()).isEqualTo(sessionId);
@@ -874,7 +871,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource())
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTest.this.sessionRepository);
.isEqualTo(AbstractGemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isEqualTo(mockSession);
assertThat(sessionEvent.getSessionId()).isEqualTo(sessionId);
@@ -906,7 +903,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource()).isEqualTo(AbstractGemFireOperationsSessionRepositoryTest.this.sessionRepository);
assertThat(sessionEvent.getSource()).isEqualTo(AbstractGemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isNull();
assertThat(sessionEvent.getSessionId()).isEqualTo(sessionId);
@@ -956,8 +953,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
Instant beforeOrAtCreationTime = Instant.now();
AbstractGemFireOperationsSessionRepository.GemFireSession session =
new AbstractGemFireOperationsSessionRepository.GemFireSession();
GemFireSession session = new GemFireSession();
assertThat(session.getId()).isNotNull();
assertThat(session.getCreationTime().compareTo(beforeOrAtCreationTime)).isGreaterThanOrEqualTo(0);
@@ -972,8 +968,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
Instant beforeOrAtCreationTime = Instant.now();
AbstractGemFireOperationsSessionRepository.GemFireSession session =
new AbstractGemFireOperationsSessionRepository.GemFireSession("1");
GemFireSession session = new GemFireSession("1");
assertThat(session.getId()).isEqualTo("1");
assertThat(session.getCreationTime().compareTo(beforeOrAtCreationTime)).isGreaterThanOrEqualTo(0);
@@ -986,7 +981,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test(expected = IllegalArgumentException.class)
public void constructGemFireSessionWithUnspecifiedId() {
try {
new AbstractGemFireOperationsSessionRepository.GemFireSession(" ");
new GemFireSession(" ");
}
catch (IllegalArgumentException expected) {
assertThat(expected).hasMessage("ID is required");
@@ -1013,8 +1008,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
given(mockSession.getAttribute(eq("attrOne"))).willReturn("testOne");
given(mockSession.getAttribute(eq("attrTwo"))).willReturn("testTwo");
AbstractGemFireOperationsSessionRepository.GemFireSession gemfireSession =
new AbstractGemFireOperationsSessionRepository.GemFireSession(mockSession);
GemFireSession gemfireSession = new GemFireSession(mockSession);
assertThat(gemfireSession.getId()).isEqualTo("2");
assertThat(gemfireSession.getCreationTime()).isEqualTo(expectedCreationTime);
@@ -1036,7 +1030,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test(expected = IllegalArgumentException.class)
public void constructGemFireSessionWithNullSession() {
try {
new AbstractGemFireOperationsSessionRepository.GemFireSession((Session) null);
new GemFireSession((Session) null);
}
catch (IllegalArgumentException expected) {
assertThat(expected).hasMessage("The Session to copy cannot be null");
@@ -1053,8 +1047,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
Duration maxInactiveInterval = Duration.ofSeconds(120L);
AbstractGemFireOperationsSessionRepository.GemFireSession session =
AbstractGemFireOperationsSessionRepository.GemFireSession.create(maxInactiveInterval);
GemFireSession<?> session = GemFireSession.create(maxInactiveInterval);
assertThat(session).isNotNull();
assertThat(session.getId()).isNotNull();
@@ -1062,7 +1055,23 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(session.getLastAccessedTime()).isEqualTo(session.getCreationTime());
assertThat(session.getMaxInactiveInterval()).isEqualTo(maxInactiveInterval);
assertThat(session.getAttributeNames()).isNotNull();
assertThat(session.getAttributeNames().isEmpty()).isTrue();
assertThat(session.getAttributeNames()).isEmpty();
}
@Test
public void createNewGemFireSessionWithDefaultMaxInactiveInterval() {
Instant beforeOrAtCreationTime = Instant.now();
GemFireSession<?> session = GemFireSession.create();
assertThat(session).isNotNull();
assertThat(session.getId()).isNotNull();
assertThat(session.getCreationTime().compareTo(beforeOrAtCreationTime)).isGreaterThanOrEqualTo(0);
assertThat(session.getLastAccessedTime()).isEqualTo(session.getCreationTime());
assertThat(session.getMaxInactiveInterval()).isEqualTo(GemFireSession.DEFAULT_MAX_INACTIVE_INTERVAL);
assertThat(session.getAttributeNames()).isNotNull();
assertThat(session.getAttributeNames()).isEmpty();
}
@Test
@@ -1078,8 +1087,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
given(mockSession.getAttributeNames()).willReturn(Collections.emptySet());
AbstractGemFireOperationsSessionRepository.GemFireSession gemfireSession =
AbstractGemFireOperationsSessionRepository.GemFireSession.from(mockSession);
GemFireSession<?> gemfireSession = GemFireSession.from(mockSession);
assertThat(gemfireSession).isNotNull();
assertThat(gemfireSession.getId()).isEqualTo("4");
@@ -1100,11 +1108,9 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test
public void fromExistingGemFireSessionIsGemFireSession() {
AbstractGemFireOperationsSessionRepository.GemFireSession gemfireSession =
AbstractGemFireOperationsSessionRepository.GemFireSession.create(Duration.ofSeconds(300));
GemFireSession<?> gemfireSession = GemFireSession.create();
AbstractGemFireOperationsSessionRepository.GemFireSession fromGemFireSession =
AbstractGemFireOperationsSessionRepository.GemFireSession.from(gemfireSession);
GemFireSession<?> fromGemFireSession = GemFireSession.from(gemfireSession);
assertThat(fromGemFireSession).isSameAs(gemfireSession);
}
@@ -1112,12 +1118,10 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test
public void setGetAndRemoveAttribute() {
AbstractGemFireOperationsSessionRepository.GemFireSession session =
AbstractGemFireOperationsSessionRepository.GemFireSession.create(Duration.ofSeconds(60));
GemFireSession<?> session = GemFireSession.create();
assertThat(session).isNotNull();
assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(60));
assertThat(session.getAttributeNames().isEmpty()).isTrue();
assertThat(session.getAttributeNames()).isEmpty();
session.setAttribute("attrOne", "testOne");
@@ -1149,8 +1153,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
Duration expectedMaxInactiveIntervalInSeconds = Duration.ofSeconds(-1);
AbstractGemFireOperationsSessionRepository.GemFireSession session =
AbstractGemFireOperationsSessionRepository.GemFireSession.create(expectedMaxInactiveIntervalInSeconds);
GemFireSession<?> session = GemFireSession.create(expectedMaxInactiveIntervalInSeconds);
assertThat(session).isNotNull();
assertThat(session.getMaxInactiveInterval()).isEqualTo(expectedMaxInactiveIntervalInSeconds);
@@ -1162,8 +1165,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
Duration expectedMaxInactiveIntervalInSeconds = Duration.ZERO;
AbstractGemFireOperationsSessionRepository.GemFireSession session =
AbstractGemFireOperationsSessionRepository.GemFireSession.create(expectedMaxInactiveIntervalInSeconds);
GemFireSession<?> session = GemFireSession.create(expectedMaxInactiveIntervalInSeconds);
assertThat(session).isNotNull();
assertThat(session.getMaxInactiveInterval()).isEqualTo(expectedMaxInactiveIntervalInSeconds);
@@ -1175,12 +1177,11 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
long expectedMaxInactiveIntervalInSeconds = TimeUnit.HOURS.toSeconds(2);
AbstractGemFireOperationsSessionRepository.GemFireSession session =
AbstractGemFireOperationsSessionRepository.GemFireSession.create(
Duration.ofSeconds(expectedMaxInactiveIntervalInSeconds));
GemFireSession<?> session = GemFireSession.create(Duration.ofSeconds(expectedMaxInactiveIntervalInSeconds));
assertThat(session).isNotNull();
assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(expectedMaxInactiveIntervalInSeconds));
assertThat(session.getMaxInactiveInterval())
.isEqualTo(Duration.ofSeconds(expectedMaxInactiveIntervalInSeconds));
Instant now = Instant.now();
@@ -1195,12 +1196,11 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
int expectedMaxInactiveIntervalInSeconds = 60;
AbstractGemFireOperationsSessionRepository.GemFireSession session =
AbstractGemFireOperationsSessionRepository.GemFireSession.create(
Duration.ofSeconds(expectedMaxInactiveIntervalInSeconds));
GemFireSession<?> session = GemFireSession.create(Duration.ofSeconds(expectedMaxInactiveIntervalInSeconds));
assertThat(session).isNotNull();
assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(expectedMaxInactiveIntervalInSeconds));
assertThat(session.getMaxInactiveInterval())
.isEqualTo(Duration.ofSeconds(expectedMaxInactiveIntervalInSeconds));
Instant twoHoursAgo = Instant.ofEpochMilli(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(2));
@@ -1213,8 +1213,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test
public void setAndGetPrincipalName() {
AbstractGemFireOperationsSessionRepository.GemFireSession session =
AbstractGemFireOperationsSessionRepository.GemFireSession.create(Duration.ZERO);
GemFireSession<?> session = GemFireSession.create(Duration.ZERO);
assertThat(session).isNotNull();
assertThat(session.getPrincipalName()).isNull();
@@ -1236,141 +1235,6 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(session.getPrincipalName()).isNull();
}
@Test
public void sessionToData() throws Exception {
@SuppressWarnings("serial")
AbstractGemFireOperationsSessionRepository.GemFireSession session =
new AbstractGemFireOperationsSessionRepository.GemFireSession("1") {
@Override
void writeObject(Object obj, DataOutput out) throws IOException {
assertThat(obj).isInstanceOf(AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes.class);
assertThat(out).isNotNull();
}
};
session.setLastAccessedTime(Instant.ofEpochMilli(123L));
session.setMaxInactiveInterval(Duration.ofSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS));
session.setPrincipalName("jblum");
DataOutput mockDataOutput = mock(DataOutput.class);
session.toData(mockDataOutput);
verify(mockDataOutput, times(1)).writeUTF(eq("1"));
verify(mockDataOutput, times(1)).writeLong(eq(session.getCreationTime().toEpochMilli()));
verify(mockDataOutput, times(1)).writeLong(eq(session.getLastAccessedTime().toEpochMilli()));
verify(mockDataOutput, times(1)).writeLong(eq(session.getMaxInactiveInterval().getSeconds()));
verify(mockDataOutput, times(1)).writeInt(eq("jblum".length()));
verify(mockDataOutput, times(1)).writeUTF(eq(session.getPrincipalName()));
}
@Test
public void sessionFromData() throws Exception {
long expectedCreationTime = 1L;
long expectedLastAccessedTime = 2L;
long expectedMaxInactiveIntervalInSeconds = TimeUnit.HOURS.toSeconds(6);
String expectedPrincipalName = "jblum";
String expectedSessionId = "2";
DataInput mockDataInput = mock(DataInput.class);
given(mockDataInput.readUTF()).willReturn(expectedSessionId).willReturn(expectedPrincipalName);
given(mockDataInput.readLong()).willReturn(expectedCreationTime).willReturn(expectedLastAccessedTime)
.willReturn(expectedMaxInactiveIntervalInSeconds);
given(mockDataInput.readInt()).willReturn(expectedPrincipalName.length());
@SuppressWarnings("serial")
AbstractGemFireOperationsSessionRepository.GemFireSession session =
new AbstractGemFireOperationsSessionRepository.GemFireSession("1") {
@Override
@SuppressWarnings("unchecked")
<T> T readObject(DataInput in) throws ClassNotFoundException, IOException {
assertThat(in).isNotNull();
AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes sessionAttributes =
new AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes();
sessionAttributes.setAttribute("attrOne", "testOne");
sessionAttributes.setAttribute("attrTwo", "testTwo");
return (T) sessionAttributes;
}
};
session.fromData(mockDataInput);
Set<String> expectedAttributeNames =
asSet("attrOne", "attrTwo", FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
assertThat(session.getId()).isEqualTo(expectedSessionId);
assertThat(session.getCreationTime()).isEqualTo(Instant.ofEpochMilli(expectedCreationTime));
assertThat(session.getLastAccessedTime()).isEqualTo(Instant.ofEpochMilli(expectedLastAccessedTime));
assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(expectedMaxInactiveIntervalInSeconds));
assertThat(session.getPrincipalName()).isEqualTo(expectedPrincipalName);
assertThat(session.getAttributeNames()).hasSize(3);
assertThat(session.getAttributeNames()).containsAll(expectedAttributeNames);
assertThat(session.<String>getAttribute("attrOne")).isEqualTo("testOne");
assertThat(session.<String>getAttribute("attrTwo")).isEqualTo("testTwo");
assertThat(session.<String>getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME))
.isEqualTo(expectedPrincipalName);
verify(mockDataInput, times(2)).readUTF();
verify(mockDataInput, times(3)).readLong();
verify(mockDataInput, times(1)).readInt();
}
@Test
public void sessionToDataThenFromDataWhenPrincipalNameIsNullGetsHandledProperly()
throws ClassNotFoundException, IOException {
Instant beforeOrAtCreationTime = Instant.now();
@SuppressWarnings("serial")
AbstractGemFireOperationsSessionRepository.GemFireSession expectedSession =
new AbstractGemFireOperationsSessionRepository.GemFireSession("123") {
@Override
void writeObject(Object obj, DataOutput out) throws IOException {
assertThat(obj).isInstanceOf(AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes.class);
assertThat(out).isNotNull();
}
};
assertThat(expectedSession.getId()).isEqualTo("123");
assertThat(expectedSession.getCreationTime().compareTo(beforeOrAtCreationTime)).isGreaterThanOrEqualTo(0);
assertThat(expectedSession.getLastAccessedTime().compareTo(beforeOrAtCreationTime)).isGreaterThanOrEqualTo(0);
assertThat(expectedSession.getMaxInactiveInterval()).isEqualTo(Duration.ZERO);
assertThat(expectedSession.getPrincipalName()).isNull();
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
expectedSession.toData(new DataOutputStream(outBytes));
@SuppressWarnings("serial")
AbstractGemFireOperationsSessionRepository.GemFireSession deserializedSession =
new AbstractGemFireOperationsSessionRepository.GemFireSession("0") {
@Override
@SuppressWarnings("unchecked")
<T> T readObject(DataInput in) throws ClassNotFoundException, IOException {
return (T) new AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes();
}
};
deserializedSession.fromData(new DataInputStream(new ByteArrayInputStream(outBytes.toByteArray())));
assertThat(deserializedSession).isEqualTo(expectedSession);
assertThat(deserializedSession.getCreationTime()).isEqualTo(expectedSession.getCreationTime());
assertThat(deserializedSession.getLastAccessedTime()).isEqualTo(expectedSession.getLastAccessedTime());
assertThat(deserializedSession.getMaxInactiveInterval()).isEqualTo(expectedSession.getMaxInactiveInterval());
assertThat(deserializedSession.getPrincipalName()).isNull();
}
@Test
public void hasDeltaWhenNoSessionChangesIsFalse() {
assertThat(new AbstractGemFireOperationsSessionRepository.GemFireSession().hasDelta()).isFalse();
@@ -1379,8 +1243,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test
public void hasDeltaWhenSessionAttributesChangeIsTrue() {
AbstractGemFireOperationsSessionRepository.GemFireSession session =
new AbstractGemFireOperationsSessionRepository.GemFireSession();
GemFireSession session = new DeltaCapableGemFireSession();
assertThat(session.hasDelta()).isFalse();
@@ -1439,15 +1302,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
DataOutput mockDataOutput = mock(DataOutput.class);
@SuppressWarnings("serial")
AbstractGemFireOperationsSessionRepository.GemFireSession session =
new AbstractGemFireOperationsSessionRepository.GemFireSession() {
@Override
void writeObject(Object obj, DataOutput out) throws IOException {
assertThat(String.valueOf(obj)).isEqualTo("test");
assertThat(out).isSameAs(mockDataOutput);
}
};
DeltaCapableGemFireSession session = new DeltaCapableGemFireSession();
session.setLastAccessedTime(Instant.ofEpochMilli(1L));
session.setMaxInactiveInterval(Duration.ofSeconds(300L));
@@ -1470,31 +1325,24 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
DataInput mockDataInput = mock(DataInput.class);
given(mockDataInput.readUTF()).willReturn("1");
given(mockDataInput.readLong()).willReturn(1L).willReturn(600L);
given(mockDataInput.readInt()).willReturn(0);
@SuppressWarnings("serial")
AbstractGemFireOperationsSessionRepository.GemFireSession session =
new AbstractGemFireOperationsSessionRepository.GemFireSession() {
@Override
@SuppressWarnings("unchecked")
<T> T readObject(DataInput in) throws ClassNotFoundException, IOException {
assertThat(in).isSameAs(mockDataInput);
return (T) "test";
}
};
DeltaCapableGemFireSession session = new DeltaCapableGemFireSession();
session.fromDelta(mockDataInput);
assertThat(session.hasDelta()).isFalse();
assertThat(session.getId()).isEqualTo("1");
assertThat(session.getLastAccessedTime()).isEqualTo(Instant.ofEpochMilli(1L));
assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(600L));
assertThat(session.getAttributeNames().isEmpty()).isTrue();
verify(mockDataInput, times(1)).readUTF();
verify(mockDataInput, times(2)).readLong();
verify(mockDataInput, times(1)).readInt();
verify(mockDataInput, never()).readUTF();
}
@Test
@@ -1502,12 +1350,10 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
Instant twoHoursAgo = Instant.now().minusMillis(TimeUnit.HOURS.toMillis(2));
AbstractGemFireOperationsSessionRepository.GemFireSession sessionOne =
new AbstractGemFireOperationsSessionRepository.GemFireSession(
mockSession("1", twoHoursAgo.toEpochMilli(), MAX_INACTIVE_INTERVAL_IN_SECONDS));
GemFireSession<?> sessionOne =
new GemFireSession<>(mockSession("1", twoHoursAgo.toEpochMilli(), MAX_INACTIVE_INTERVAL_IN_SECONDS));
AbstractGemFireOperationsSessionRepository.GemFireSession sessionTwo =
new AbstractGemFireOperationsSessionRepository.GemFireSession("2");
GemFireSession<?> sessionTwo = new GemFireSession<>("2");
assertThat(sessionOne.getCreationTime()).isEqualTo(twoHoursAgo);
assertThat(sessionTwo.getCreationTime().isAfter(twoHoursAgo)).isTrue();
@@ -1519,15 +1365,13 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test
public void sessionEqualsDifferentSessionBasedOnId() {
AbstractGemFireOperationsSessionRepository.GemFireSession sessionOne =
new AbstractGemFireOperationsSessionRepository.GemFireSession("1");
GemFireSession sessionOne = new GemFireSession("1");
sessionOne.setLastAccessedTime(Instant.ofEpochSecond(12345L));
sessionOne.setMaxInactiveInterval(Duration.ofSeconds(120L));
sessionOne.setPrincipalName("jblum");
AbstractGemFireOperationsSessionRepository.GemFireSession sessionTwo =
new AbstractGemFireOperationsSessionRepository.GemFireSession("1");
GemFireSession sessionTwo = new GemFireSession("1");
sessionTwo.setLastAccessedTime(Instant.ofEpochSecond(67890L));
sessionTwo.setMaxInactiveInterval(Duration.ofSeconds(300L));
@@ -1543,8 +1387,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test
public void sessionHashCodeIsNotEqualToStringIdHashCode() {
AbstractGemFireOperationsSessionRepository.GemFireSession session =
new AbstractGemFireOperationsSessionRepository.GemFireSession("1");
GemFireSession session = new GemFireSession("1");
assertThat(session.getId()).isEqualTo("1");
assertThat(session.hashCode()).isNotEqualTo("1".hashCode());
@@ -1559,8 +1402,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
given(mockSession.getAttribute(eq("attrOne"))).willReturn("testOne");
given(mockSession.getAttribute(eq("attrTwo"))).willReturn("testTwo");
AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes sessionAttributes =
new AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes();
GemFireSessionAttributes sessionAttributes = new GemFireSessionAttributes();
assertThat(sessionAttributes.getAttributeNames().isEmpty()).isTrue();
@@ -1585,8 +1427,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
source.setAttribute("attrOne", "testOne");
source.setAttribute("attrTwo", "testTwo");
AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes target =
new AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes();
GemFireSessionAttributes target = new GemFireSessionAttributes();
assertThat(target.getAttributeNames().isEmpty()).isTrue();
@@ -1598,69 +1439,6 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(target.<String>getAttribute("attrTwo")).isEqualTo("testTwo");
}
@Test
public void sessionAttributesToData() throws Exception {
DataOutput mockDataOutput = mock(DataOutput.class);
@SuppressWarnings("serial")
AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes sessionAttributes =
new AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes() {
private int count = 0;
@Override
void writeObject(Object obj, DataOutput out) throws IOException {
assertThat(Arrays.asList("testOne", "testTwo").get(count++)).isEqualTo(String.valueOf(obj));
assertThat(out).isSameAs(mockDataOutput);
}
};
sessionAttributes.setAttribute("attrOne", "testOne");
sessionAttributes.setAttribute("attrTwo", "testTwo");
sessionAttributes.toData(mockDataOutput);
verify(mockDataOutput, times(1)).writeInt(eq(2));
verify(mockDataOutput, times(1)).writeUTF(eq("attrOne"));
verify(mockDataOutput, times(1)).writeUTF(eq("attrTwo"));
}
@Test
public void sessionAttributesFromData() throws Exception {
DataInput mockDataInput = mock(DataInput.class);
given(mockDataInput.readInt()).willReturn(2);
given(mockDataInput.readUTF()).willReturn("attrOne").willReturn("attrTwo");
@SuppressWarnings("serial")
AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes sessionAttributes =
new AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes() {
private int count = 0;
@Override
@SuppressWarnings("unchecked")
<T> T readObject(DataInput in) throws ClassNotFoundException, IOException {
assertThat(in).isSameAs(mockDataInput);
return (T) Arrays.asList("testOne", "testTwo").get(count++);
}
};
assertThat(sessionAttributes.getAttributeNames().isEmpty()).isTrue();
sessionAttributes.fromData(mockDataInput);
assertThat(sessionAttributes.getAttributeNames().size()).isEqualTo(2);
assertThat(sessionAttributes.getAttributeNames().containsAll(asSet("attrOne", "attrTwo"))).isTrue();
assertThat(sessionAttributes.<String>getAttribute("attrOne")).isEqualTo("testOne");
assertThat(sessionAttributes.<String>getAttribute("attrTwo")).isEqualTo("testTwo");
verify(mockDataInput, times(1)).readInt();
verify(mockDataInput, times(2)).readUTF();
}
@Test
public void sessionAttributesHasDeltaIsFalse() {
assertThat(new AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes().hasDelta()).isFalse();
@@ -1669,8 +1447,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test
public void sessionAttributesHasDeltaIsTrue() {
AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes sessionAttributes =
new AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes();
GemFireSessionAttributes sessionAttributes = new DeltaCapableGemFireSessionAttributes();
assertThat(sessionAttributes.hasDelta()).isFalse();
@@ -1686,13 +1463,12 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
DataOutput mockDataOutput = mock(DataOutput.class);
@SuppressWarnings("serial")
AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes sessionAttributes =
new AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes() {
DeltaCapableGemFireSessionAttributes sessionAttributes = new DeltaCapableGemFireSessionAttributes() {
private int count = 0;
@Override
void writeObject(Object obj, DataOutput out) throws IOException {
protected void writeObject(Object obj, DataOutput out) throws IOException {
assertThat(Arrays.asList("testOne", "testTwo", "testThree").get(count++)).isEqualTo(String.valueOf(obj));
assertThat(out).isSameAs(mockDataOutput);
}
@@ -1741,14 +1517,13 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
given(mockDataInput.readUTF()).willReturn("attrOne").willReturn("attrTwo");
@SuppressWarnings("serial")
AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes sessionAttributes =
new AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes() {
DeltaCapableGemFireSessionAttributes sessionAttributes = new DeltaCapableGemFireSessionAttributes() {
private int count = 0;
@Override
@SuppressWarnings("unchecked")
<T> T readObject(DataInput in) throws ClassNotFoundException, IOException {
protected <T> T readObject(DataInput in) throws ClassNotFoundException, IOException {
assertThat(in).isSameAs(mockDataInput);
return (T) Arrays.asList("testOne", "testTwo", "testThree").get(count++);
}
@@ -1802,8 +1577,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Test
public void sessionAttributesEntrySetIteratesAttributeNameValues() {
AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes sessionAttributes =
new AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes();
GemFireSessionAttributes sessionAttributes = new GemFireSessionAttributes();
sessionAttributes.setAttribute("keyOne", "valueOne");
sessionAttributes.setAttribute("keyTwo", "valueTwo");
@@ -1813,8 +1587,8 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(sessionAttributeEntries).isNotNull();
assertThat(sessionAttributeEntries.size()).isEqualTo(2);
Set<String> expectedNames = asSet("keyOne", "keyTwo");
Set<?> expectedValues = asSet("valueOne", "valueTwo");
Set<String> expectedNames = new HashSet<>(asSet("keyOne", "keyTwo"));
Set<?> expectedValues = new HashSet<>(asSet("valueOne", "valueTwo"));
for (Map.Entry<String, Object> entry : sessionAttributeEntries) {
expectedNames.remove(entry.getKey());
@@ -1828,8 +1602,8 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
assertThat(sessionAttributeEntries.size()).isEqualTo(3);
expectedNames = asSet("keyOne", "keyTwo");
expectedValues = asSet("valueOne", "valueTwo");
expectedNames = new HashSet<>(asSet("keyOne", "keyTwo"));
expectedValues = new HashSet<>(asSet("valueOne", "valueTwo"));
for (Map.Entry<String, Object> entry : sessionAttributeEntries) {
expectedNames.remove(entry.getKey());
@@ -1858,7 +1632,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@SuppressWarnings("unused")
protected static final class ThreadSafeSessionTest extends MultithreadedTestCase {
private AbstractGemFireOperationsSessionRepository.GemFireSession session;
private GemFireSession<?> session;
private final Instant beforeOrAtCreationTime = Instant.now();
@@ -1867,7 +1641,7 @@ public class AbstractGemFireOperationsSessionRepositoryTest {
@Override
public void initialize() {
this.session = new AbstractGemFireOperationsSessionRepository.GemFireSession("1");
this.session = new GemFireSession<>("1");
assertThat(this.session).isNotNull();
assertThat(this.session.getId()).isEqualTo("1");

View File

@@ -74,7 +74,7 @@ import org.springframework.session.events.SessionDeletedEvent;
* @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository
*/
@RunWith(MockitoJUnitRunner.class)
public class GemFireOperationsSessionRepositoryTest {
public class GemFireOperationsSessionRepositoryTests {
protected static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600;
@@ -271,7 +271,7 @@ public class GemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource())
.isSameAs(GemFireOperationsSessionRepositoryTest.this.sessionRepository);
.isSameAs(GemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isSameAs(mockSession);
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);
@@ -393,7 +393,7 @@ public class GemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource()).isSameAs(GemFireOperationsSessionRepositoryTest.this.sessionRepository);
assertThat(sessionEvent.getSource()).isSameAs(GemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isSameAs(mockSession);
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);
@@ -423,7 +423,7 @@ public class GemFireOperationsSessionRepositoryTest {
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource()).isSameAs(GemFireOperationsSessionRepositoryTest.this.sessionRepository);
assertThat(sessionEvent.getSource()).isSameAs(GemFireOperationsSessionRepositoryTests.this.sessionRepository);
assertThat(sessionEvent.<Session>getSession()).isNull();
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);

View File

@@ -28,6 +28,7 @@ import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
@@ -41,6 +42,8 @@ import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.gemfire.GemfireOperations;
import org.springframework.data.gemfire.GemfireTemplate;
@@ -50,26 +53,36 @@ import org.springframework.session.data.gemfire.GemFireOperationsSessionReposito
import org.springframework.session.data.gemfire.config.annotation.web.http.support.GemFireCacheTypeAwareRegionFactoryBean;
/**
* The GemFireHttpSessionConfigurationTest class is a test suite of test cases testing the
* contract and functionality of the {@link GemFireHttpSessionConfiguration} class.
* Unit tests for {@link GemFireHttpSessionConfiguration} class.
*
* @author John Blum
* @since 1.1.0
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.springframework.data.gemfire.GemfireOperations
* @see org.springframework.data.gemfire.GemfireTemplate
* @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
* @see org.apache.geode.cache.Cache
* @see org.apache.geode.cache.GemFireCache
* @see org.apache.geode.cache.Region
* @see org.apache.geode.cache.ExpirationAttributes
* @see org.apache.geode.cache.RegionAttributes
* @see org.apache.geode.cache.client.ClientCache
* @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory
* @see org.springframework.context.ConfigurableApplicationContext
* @see org.springframework.core.type.AnnotationMetadata
* @see org.springframework.data.gemfire.GemfireOperations
* @see org.springframework.data.gemfire.GemfireTemplate
* @see org.springframework.session.Session
* @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
*/
public class GemFireHttpSessionConfigurationTest {
public class GemFireHttpSessionConfigurationTests {
private GemFireHttpSessionConfiguration gemfireConfiguration;
@AfterClass
public static void tearDown() {
System.clearProperty(GemFireHttpSessionConfiguration.SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME);
}
@SuppressWarnings("unchecked")
protected <T> T getField(Object obj, String fieldName) {
try {
@@ -197,7 +210,7 @@ public class GemFireHttpSessionConfigurationTest {
}
@Test
public void setAndGetSpringSessionGemFireRegionName() {
public void setAndGetSessionRegionName() {
assertThat(this.gemfireConfiguration.getSessionRegionName()).isEqualTo(
GemFireHttpSessionConfiguration.DEFAULT_SESSION_REGION_NAME);
@@ -222,6 +235,61 @@ public class GemFireHttpSessionConfigurationTest {
GemFireHttpSessionConfiguration.DEFAULT_SESSION_REGION_NAME);
}
@Test
public void setAndGetSessionSerializerBeanName() {
assertThat(this.gemfireConfiguration.getSessionSerializerBeanName())
.isEqualTo(GemFireHttpSessionConfiguration.DEFAULT_SESSION_SERIALIZER_BEAN_NAME);
this.gemfireConfiguration.setSessionSerializerBeanName(
GemFireHttpSessionConfiguration.SESSION_DATA_SERIALIZER_BEAN_NAME);
assertThat(this.gemfireConfiguration.getSessionSerializerBeanName())
.isEqualTo(GemFireHttpSessionConfiguration.SESSION_DATA_SERIALIZER_BEAN_NAME);
this.gemfireConfiguration.setSessionSerializerBeanName(null);
assertThat(this.gemfireConfiguration.getSessionSerializerBeanName())
.isEqualTo(GemFireHttpSessionConfiguration.DEFAULT_SESSION_SERIALIZER_BEAN_NAME);
this.gemfireConfiguration.setSessionSerializerBeanName(
GemFireHttpSessionConfiguration.SESSION_PDX_SERIALIZER_BEAN_NAME);
assertThat(this.gemfireConfiguration.getSessionSerializerBeanName())
.isEqualTo(GemFireHttpSessionConfiguration.SESSION_PDX_SERIALIZER_BEAN_NAME);
}
@Test
public void isUsingDataSerializationIsFalse() {
this.gemfireConfiguration.setSessionSerializerBeanName("test");
assertThat(this.gemfireConfiguration.getSessionSerializerBeanName()).isEqualTo("test");
assertThat(this.gemfireConfiguration.isUsingDataSerialization()).isFalse();
this.gemfireConfiguration.setSessionSerializerBeanName(
GemFireHttpSessionConfiguration.SESSION_PDX_SERIALIZER_BEAN_NAME);
assertThat(this.gemfireConfiguration.getSessionSerializerBeanName())
.isEqualTo(GemFireHttpSessionConfiguration.SESSION_PDX_SERIALIZER_BEAN_NAME);
assertThat(this.gemfireConfiguration.isUsingDataSerialization()).isFalse();
}
@Test
public void isUsingDataSerializationIsTrue() {
assertThat(this.gemfireConfiguration.getSessionSerializerBeanName())
.isEqualTo(GemFireHttpSessionConfiguration.SESSION_DATA_SERIALIZER_BEAN_NAME);
assertThat(this.gemfireConfiguration.isUsingDataSerialization()).isTrue();
this.gemfireConfiguration.setSessionSerializerBeanName(null);
assertThat(this.gemfireConfiguration.getSessionSerializerBeanName())
.isEqualTo(GemFireHttpSessionConfiguration.SESSION_DATA_SERIALIZER_BEAN_NAME);
assertThat(this.gemfireConfiguration.isUsingDataSerialization()).isTrue();
}
@Test
public void setsImportMetadata() {
@@ -235,6 +303,7 @@ public class GemFireHttpSessionConfigurationTest {
annotationAttributes.put("poolName", "TestPool");
annotationAttributes.put("serverRegionShortcut", RegionShortcut.REPLICATE);
annotationAttributes.put("regionName", "TEST");
annotationAttributes.put("sessionSerializerBeanName", "testSessionSerializer");
given(mockAnnotationMetadata.getAnnotationAttributes(eq(EnableGemFireHttpSession.class.getName())))
.willReturn(annotationAttributes);
@@ -247,8 +316,36 @@ public class GemFireHttpSessionConfigurationTest {
assertThat(this.gemfireConfiguration.getPoolName()).isEqualTo("TestPool");
assertThat(this.gemfireConfiguration.getServerRegionShortcut()).isEqualTo(RegionShortcut.REPLICATE);
assertThat(this.gemfireConfiguration.getSessionRegionName()).isEqualTo("TEST");
assertThat(this.gemfireConfiguration.getSessionSerializerBeanName()).isEqualTo("testSessionSerializer");
verify(mockAnnotationMetadata, times(1)).getAnnotationAttributes(eq(EnableGemFireHttpSession.class.getName()));
verify(mockAnnotationMetadata, times(1))
.getAnnotationAttributes(eq(EnableGemFireHttpSession.class.getName()));
}
@Test
public void postConstructInitSetsSystemPropertyAndRegistersBeanAlias() {
ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class);
ConfigurableApplicationContext mockApplicationContext = mock(ConfigurableApplicationContext.class);
given(mockApplicationContext.getBeanFactory()).willReturn(mockBeanFactory);
assertThat(System.getProperty(GemFireHttpSessionConfiguration.SESSION_SERIALIZER_REGISTERED_ALIAS)).isNull();
this.gemfireConfiguration.setApplicationContext(mockApplicationContext);
this.gemfireConfiguration.setSessionSerializerBeanName("testSessionSerializer");
this.gemfireConfiguration.init();
assertThat(this.gemfireConfiguration.getApplicationContext()).isSameAs(mockApplicationContext);
assertThat(System.getProperty(GemFireHttpSessionConfiguration.SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME))
.isEqualTo("testSessionSerializer");
verify(mockApplicationContext, times(1)).getBeanFactory();
verify(mockBeanFactory, times(1)).registerAlias(eq("testSessionSerializer"),
eq(GemFireHttpSessionConfiguration.SESSION_SERIALIZER_REGISTERED_ALIAS));
}
@Test

View File

@@ -39,7 +39,7 @@ import org.springframework.data.gemfire.client.Interest;
import org.springframework.session.Session;
/**
* The GemFireCacheTypeAwareRegionFactoryBeanTest class is a test suite of test cases
* The GemFireCacheTypeAwareRegionFactoryBeanTests class is a test suite of test cases
* testing the contract and functionality of the GemFireCacheTypeAwareRegionFactoryBean
* class.
*
@@ -60,7 +60,7 @@ import org.springframework.session.Session;
* @see org.apache.geode.cache.client.ClientRegionShortcut
*/
@RunWith(MockitoJUnitRunner.class)
public class GemFireCacheTypeAwareRegionFactoryBeanTest {
public class GemFireCacheTypeAwareRegionFactoryBeanTests {
@Mock
Cache mockCache;
@@ -89,13 +89,13 @@ public class GemFireCacheTypeAwareRegionFactoryBeanTest {
@Override
protected Region<Object, Session> newClientRegion(GemFireCache gemfireCache) throws Exception {
assertThat(gemfireCache).isSameAs(expectedCache);
return GemFireCacheTypeAwareRegionFactoryBeanTest.this.mockClientRegion;
return GemFireCacheTypeAwareRegionFactoryBeanTests.this.mockClientRegion;
}
@Override
protected Region<Object, Session> newServerRegion(GemFireCache gemfireCache) throws Exception {
assertThat(gemfireCache).isSameAs(expectedCache);
return GemFireCacheTypeAwareRegionFactoryBeanTest.this.mockServerRegion;
return GemFireCacheTypeAwareRegionFactoryBeanTests.this.mockServerRegion;
}
};

View File

@@ -0,0 +1,122 @@
/*
* Copyright 2017 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.serialization.data.provider;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.springframework.data.gemfire.util.CollectionUtils.asSet;
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes;
import java.io.DataInput;
import java.io.DataOutput;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
/**
* Unit tests for {@link DataSerializableSessionAttributesSerializer}.
*
* @author John Blum
* @see org.junit.Test
* @see org.mockito.Mock
* @see org.mockito.Mockito
* @see org.mockito.Spy
* @see org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes
* @see org.springframework.session.data.gemfire.serialization.data.provider.DataSerializableSessionAttributesSerializer
* @since 2.0.0
*/
public class DataSerializableSessionAttributesSerializerTests {
private DataSerializableSessionAttributesSerializer sessionAttributesSerializer =
spy(new DataSerializableSessionAttributesSerializer());
@Test
public void getIdReturnsSameValue() {
int id = this.sessionAttributesSerializer.getId();
assertThat(id).isNotEqualTo(0);
assertThat(id).isEqualTo(this.sessionAttributesSerializer.getId());
}
@Test
public void supportedClassesContainsGemFireSessionAttributes() {
assertThat(this.sessionAttributesSerializer.getSupportedClasses()).contains(GemFireSessionAttributes.class);
}
@Test
public void sessionAttributesToData() throws Exception {
DataOutput mockDataOutput = mock(DataOutput.class);
GemFireSessionAttributes sessionAttributes = GemFireSessionAttributes.create();
sessionAttributes.setAttribute("attrOne", "testOne");
sessionAttributes.setAttribute("attrTwo", "testTwo");
doAnswer(invocation -> {
DataOutput dataOutput = invocation.getArgument(1);
dataOutput.writeUTF(invocation.getArgument(0));
return null;
}).when(sessionAttributesSerializer).serializeObject(any(), any(DataOutput.class));
sessionAttributesSerializer.serialize(sessionAttributes, mockDataOutput);
verify(mockDataOutput, times(1)).writeInt(eq(2));
verify(mockDataOutput, times(1)).writeUTF(eq("attrOne"));
verify(mockDataOutput, times(1)).writeUTF(eq("testOne"));
verify(mockDataOutput, times(1)).writeUTF(eq("attrTwo"));
verify(mockDataOutput, times(1)).writeUTF(eq("testTwo"));
}
@Test
public void sessionAttributesFromData() throws Exception {
AtomicInteger count = new AtomicInteger(0);
DataInput mockDataInput = mock(DataInput.class);
given(mockDataInput.readInt()).willReturn(2);
given(mockDataInput.readUTF()).willReturn("attrOne").willReturn("attrTwo");
doAnswer(invocation -> Arrays.asList("testOne", "testTwo").get(count.getAndIncrement()))
.when(sessionAttributesSerializer).deserializeObject(any(DataInput.class));
GemFireSessionAttributes sessionAttributes = sessionAttributesSerializer.deserialize(mockDataInput);
assertThat(sessionAttributes).isNotNull();
assertThat(sessionAttributes.getAttributeNames()).hasSize(2);
assertThat(sessionAttributes.getAttributeNames()).containsAll(asSet("attrOne", "attrTwo"));
assertThat(sessionAttributes.<String>getAttribute("attrOne")).isEqualTo("testOne");
assertThat(sessionAttributes.<String>getAttribute("attrTwo")).isEqualTo("testTwo");
verify(mockDataInput, times(1)).readInt();
verify(mockDataInput, times(2)).readUTF();
}
}

View File

@@ -0,0 +1,201 @@
/*
* Copyright 2017 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.serialization.data.provider;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.springframework.data.gemfire.util.CollectionUtils.asSet;
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSession;
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.springframework.session.FindByIndexNameSessionRepository;
/**
* Unit tests for {@link DataSerializableSessionSerializer}.
*
* @author John Blum
* @see org.junit.Test
* @see org.mockito.Mock
* @see org.mockito.Mockito
* @see org.mockito.Spy
* @see org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSession
* @see org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes
* @see org.springframework.session.data.gemfire.serialization.data.provider.DataSerializableSessionSerializer
* @since 2.0.0
*/
public class DataSerializableSessionSerializerTests {
private DataSerializableSessionSerializer sessionSerializer = spy(new DataSerializableSessionSerializer());
@Test
public void getIdReturnsSameValue() {
int id = this.sessionSerializer.getId();
assertThat(id).isNotEqualTo(0);
assertThat(id).isEqualTo((this.sessionSerializer.getId()));
}
@Test
public void supportedClassContainsGemFireSession() {
assertThat(this.sessionSerializer.getSupportedClasses()).contains(GemFireSession.class);
}
@Test
public void sessionToData() throws Exception {
GemFireSession<?> session = GemFireSession.create();
session.setLastAccessedTime(Instant.ofEpochMilli(123L));
session.setMaxInactiveInterval(Duration.ofSeconds(60L));
session.setPrincipalName("jblum");
DataOutput mockDataOutput = mock(DataOutput.class);
doAnswer(invocation -> {
assertThat(invocation.<GemFireSessionAttributes>getArgument(0)).isEqualTo(session.getAttributes());
assertThat(invocation.<DataOutput>getArgument(1)).isEqualTo(mockDataOutput);
return null;
}).when(this.sessionSerializer).serializeObject(any(), any(DataOutput.class));
assertThat(session.hasDelta()).isTrue();
this.sessionSerializer.serialize(session, mockDataOutput);
assertThat(session.hasDelta()).isFalse();
verify(mockDataOutput, times(1)).writeUTF(eq(session.getId()));
verify(mockDataOutput, times(1)).writeLong(eq(session.getCreationTime().toEpochMilli()));
verify(mockDataOutput, times(1)).writeLong(eq(session.getLastAccessedTime().toEpochMilli()));
verify(mockDataOutput, times(1)).writeLong(eq(session.getMaxInactiveInterval().getSeconds()));
verify(mockDataOutput, times(1)).writeInt(eq("jblum".length()));
verify(mockDataOutput, times(1)).writeUTF(eq(session.getPrincipalName()));
verify(this.sessionSerializer, times(1))
.serializeObject(eq(session.getAttributes()), eq(mockDataOutput));
}
@Test
public void sessionFromData() throws Exception {
long expectedCreationTime = 1L;
long expectedLastAccessedTime = 2L;
long expectedMaxInactiveIntervalInSeconds = TimeUnit.HOURS.toSeconds(2);
String expectedPrincipalName = "jblum";
String expectedSessionId = "2";
DataInput mockDataInput = mock(DataInput.class);
given(mockDataInput.readUTF()).willReturn(expectedSessionId).willReturn(expectedPrincipalName);
given(mockDataInput.readLong()).willReturn(expectedCreationTime).willReturn(expectedLastAccessedTime)
.willReturn(expectedMaxInactiveIntervalInSeconds);
given(mockDataInput.readInt()).willReturn(expectedPrincipalName.length());
doAnswer(invocation -> {
GemFireSessionAttributes sessionAttributes = GemFireSessionAttributes.create();
sessionAttributes.setAttribute("attrOne", "testOne");
sessionAttributes.setAttribute("attrTwo", "testTwo");
return sessionAttributes;
}).when(this.sessionSerializer).deserializeObject(any(DataInput.class));
GemFireSession<?> session = this.sessionSerializer.deserialize(mockDataInput);
Set<String> expectedAttributeNames =
asSet("attrOne", "attrTwo", FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
assertThat(session.getId()).isEqualTo(expectedSessionId);
assertThat(session.getCreationTime()).isEqualTo(Instant.ofEpochMilli(expectedCreationTime));
assertThat(session.getLastAccessedTime()).isEqualTo(Instant.ofEpochMilli(expectedLastAccessedTime));
assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(expectedMaxInactiveIntervalInSeconds));
assertThat(session.getPrincipalName()).isEqualTo(expectedPrincipalName);
assertThat(session.hasDelta()).isFalse();
assertThat(session.getAttributeNames()).hasSize(3);
assertThat(session.getAttributeNames()).containsAll(expectedAttributeNames);
assertThat(session.<String>getAttribute("attrOne")).isEqualTo("testOne");
assertThat(session.<String>getAttribute("attrTwo")).isEqualTo("testTwo");
assertThat(session.<String>getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME))
.isEqualTo(expectedPrincipalName);
verify(mockDataInput, times(2)).readUTF();
verify(mockDataInput, times(3)).readLong();
verify(mockDataInput, times(1)).readInt();
}
@Test
public void sessionToDataThenFromDataWhenPrincipalNameIsNullGetsHandledProperly()
throws ClassNotFoundException, IOException {
Instant beforeOrAtCreationTime = Instant.now();
GemFireSession<?> expectedSession = GemFireSession.create();
assertThat(expectedSession.getId()).isNotNull();
assertThat(expectedSession.getCreationTime().compareTo(beforeOrAtCreationTime)).isGreaterThanOrEqualTo(0);
assertThat(expectedSession.getLastAccessedTime().compareTo(beforeOrAtCreationTime)).isGreaterThanOrEqualTo(0);
assertThat(expectedSession.getMaxInactiveInterval()).isEqualTo(Duration.ZERO);
assertThat(expectedSession.getPrincipalName()).isNull();
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
doAnswer(invocation -> null).when(this.sessionSerializer).serializeObject(any(), any(DataOutput.class));
doAnswer(invocation -> GemFireSessionAttributes.create())
.when(this.sessionSerializer).deserializeObject(any(DataInput.class));
this.sessionSerializer.serialize(expectedSession, new DataOutputStream(outBytes));
GemFireSession<?> deserializedSession =
this.sessionSerializer.deserialize(new DataInputStream(new ByteArrayInputStream(outBytes.toByteArray())));
assertThat(deserializedSession).isEqualTo(expectedSession);
assertThat(deserializedSession.getCreationTime()).isEqualTo(expectedSession.getCreationTime());
assertThat(deserializedSession.getLastAccessedTime()).isEqualTo(expectedSession.getLastAccessedTime());
assertThat(deserializedSession.getMaxInactiveInterval()).isEqualTo(expectedSession.getMaxInactiveInterval());
assertThat(deserializedSession.getPrincipalName()).isNull();
verify(this.sessionSerializer, times(1))
.serializeObject(eq(expectedSession.getAttributes()), isA(DataOutput.class));
verify(this.sessionSerializer, times(1)).deserializeObject(isA(DataInput.class));
}
}

View File

@@ -47,7 +47,7 @@ import org.apache.geode.cache.client.ClientRegionShortcut;
* @see org.mockito.Mockito
* @see org.springframework.session.data.gemfire.support.GemFireUtils
*/
public class GemFireUtilsTest {
public class GemFireUtilsTests {
@Test
public void closeNonNullCloseableSuccessfullyReturnsTrue() throws IOException {