Add tests for all classes in the new Serialization framework.
Resolves Issue #2.
This commit is contained in:
@@ -25,16 +25,12 @@ import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -42,13 +38,14 @@ 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;
|
||||
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
@@ -169,7 +166,9 @@ public class ClientServerHttpSessionAttributesDeltaIntegrationTests extends Abst
|
||||
assertThat(reloadedSession.<Integer>getAttribute("attrOne")).isEqualTo(1);
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession
|
||||
@ClientCacheApplication
|
||||
@EnableGemFireHttpSession(poolName = "DEFAULT", sessionSerializerBeanName =
|
||||
GemFireHttpSessionConfiguration.SESSION_DATA_SERIALIZER_BEAN_NAME)
|
||||
@SuppressWarnings("unused")
|
||||
static class SpringSessionDataGemFireClientConfiguration {
|
||||
|
||||
@@ -178,42 +177,16 @@ public class ClientServerHttpSessionAttributesDeltaIntegrationTests extends Abst
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
Properties gemfireProperties() {
|
||||
@Bean ClientCacheConfigurer clientCachePoolPortConfigurer(
|
||||
@Value("${spring.session.data.gemfire.port:" + DEFAULT_GEMFIRE_SERVER_PORT + "}") int port) {
|
||||
|
||||
Properties gemfireProperties = new Properties();
|
||||
return (beanName, clientCacheFactoryBean) -> {
|
||||
|
||||
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
|
||||
clientCacheFactoryBean.setServers(Collections.singleton(
|
||||
new ConnectionEndpoint(SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port)));
|
||||
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
ClientCacheFactoryBean gemfireCache() {
|
||||
|
||||
ClientCacheFactoryBean clientCacheFactory = new ClientCacheFactoryBean();
|
||||
|
||||
clientCacheFactory.setClose(true);
|
||||
clientCacheFactory.setProperties(gemfireProperties());
|
||||
|
||||
return clientCacheFactory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
PoolFactoryBean gemfirePool(@Value("${spring.session.data.gemfire.port:"
|
||||
+ DEFAULT_GEMFIRE_SERVER_PORT + "}") int port) {
|
||||
|
||||
PoolFactoryBean poolFactory = new PoolFactoryBean();
|
||||
|
||||
poolFactory.setKeepAlive(false);
|
||||
poolFactory.setPingInterval(TimeUnit.SECONDS.toMillis(5));
|
||||
poolFactory.setReadTimeout(2000); // 2 seconds
|
||||
poolFactory.setRetryAttempts(1);
|
||||
poolFactory.setSubscriptionEnabled(true);
|
||||
|
||||
poolFactory.setServers(Collections.singletonList(new ConnectionEndpoint(
|
||||
SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port)));
|
||||
|
||||
return poolFactory;
|
||||
clientCacheFactoryBean.setSubscriptionEnabled(true);
|
||||
};
|
||||
}
|
||||
|
||||
// used for debugging purposes
|
||||
@@ -234,7 +207,9 @@ public class ClientServerHttpSessionAttributesDeltaIntegrationTests extends Abst
|
||||
}
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
@CacheServerApplication(name = "ClientServerHttpSessionAttributesDeltaIntegrationTests")
|
||||
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS,
|
||||
sessionSerializerBeanName = GemFireHttpSessionConfiguration.SESSION_DATA_SERIALIZER_BEAN_NAME)
|
||||
@SuppressWarnings("unused")
|
||||
static class SpringSessionDataGemFireServerConfiguration {
|
||||
|
||||
@@ -245,53 +220,24 @@ public class ClientServerHttpSessionAttributesDeltaIntegrationTests extends Abst
|
||||
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 ClientServerHttpSessionAttributesDeltaIntegrationTests.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.setAutoStartup(true);
|
||||
cacheServerFactoryBean.setBindAddress(SERVER_HOSTNAME);
|
||||
cacheServerFactoryBean.setPort(port);
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
AnnotationConfigApplicationContext context =
|
||||
AnnotationConfigApplicationContext applicationContext =
|
||||
new AnnotationConfigApplicationContext(SpringSessionDataGemFireServerConfiguration.class);
|
||||
|
||||
context.registerShutdownHook();
|
||||
applicationContext.registerShutdownHook();
|
||||
|
||||
writeProcessControlFile(WORKING_DIRECTORY);
|
||||
}
|
||||
|
||||
@@ -141,7 +141,8 @@ public class ClientServerProxyRegionSessionOperationsIntegrationTests extends Ab
|
||||
assertThat(loadedSession).isNotNull();
|
||||
assertThat(loadedSession.getId()).isEqualTo(session.getId());
|
||||
assertThat(loadedSession.getCreationTime()).isEqualTo(session.getCreationTime());
|
||||
assertThat(loadedSession.getLastAccessedTime().compareTo(session.getLastAccessedTime())).isGreaterThanOrEqualTo(0);
|
||||
assertThat(loadedSession.getLastAccessedTime().compareTo(session.getLastAccessedTime()))
|
||||
.isGreaterThanOrEqualTo(0);
|
||||
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.support.GemfireBeanFactoryLocator;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.DeltaCapableGemFireSession;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.DeltaCapableGemFireSessionAttributes;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSession;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes;
|
||||
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
|
||||
import org.springframework.session.data.gemfire.serialization.SessionSerializer;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link DataSerializerSessionSerializerAdapter}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.io.DataInput
|
||||
* @see java.io.DataOutput
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.serialization.SessionSerializer
|
||||
* @see org.springframework.session.data.gemfire.serialization.data.support.DataSerializerSessionSerializerAdapter
|
||||
* @see org.springframework.test.context.ContextConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
public class DataSerializerSessionSerializerAdapterIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private DataSerializerSessionSerializerAdapter<Session> dataSerializer;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(GemFireHttpSessionConfiguration.SESSION_SERIALIZER_BEAN_ALIAS)
|
||||
private SessionSerializer<Session, DataInput, DataOutput> sessionSerializer;
|
||||
|
||||
@Test
|
||||
public void constructsAndAutowiresDataSerializerSessionSerializerAdapter() {
|
||||
|
||||
assertThat(this.dataSerializer).isNotNull();
|
||||
assertThat(this.sessionSerializer).isNotNull();
|
||||
assertThat(this.dataSerializer.getId()).isEqualTo(0xBAC2BAC);
|
||||
assertThat(this.dataSerializer.getSupportedClasses())
|
||||
.containsExactly(GemFireSession.class, GemFireSessionAttributes.class, DeltaCapableGemFireSession.class,
|
||||
DeltaCapableGemFireSessionAttributes.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@SuppressWarnings("unused")
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
GemfireBeanFactoryLocator beanFactoryLocator(BeanFactory beanFactory) {
|
||||
return GemfireBeanFactoryLocator.newBeanFactoryLocator(beanFactory, "sessionBeanFactory");
|
||||
}
|
||||
|
||||
@Bean
|
||||
DataSerializerSessionSerializerAdapter dataSerializer() {
|
||||
return new DataSerializerSessionSerializerAdapter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Qualifier(GemFireHttpSessionConfiguration.SESSION_SERIALIZER_BEAN_ALIAS)
|
||||
@SuppressWarnings("unchecked")
|
||||
SessionSerializer<Session, DataInput, DataOutput> mockSessionSerializer() {
|
||||
return mock(SessionSerializer.class, "SessionSerializer");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,18 +39,16 @@ import org.apache.geode.pdx.PdxSerializer;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
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.Configuration;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.GemfireOperations;
|
||||
@@ -58,8 +56,6 @@ import org.springframework.data.gemfire.GemfireTemplate;
|
||||
import org.springframework.data.gemfire.IndexFactoryBean;
|
||||
import org.springframework.data.gemfire.IndexType;
|
||||
import org.springframework.data.gemfire.RegionAttributesFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
|
||||
import org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer;
|
||||
import org.springframework.data.gemfire.config.xml.GemfireConstants;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
@@ -153,14 +149,9 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
*/
|
||||
public static final String SESSION_DATA_SERIALIZER_BEAN_NAME = "SessionDataSerializer";
|
||||
public static final String SESSION_PDX_SERIALIZER_BEAN_NAME = "SessionPdxSerializer";
|
||||
public static final String SESSION_SERIALIZER_BEAN_ALIAS = "SessionSerializerRegisteredBeanAlias";
|
||||
|
||||
public static final String SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME =
|
||||
"spring.session.data.geode.serializer.qualifier";
|
||||
|
||||
public static final String SESSION_SERIALIZER_REGISTERED_ALIAS =
|
||||
"org.springframework.session.data.geode.serializer.registeredAlias";
|
||||
|
||||
public static final String DEFAULT_SESSION_SERIALIZER_BEAN_NAME = SESSION_DATA_SERIALIZER_BEAN_NAME;
|
||||
public static final String DEFAULT_SESSION_SERIALIZER_BEAN_NAME = SESSION_PDX_SERIALIZER_BEAN_NAME;
|
||||
|
||||
/**
|
||||
* Defaults names of all {@link Session} attributes that will be indexed by Apache Geode.
|
||||
@@ -185,21 +176,34 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
|
||||
private String[] indexableSessionAttributes = DEFAULT_INDEXABLE_SESSION_ATTRIBUTES;
|
||||
|
||||
/**
|
||||
* Sets a reference the Spring {@link ApplicationContext}.
|
||||
*
|
||||
* @param applicationContext reference to the Spring {@link ApplicationContext}.
|
||||
* @throws BeansException if the reference cannot be stored.
|
||||
* @see org.springframework.context.ApplicationContext
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
super.setApplicationContext(applicationContext);
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Spring {@link ApplicationContext}.
|
||||
*
|
||||
* @return a reference to the Spring {@link ApplicationContext}.
|
||||
* @see org.springframework.context.ApplicationContext
|
||||
*/
|
||||
protected ApplicationContext getApplicationContext() {
|
||||
return Optional.ofNullable(this.applicationContext)
|
||||
.orElseThrow(() -> newIllegalStateException("The ApplicationContext was not properly configured"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the {@link ClassLoader} used by the Spring container to load bean class types.
|
||||
* Sets a reference to the {@link ClassLoader} used by the Spring container to load bean {@link Class class types}.
|
||||
*
|
||||
* @param beanClassLoader {@link ClassLoader} used by the Spring container to load bean class types.
|
||||
* @param beanClassLoader {@link ClassLoader} used by the Spring container to load bean {@link Class class types}.
|
||||
* @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(ClassLoader)
|
||||
* @see java.lang.ClassLoader
|
||||
*/
|
||||
@@ -207,6 +211,24 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
this.beanClassLoader = beanClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link ClassLoader} used by the Spring container to load bean
|
||||
* {@link Class class types}.
|
||||
*
|
||||
* @return the {@link ClassLoader} used by the Spring container to load bean {@link Class class types}.
|
||||
* @see java.lang.ClassLoader
|
||||
*/
|
||||
protected ClassLoader getBeanClassLoader() {
|
||||
return this.beanClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Spring container {@link ConfigurableBeanFactory}.
|
||||
*
|
||||
* @return a reference to the Spring container {@link ConfigurableBeanFactory}.
|
||||
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory
|
||||
* @see #getApplicationContext()
|
||||
*/
|
||||
protected ConfigurableBeanFactory getBeanFactory() {
|
||||
|
||||
ApplicationContext applicationContext = getApplicationContext();
|
||||
@@ -218,16 +240,6 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
ConfigurableBeanFactory.class.getName(), ObjectUtils.nullSafeClassName(applicationContext)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link ClassLoader} used by the Spring container to load bean class types.
|
||||
*
|
||||
* @return the {@link ClassLoader} used by the Spring container to load bean class types.
|
||||
* @see java.lang.ClassLoader
|
||||
*/
|
||||
protected ClassLoader getBeanClassLoader() {
|
||||
return this.beanClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link ClientRegionShortcut} used to configure the data management policy of the {@link ClientCache}
|
||||
* {@link Region} that will store {@link Session} state.
|
||||
@@ -457,28 +469,31 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
|
||||
@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);
|
||||
getBeanFactory().registerAlias(getSessionSerializerBeanName(), SESSION_SERIALIZER_BEAN_ALIAS);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@DependsOn({ SESSION_DATA_SERIALIZER_BEAN_NAME, SESSION_PDX_SERIALIZER_BEAN_NAME })
|
||||
public ClientCacheConfigurer sessionClientCacheConfigurer(
|
||||
@Qualifier(SESSION_SERIALIZER_REGISTERED_ALIAS) SessionSerializer sessionSerializer) {
|
||||
BeanPostProcessor sessionSerializerConfigurationBeanPostProcessor() {
|
||||
|
||||
return (beanName, clientCacheFactoryBean) -> configureSerialization(clientCacheFactoryBean, sessionSerializer);
|
||||
return new BeanPostProcessor() {
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
|
||||
if (bean instanceof CacheFactoryBean) {
|
||||
|
||||
SessionSerializer sessionSerializer = resolveSessionSerializer();
|
||||
|
||||
configureSerialization((CacheFactoryBean) bean, sessionSerializer);
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@DependsOn({ SESSION_DATA_SERIALIZER_BEAN_NAME, SESSION_PDX_SERIALIZER_BEAN_NAME })
|
||||
public PeerCacheConfigurer sessionPeerCacheConfigurer(
|
||||
@Qualifier(SESSION_SERIALIZER_REGISTERED_ALIAS) SessionSerializer sessionSerializer) {
|
||||
|
||||
return (beanName, cacheFactoryBean) -> configureSerialization(cacheFactoryBean, sessionSerializer);
|
||||
private SessionSerializer resolveSessionSerializer() {
|
||||
return getApplicationContext().getBean(SESSION_SERIALIZER_BEAN_ALIAS, SessionSerializer.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -497,8 +512,6 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
(PdxSerializer) sessionSerializer, cacheFactoryBean.getPdxSerializer()));
|
||||
}
|
||||
else {
|
||||
// TODO add more intelligence to figure out what type of serializer has been configured
|
||||
// (e.g. PDX or DataSerialization based serializers)
|
||||
Optional.ofNullable(sessionSerializer)
|
||||
.ifPresent(serializer ->
|
||||
cacheFactoryBean.setPdxSerializer(ComposablePdxSerializer.compose(
|
||||
@@ -508,28 +521,14 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the {@link SessionRepository} bean used to interact with Apache Geode or Pivotal GemFire
|
||||
* as the Spring Session provider.
|
||||
*
|
||||
* @param gemfireOperations instance of {@link GemfireOperations} used to manage {@link Session} state
|
||||
* in Apache Geode or Pivotal GemFire.
|
||||
* @return a {@link GemFireOperationsSessionRepository} for managing (clustering/replicating) {@link Session} state
|
||||
* in Apache Geode or Pivotal GemFire.
|
||||
* @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository
|
||||
* @see org.springframework.data.gemfire.GemfireOperations
|
||||
*/
|
||||
@Bean
|
||||
public GemFireOperationsSessionRepository sessionRepository(
|
||||
@Qualifier("sessionRegionTemplate") GemfireOperations gemfireOperations) {
|
||||
@Bean(SESSION_DATA_SERIALIZER_BEAN_NAME)
|
||||
public Object sessionDataSerializer() {
|
||||
return new DataSerializableSessionSerializer();
|
||||
}
|
||||
|
||||
GemFireOperationsSessionRepository sessionRepository =
|
||||
new GemFireOperationsSessionRepository(gemfireOperations);
|
||||
|
||||
sessionRepository.setMaxInactiveIntervalInSeconds(getMaxInactiveIntervalInSeconds());
|
||||
sessionRepository.setUseDataSerialization(isUsingDataSerialization());
|
||||
|
||||
return sessionRepository;
|
||||
@Bean(SESSION_PDX_SERIALIZER_BEAN_NAME)
|
||||
public Object sessionPdxSerializer() {
|
||||
return new PdxSerializableSessionSerializer();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -634,16 +633,28 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
return new GemfireTemplate(gemfireCache.getRegion(getSessionRegionName()));
|
||||
}
|
||||
|
||||
@Bean(SESSION_DATA_SERIALIZER_BEAN_NAME)
|
||||
//@Conditional(DataSerializableSessionSerializerCondition.class)
|
||||
public Object sessionDataSerializer() {
|
||||
return new PdxSerializableSessionSerializer();
|
||||
}
|
||||
/**
|
||||
* Defines the {@link SessionRepository} bean used to interact with Apache Geode or Pivotal GemFire
|
||||
* as the Spring Session provider.
|
||||
*
|
||||
* @param gemfireOperations instance of {@link GemfireOperations} used to manage {@link Session} state
|
||||
* in Apache Geode or Pivotal GemFire.
|
||||
* @return a {@link GemFireOperationsSessionRepository} for managing (clustering/replicating) {@link Session} state
|
||||
* in Apache Geode or Pivotal GemFire.
|
||||
* @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository
|
||||
* @see org.springframework.data.gemfire.GemfireOperations
|
||||
*/
|
||||
@Bean
|
||||
public GemFireOperationsSessionRepository sessionRepository(
|
||||
@Qualifier("sessionRegionTemplate") GemfireOperations gemfireOperations) {
|
||||
|
||||
@Bean(SESSION_PDX_SERIALIZER_BEAN_NAME)
|
||||
//@Conditional(PdxSerializableSessionSerializerCondition.class)
|
||||
public Object sessionPdxSerializer() {
|
||||
return new DataSerializableSessionSerializer();
|
||||
GemFireOperationsSessionRepository sessionRepository =
|
||||
new GemFireOperationsSessionRepository(gemfireOperations);
|
||||
|
||||
sessionRepository.setMaxInactiveIntervalInSeconds(getMaxInactiveIntervalInSeconds());
|
||||
sessionRepository.setUseDataSerialization(isUsingDataSerialization());
|
||||
|
||||
return sessionRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -695,40 +706,4 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
|
||||
return sessionAttributesIndex;
|
||||
}
|
||||
|
||||
public static class DataSerializableSessionSerializerCondition implements Condition {
|
||||
|
||||
@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));
|
||||
}
|
||||
}
|
||||
|
||||
public static class PdxSerializableSessionSerializerCondition implements Condition {
|
||||
|
||||
@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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,13 +58,6 @@ public abstract class AbstractDataSerializableSessionSerializer<T> extends DataS
|
||||
return DEFAULT_ALLOW_JAVA_SERIALIZATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean canSerialize(Class<?> type) {
|
||||
return stream(nullSafeArray(getSupportedClasses(), Class.class))
|
||||
.anyMatch(supportedClass -> supportedClass.isAssignableFrom(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean toData(Object session, DataOutput out) throws IOException {
|
||||
@@ -95,6 +88,14 @@ public abstract class AbstractDataSerializableSessionSerializer<T> extends DataS
|
||||
return DataSerializer.readObject(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean canSerialize(Class<?> type) {
|
||||
return stream(nullSafeArray(getSupportedClasses(), Class.class))
|
||||
.filter(it -> type != null)
|
||||
.anyMatch(supportedClass -> supportedClass.isAssignableFrom(type));
|
||||
}
|
||||
|
||||
protected <T> T safeRead(DataInput in, DataInputReader<T> reader) {
|
||||
try {
|
||||
return reader.doRead(in);
|
||||
|
||||
@@ -18,18 +18,28 @@ package org.springframework.session.data.gemfire.serialization.data.provider;
|
||||
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.asArray;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeSet;
|
||||
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.DeltaCapableGemFireSessionAttributes;
|
||||
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.gemfire.serialization.SessionSerializer;
|
||||
import org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer;
|
||||
|
||||
/**
|
||||
* The {@link DataSerializableSessionAttributesSerializer} class...
|
||||
* The {@link DataSerializableSessionAttributesSerializer} class is an implementation of the {@link SessionSerializer}
|
||||
* interface used to serialize a Spring {@link Session} attributes using the GemFire/Geode's Data Serialization
|
||||
* framework.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.io.DataInput
|
||||
* @see java.io.DataOutput
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.serialization.SessionSerializer
|
||||
* @see org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@@ -47,7 +57,7 @@ public class DataSerializableSessionAttributesSerializer
|
||||
|
||||
@Override
|
||||
public Class<?>[] getSupportedClasses() {
|
||||
return asArray(GemFireSessionAttributes.class);
|
||||
return asArray(GemFireSessionAttributes.class, DeltaCapableGemFireSessionAttributes.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,16 +25,25 @@ import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.DeltaCapableGemFireSession;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSession;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes;
|
||||
import org.springframework.session.data.gemfire.serialization.SessionSerializer;
|
||||
import org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer;
|
||||
import org.springframework.session.data.gemfire.support.AbstractSession;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link DataSerializableSessionSerializer} class...
|
||||
* The {@link DataSerializableSessionSerializer} class is an implementation of the {@link SessionSerializer} interface
|
||||
* used to serialize a Spring {@link Session} using the GemFire/Geode's Data Serialization framework.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.io.DataInput
|
||||
* @see java.io.DataOutput
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.serialization.SessionSerializer
|
||||
* @see org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@@ -52,7 +61,7 @@ public class DataSerializableSessionSerializer extends AbstractDataSerializableS
|
||||
|
||||
@Override
|
||||
public Class<?>[] getSupportedClasses() {
|
||||
return asArray(GemFireSession.class);
|
||||
return asArray(GemFireSession.class, DeltaCapableGemFireSession.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,43 +24,58 @@ import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import org.apache.geode.DataSerializer;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.DeltaCapableGemFireSession;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.DeltaCapableGemFireSessionAttributes;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSession;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes;
|
||||
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
|
||||
import org.springframework.session.data.gemfire.serialization.SessionSerializer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* The DataSerializerSessionSerializerAdapter class...
|
||||
* The {@link DataSerializerSessionSerializerAdapter} class is a two-way Adapter adapting a {@link SessionSerializer}
|
||||
* instance as an instance of {@link DataSerializer} in a GemFire/Geode context, or adapting a {@link DataSerializer}
|
||||
* as a {@link SessionSerializer} in a Spring Session context.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.DataSerializer
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.serialization.SessionSerializer
|
||||
* @see org.springframework.session.data.gemfire.serialization.data.support.WirableDataSerializer
|
||||
* @see org.springframework.stereotype.Component
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Component("org.springfamework.session.data.gemfire.serialization.data.support.DataSerializerSessionSerializerAdapter")
|
||||
public class DataSerializerSessionSerializerAdapter<T extends Session> extends WirableDataSerializer<T> {
|
||||
|
||||
static {
|
||||
register(DataSerializerSessionSerializerAdapter.class);
|
||||
}
|
||||
|
||||
@Resource(name = "${" + GemFireHttpSessionConfiguration.SESSION_SERIALIZER_QUALIFIER_PROPERTY_NAME
|
||||
+ ":" + GemFireHttpSessionConfiguration.SESSION_DATA_SERIALIZER_BEAN_NAME + "}")
|
||||
private SessionSerializer<T, DataInput, DataOutput> sessionSerializer;
|
||||
|
||||
public DataSerializerSessionSerializerAdapter() {
|
||||
autowire();
|
||||
}
|
||||
|
||||
public DataSerializerSessionSerializerAdapter(SessionSerializer<T, DataInput, DataOutput> sessionSerializer) {
|
||||
this.sessionSerializer = Optional.ofNullable(sessionSerializer)
|
||||
.orElseThrow(() -> newIllegalArgumentException("SessionSerializer is required"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return 0x0BAC2BAC;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@Qualifier(GemFireHttpSessionConfiguration.SESSION_SERIALIZER_BEAN_ALIAS)
|
||||
public final void setSessionSerializer(SessionSerializer<T, DataInput, DataOutput> sessionSerializer) {
|
||||
this.sessionSerializer = Optional.ofNullable(sessionSerializer)
|
||||
.orElseThrow(() -> newIllegalArgumentException("SessionSerializer is required"));
|
||||
}
|
||||
|
||||
protected SessionSerializer<T, DataInput, DataOutput> getSessionSerializer() {
|
||||
return Optional.ofNullable(this.sessionSerializer)
|
||||
.orElseThrow(() -> newIllegalStateException("SessionSerializer was not properly configured"));
|
||||
@@ -68,7 +83,8 @@ public class DataSerializerSessionSerializerAdapter<T extends Session> extends W
|
||||
|
||||
@Override
|
||||
public Class<?>[] getSupportedClasses() {
|
||||
return asArray(Session.class);
|
||||
return asArray(GemFireSession.class, GemFireSessionAttributes.class, DeltaCapableGemFireSession.class,
|
||||
DeltaCapableGemFireSessionAttributes.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,31 +18,47 @@ package org.springframework.session.data.gemfire.serialization.data.support;
|
||||
|
||||
import static org.springframework.data.gemfire.support.GemfireBeanFactoryLocator.newBeanFactoryLocator;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.DataSerializer;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||
import org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* The WirableDataSerializer class...
|
||||
* {@link WirableDataSerializer} is an abstract base class supporting auto-wiring of a non-managed,
|
||||
* GemFire/Geode {@link DataSerializer}, Spring {@link Component}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.DataSerializer
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.wiring.BeanConfigurerSupport
|
||||
* @see org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public abstract class WirableDataSerializer<T> extends AbstractDataSerializableSessionSerializer<T> {
|
||||
abstract class WirableDataSerializer<T> extends AbstractDataSerializableSessionSerializer<T> {
|
||||
|
||||
protected final void autowire() {
|
||||
|
||||
BeanConfigurerSupport beanConfigurer = newBeanConfigurer(locateBeanFactory());
|
||||
|
||||
beanConfigurer.configureBean(this);
|
||||
beanConfigurer.destroy();
|
||||
locateBeanFactory().map(this::newBeanConfigurer).ifPresent(beanConfigurer -> {
|
||||
beanConfigurer.configureBean(this);
|
||||
beanConfigurer.destroy();
|
||||
});
|
||||
}
|
||||
|
||||
private BeanFactory locateBeanFactory() {
|
||||
return newBeanFactoryLocator().useBeanFactory();
|
||||
Optional<BeanFactory> locateBeanFactory() {
|
||||
|
||||
try {
|
||||
return Optional.ofNullable(newBeanFactoryLocator().useBeanFactory());
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private BeanConfigurerSupport newBeanConfigurer(BeanFactory beanFactory) {
|
||||
BeanConfigurerSupport newBeanConfigurer(BeanFactory beanFactory) {
|
||||
|
||||
BeanConfigurerSupport beanConfigurer = new BeanConfigurerSupport();
|
||||
|
||||
|
||||
@@ -26,19 +26,23 @@ import org.springframework.session.Session;
|
||||
import org.springframework.session.data.gemfire.serialization.SessionSerializer;
|
||||
|
||||
/**
|
||||
* The {@link AbstractPdxSerializableSessionSerializer} class...
|
||||
* The {@link AbstractPdxSerializableSessionSerializer} class is an abstract base class containing functionality common
|
||||
* to all GemFire/Geode PDX-based {@link SessionSerializer} implementations.
|
||||
*
|
||||
* This class also implements GemFire/Geode's {@link PdxSerializer} interface, adapting it to the Spring Session,
|
||||
* Data GemFire {@link SessionSerializer} interface.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.pdx.PdxReader
|
||||
* @see org.apache.geode.pdx.PdxWriter
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.serialization.SessionSerializer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public abstract class AbstractPdxSerializableSessionSerializer<T extends Session>
|
||||
implements PdxSerializer, SessionSerializer<T, PdxReader, PdxWriter> {
|
||||
|
||||
@Override
|
||||
public boolean canSerialize(Class<?> type) {
|
||||
return Optional.ofNullable(type).map(Session.class::isAssignableFrom).orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean toData(Object session, PdxWriter writer) {
|
||||
@@ -60,4 +64,9 @@ public abstract class AbstractPdxSerializableSessionSerializer<T extends Session
|
||||
.map(it -> deserialize(reader))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSerialize(Class<?> type) {
|
||||
return Optional.ofNullable(type).map(Session.class::isAssignableFrom).orElse(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,29 +29,31 @@ import java.util.Set;
|
||||
import org.apache.geode.pdx.PdxReader;
|
||||
import org.apache.geode.pdx.PdxWriter;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.gemfire.serialization.SessionSerializer;
|
||||
import org.springframework.session.data.gemfire.serialization.pdx.AbstractPdxSerializableSessionSerializer;
|
||||
import org.springframework.session.data.gemfire.support.AbstractSession;
|
||||
|
||||
/**
|
||||
* The PdxSerializableSessionSerializer class...
|
||||
* The {@link PdxSerializableSessionSerializer} class is an implementation of the {@link SessionSerializer} interface
|
||||
* used to serialize a Spring {@link Session} using the GemFire/Geode's PDX Serialization framework.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
* @see org.apache.geode.pdx.PdxReader
|
||||
* @see org.apache.geode.pdx.PdxWriter
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.serialization.SessionSerializer
|
||||
* @see org.springframework.session.data.gemfire.serialization.pdx.AbstractPdxSerializableSessionSerializer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class PdxSerializableSessionSerializer extends AbstractPdxSerializableSessionSerializer<GemFireSession> {
|
||||
|
||||
@Override
|
||||
public boolean canSerialize(Class<?> type) {
|
||||
return Optional.ofNullable(type).map(GemFireSession.class::isAssignableFrom).orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
|
||||
public void serialize(GemFireSession session, PdxWriter writer) {
|
||||
|
||||
synchronized (session) {
|
||||
|
||||
writer.writeString("id", session.getId());
|
||||
writer.writeLong("creationTime", session.getCreationTime().toEpochMilli());
|
||||
writer.writeLong("lastAccessedTime", session.getLastAccessedTime().toEpochMilli());
|
||||
@@ -102,4 +104,9 @@ public class PdxSerializableSessionSerializer extends AbstractPdxSerializableSes
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSerialize(Class<?> type) {
|
||||
return Optional.ofNullable(type).map(GemFireSession.class::isAssignableFrom).orElse(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,23 +34,19 @@ import org.apache.geode.pdx.PdxSerializer;
|
||||
import org.apache.geode.pdx.PdxWriter;
|
||||
|
||||
/**
|
||||
* The ComposablePdxSerializer class...
|
||||
* The {@link ComposablePdxSerializer} class is a composite of {@link PdxSerializer} objects implementing
|
||||
* the Composite Software Design Pattern.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
* @see java.lang.Iterable
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ComposablePdxSerializer implements Iterable<PdxSerializer>, PdxSerializer {
|
||||
public class ComposablePdxSerializer implements PdxSerializer, Iterable<PdxSerializer> {
|
||||
|
||||
private final List<PdxSerializer> pdxSerializers;
|
||||
|
||||
private ComposablePdxSerializer(List<PdxSerializer> pdxSerializers) {
|
||||
|
||||
this.pdxSerializers = Optional.ofNullable(pdxSerializers)
|
||||
.map(it -> Collections.unmodifiableList(pdxSerializers))
|
||||
.orElseThrow(() -> newIllegalArgumentException("PdxSerializers [%s] are required", pdxSerializers));
|
||||
}
|
||||
|
||||
public static PdxSerializer compose(PdxSerializer... pdxSerializers) {
|
||||
return compose(Arrays.asList(nullSafeArray(pdxSerializers, PdxSerializer.class)));
|
||||
}
|
||||
@@ -66,6 +62,13 @@ public class ComposablePdxSerializer implements Iterable<PdxSerializer>, PdxSeri
|
||||
: new ComposablePdxSerializer(pdxSerializerList)));
|
||||
}
|
||||
|
||||
private ComposablePdxSerializer(List<PdxSerializer> pdxSerializers) {
|
||||
|
||||
this.pdxSerializers = Optional.ofNullable(pdxSerializers)
|
||||
.map(it -> Collections.unmodifiableList(pdxSerializers))
|
||||
.orElseThrow(() -> newIllegalArgumentException("PdxSerializers [%s] are required", pdxSerializers));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<PdxSerializer> iterator() {
|
||||
return this.pdxSerializers.iterator();
|
||||
|
||||
@@ -21,6 +21,7 @@ import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newI
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.pdx.PdxReader;
|
||||
import org.apache.geode.pdx.PdxSerializer;
|
||||
import org.apache.geode.pdx.PdxWriter;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
@@ -28,9 +29,15 @@ import org.springframework.session.data.gemfire.serialization.SessionSerializer;
|
||||
import org.springframework.session.data.gemfire.serialization.pdx.AbstractPdxSerializableSessionSerializer;
|
||||
|
||||
/**
|
||||
* The {@link PdxSerializerSessionSerializerAdapter} class...
|
||||
* The {@link PdxSerializerSessionSerializerAdapter} class is a two-way Adapter adapting a {@link SessionSerializer}
|
||||
* instance as an instance of {@link PdxSerializer} in a GemFire/Geode context, or adapting a {@link PdxSerializer}
|
||||
* as a {@link SessionSerializer} in a Spring Session context.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.serialization.SessionSerializer
|
||||
* @see org.springframework.session.data.gemfire.serialization.pdx.AbstractPdxSerializableSessionSerializer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
@@ -28,7 +28,6 @@ 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;
|
||||
|
||||
@@ -78,11 +77,6 @@ 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 {
|
||||
@@ -324,7 +318,7 @@ public class GemFireHttpSessionConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postConstructInitSetsSystemPropertyAndRegistersBeanAlias() {
|
||||
public void postConstructInitRegistersBeanAlias() {
|
||||
|
||||
ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class);
|
||||
|
||||
@@ -332,20 +326,18 @@ public class GemFireHttpSessionConfigurationTests {
|
||||
|
||||
given(mockApplicationContext.getBeanFactory()).willReturn(mockBeanFactory);
|
||||
|
||||
assertThat(System.getProperty(GemFireHttpSessionConfiguration.SESSION_SERIALIZER_REGISTERED_ALIAS)).isNull();
|
||||
assertThat(System.getProperty(GemFireHttpSessionConfiguration.SESSION_SERIALIZER_BEAN_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));
|
||||
eq(GemFireHttpSessionConfiguration.SESSION_SERIALIZER_BEAN_ALIAS));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link SessionSerializer} interface.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.session.data.gemfire.serialization.SessionSerializer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SessionSerializerTests {
|
||||
|
||||
@Mock
|
||||
private SessionSerializer sessionSerializer;
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void canSerializeWithSerializableObjectReturnsTrue() {
|
||||
|
||||
when(this.sessionSerializer.canSerialize(any(Class.class))).thenReturn(true);
|
||||
when(this.sessionSerializer.canSerialize(any(Object.class))).thenCallRealMethod();
|
||||
|
||||
assertThat(this.sessionSerializer.canSerialize("test")).isTrue();
|
||||
|
||||
verify(this.sessionSerializer, times(1)).canSerialize(eq("test"));
|
||||
verify(this.sessionSerializer, times(1)).canSerialize(eq(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void canSerializeWithNullReturnFalse() {
|
||||
|
||||
assertThat(this.sessionSerializer.canSerialize((Object) null)).isFalse();
|
||||
|
||||
verify(this.sessionSerializer, times(1)).canSerialize(eq((Object) null));
|
||||
verify(this.sessionSerializer, never()).canSerialize(any(Class.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void canSerializeWithNonSerializableObjectReturnFalse() {
|
||||
|
||||
when(this.sessionSerializer.canSerialize(any(Class.class))).thenReturn(false);
|
||||
when(this.sessionSerializer.canSerialize(any(Object.class))).thenCallRealMethod();
|
||||
|
||||
assertThat(this.sessionSerializer.canSerialize("test")).isFalse();
|
||||
|
||||
verify(this.sessionSerializer, times(1)).canSerialize(eq("test"));
|
||||
verify(this.sessionSerializer, times(1)).canSerialize(eq(String.class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.asArray;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.gemfire.serialization.SerializationException;
|
||||
import org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer.DataInputReader;
|
||||
import org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer.DataOutputWriter;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractDataSerializableSessionSerializer}.
|
||||
*
|
||||
* @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.serialization.data.AbstractDataSerializableSessionSerializer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractDataSerializableSessionSerializerTests {
|
||||
|
||||
@Spy
|
||||
private AbstractDataSerializableSessionSerializer<Session> sessionSerializer;
|
||||
|
||||
@Mock
|
||||
private DataInput mockDataInput;
|
||||
|
||||
@Mock
|
||||
private DataOutput mockDataOuput;
|
||||
|
||||
@Mock
|
||||
private Session mockSession;
|
||||
|
||||
@Test
|
||||
public void constructAbstractDataSerializableSessionSerializer() {
|
||||
|
||||
assertThat(this.sessionSerializer).isNotNull();
|
||||
assertThat(this.sessionSerializer.getId()).isEqualTo(0xA11ACE5);
|
||||
assertThat(this.sessionSerializer.getSupportedClasses()).isEmpty();
|
||||
assertThat(this.sessionSerializer.allowJavaSerialization()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDataCallsSerializeForSerializableObjectAndReturnsTrue() throws IOException {
|
||||
|
||||
when(this.sessionSerializer.canSerialize(any(Session.class))).thenReturn(true);
|
||||
|
||||
assertThat(this.sessionSerializer.toData(this.mockSession, this.mockDataOuput)).isTrue();
|
||||
|
||||
verify(this.sessionSerializer, times(1)).canSerialize(eq(this.mockSession));
|
||||
verify(this.sessionSerializer, times(1))
|
||||
.serialize(eq(this.mockSession), eq(this.mockDataOuput));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDataWithNonSerializableObjectReturnsFalse() throws IOException {
|
||||
|
||||
when(this.sessionSerializer.canSerialize(any())).thenReturn(false);
|
||||
|
||||
assertThat(this.sessionSerializer.toData("test", this.mockDataOuput)).isFalse();
|
||||
|
||||
verify(this.sessionSerializer, times(1)).canSerialize(eq("test"));
|
||||
verify(this.sessionSerializer, never()).serialize(any(), any(DataOutput.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDataWithNullReturnsFalse() throws IOException {
|
||||
|
||||
assertThat(this.sessionSerializer.toData(null, this.mockDataOuput)).isFalse();
|
||||
|
||||
verify(this.sessionSerializer, never()).canSerialize(any());
|
||||
verify(this.sessionSerializer, never()).serialize(any(), any(DataOutput.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeObjectDefaultsAllowJavaSerializationToTrue() throws IOException {
|
||||
|
||||
this.sessionSerializer.serializeObject("test", this.mockDataOuput);
|
||||
|
||||
verify(this.sessionSerializer, times(1))
|
||||
.serializeObject(eq("test"), eq(this.mockDataOuput), eq(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeObjectWithAllowJavaSerializationSetToFalse() throws IOException {
|
||||
this.sessionSerializer.serializeObject("test", this.mockDataOuput, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromDataCallsDeserialize() throws IOException, ClassNotFoundException {
|
||||
|
||||
when(this.sessionSerializer.deserialize(any(DataInput.class))).thenReturn(this.mockSession);
|
||||
|
||||
assertThat(this.sessionSerializer.fromData(this.mockDataInput)).isEqualTo(this.mockSession);
|
||||
|
||||
verify(this.sessionSerializer, times(1)).deserialize(eq(this.mockDataInput));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSerializeSerializableType() {
|
||||
|
||||
when(this.sessionSerializer.getSupportedClasses()).thenReturn(asArray(Session.class));
|
||||
|
||||
assertThat(this.sessionSerializer.canSerialize(this.mockSession)).isTrue();
|
||||
|
||||
verify(this.sessionSerializer, times(1)).getSupportedClasses();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSerializeSerializableSubType() {
|
||||
|
||||
when(this.sessionSerializer.getSupportedClasses()).thenReturn(asArray(Number.class, Integer.class, Long.class));
|
||||
|
||||
assertThat(this.sessionSerializer.canSerialize((short) 64)).isTrue();
|
||||
|
||||
verify(this.sessionSerializer, times(1)).getSupportedClasses();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cannotSerializeNonSerializableType() {
|
||||
|
||||
when(this.sessionSerializer.getSupportedClasses()).thenReturn(asArray(Session.class));
|
||||
|
||||
assertThat(this.sessionSerializer.canSerialize("sessionId")).isFalse();
|
||||
|
||||
verify(this.sessionSerializer, times(1)).getSupportedClasses();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cannotSerializeNull() {
|
||||
|
||||
when(this.sessionSerializer.getSupportedClasses()).thenReturn(asArray(Object.class));
|
||||
|
||||
assertThat(this.sessionSerializer.canSerialize(null)).isFalse();
|
||||
|
||||
verify(this.sessionSerializer, times(1)).getSupportedClasses();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cannotSerializeWhenSupportClassesAreEmpty() {
|
||||
|
||||
when(this.sessionSerializer.getSupportedClasses()).thenReturn(asArray());
|
||||
|
||||
assertThat(this.sessionSerializer.canSerialize("test")).isFalse();
|
||||
|
||||
verify(this.sessionSerializer, times(1)).getSupportedClasses();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cannotSerializeWhenSupportClassesAreNull() {
|
||||
|
||||
when(this.sessionSerializer.getSupportedClasses()).thenReturn(null);
|
||||
|
||||
assertThat(this.sessionSerializer.canSerialize("test")).isFalse();
|
||||
|
||||
verify(this.sessionSerializer, times(1)).getSupportedClasses();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void safeReadReturnsValue() throws IOException, ClassNotFoundException {
|
||||
|
||||
DataInputReader<String> mockDataInputReader = mock(DataInputReader.class);
|
||||
|
||||
when(mockDataInputReader.doRead(any(DataInput.class))).thenReturn("test");
|
||||
|
||||
assertThat(this.sessionSerializer.safeRead(this.mockDataInput, mockDataInputReader)).isEqualTo("test");
|
||||
|
||||
verify(mockDataInputReader, times(1)).doRead(eq(this.mockDataInput));
|
||||
}
|
||||
|
||||
@Test(expected = SerializationException.class)
|
||||
@SuppressWarnings("unchecked")
|
||||
public void safeReadHandlesClassCastException() throws IOException, ClassNotFoundException {
|
||||
|
||||
DataInputReader<String> mockDataInputReader = mock(DataInputReader.class);
|
||||
|
||||
when(mockDataInputReader.doRead(any(DataInput.class))).thenThrow(new ClassNotFoundException("test"));
|
||||
|
||||
try {
|
||||
this.sessionSerializer.safeRead(this.mockDataInput, mockDataInputReader);
|
||||
}
|
||||
catch (Exception expected) {
|
||||
|
||||
assertThat(expected).isInstanceOf(SerializationException.class);
|
||||
assertThat(expected).hasCauseInstanceOf(ClassNotFoundException.class);
|
||||
assertThat(expected.getCause()).hasMessage("test");
|
||||
assertThat(expected.getCause()).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockDataInputReader, times(1)).doRead(eq(this.mockDataInput));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = SerializationException.class)
|
||||
@SuppressWarnings("unchecked")
|
||||
public void safeReadHandlesIOException() throws IOException, ClassNotFoundException {
|
||||
|
||||
DataInputReader<String> mockDataInputReader = mock(DataInputReader.class);
|
||||
|
||||
when(mockDataInputReader.doRead(any(DataInput.class))).thenAnswer(invocation ->
|
||||
invocation.<DataInput>getArgument(0).readUTF());
|
||||
|
||||
when(this.mockDataInput.readUTF()).thenThrow(new IOException("test"));
|
||||
|
||||
try {
|
||||
this.sessionSerializer.safeRead(this.mockDataInput, mockDataInputReader);
|
||||
}
|
||||
catch (Exception expected) {
|
||||
|
||||
assertThat(expected).isInstanceOf(SerializationException.class);
|
||||
assertThat(expected).hasCauseInstanceOf(IOException.class);
|
||||
assertThat(expected.getCause()).hasMessage("test");
|
||||
assertThat(expected.getCause()).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockDataInputReader, times(1)).doRead(eq(this.mockDataInput));
|
||||
verify(this.mockDataInput, times(1)).readUTF();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void safeWriteWritesValue() throws IOException {
|
||||
|
||||
DataOutputWriter mockDataOutputWriter = mock(DataOutputWriter.class);
|
||||
|
||||
this.sessionSerializer.safeWrite(this.mockDataOuput, mockDataOutputWriter);
|
||||
|
||||
verify(mockDataOutputWriter, times(1)).doWrite(eq(this.mockDataOuput));
|
||||
}
|
||||
|
||||
@Test(expected = SerializationException.class)
|
||||
public void safeWriteHandlesIOException() throws IOException {
|
||||
|
||||
DataOutputWriter mockDataOutputWriter = mock(DataOutputWriter.class);
|
||||
|
||||
doThrow(new IOException("test")).when(mockDataOutputWriter).doWrite(any(DataOutput.class));
|
||||
|
||||
try {
|
||||
this.sessionSerializer.safeWrite(this.mockDataOuput, mockDataOutputWriter);
|
||||
}
|
||||
catch (Exception expected ) {
|
||||
|
||||
assertThat(expected).isInstanceOf(SerializationException.class);
|
||||
assertThat(expected).hasCauseInstanceOf(IOException.class);
|
||||
assertThat(expected.getCause()).hasMessage("test");
|
||||
assertThat(expected.getCause()).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockDataOutputWriter, times(1)).doWrite(eq(this.mockDataOuput));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ 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.DeltaCapableGemFireSessionAttributes;
|
||||
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes;
|
||||
|
||||
import java.io.DataInput;
|
||||
@@ -62,8 +63,9 @@ public class DataSerializableSessionAttributesSerializerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportedClassesContainsGemFireSessionAttributes() {
|
||||
public void supportedClassesContainsGemFireSessionAttributesAndSubTypes() {
|
||||
assertThat(this.sessionAttributesSerializer.getSupportedClasses()).contains(GemFireSessionAttributes.class);
|
||||
assertThat(this.sessionAttributesSerializer.getSupportedClasses()).contains(DeltaCapableGemFireSessionAttributes.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -27,6 +27,7 @@ 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.GemFireSession;
|
||||
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes;
|
||||
|
||||
@@ -73,8 +74,9 @@ public class DataSerializableSessionSerializerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportedClassContainsGemFireSession() {
|
||||
public void supportedClassContainsGemFireSessionAndSubTypes() {
|
||||
assertThat(this.sessionSerializer.getSupportedClasses()).contains(GemFireSession.class);
|
||||
assertThat(this.sessionSerializer.getSupportedClasses()).contains(DeltaCapableGemFireSession.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.gemfire.serialization.SessionSerializer;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DataSerializerSessionSerializerAdapter}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.io.DataInput
|
||||
* @see java.io.DataOutput
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.serialization.SessionSerializer
|
||||
* @see org.springframework.session.data.gemfire.serialization.data.support.DataSerializerSessionSerializerAdapter
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class DataSerializerSessionSerializerAdapterUnitTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setAndGetSessionSerializerReturnsExpected() {
|
||||
|
||||
SessionSerializer<Session, DataInput, DataOutput> mockSessionSerializer = mock(SessionSerializer.class);
|
||||
|
||||
DataSerializerSessionSerializerAdapter<Session> dataSerializer =
|
||||
new DataSerializerSessionSerializerAdapter<>();
|
||||
|
||||
dataSerializer.setSessionSerializer(mockSessionSerializer);
|
||||
|
||||
assertThat(dataSerializer.getSessionSerializer()).isSameAs(mockSessionSerializer);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setSessionSerializerToNullThrowsIllegalArgumentException() {
|
||||
|
||||
try {
|
||||
new DataSerializerSessionSerializerAdapter<>().setSessionSerializer(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("SessionSerializer is required");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getUninitializedSessionSerializerThrowsIllegalStateException() {
|
||||
|
||||
try {
|
||||
new DataSerializerSessionSerializerAdapter<>().getSessionSerializer();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("SessionSerializer was not properly configured");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void serializeDelegatesToSessionSerializerSerialize() {
|
||||
|
||||
DataOutput mockDataOutput = mock(DataOutput.class);
|
||||
|
||||
Session mockSession = mock(Session.class);
|
||||
|
||||
SessionSerializer<Session, DataInput, DataOutput> mockSessionSerializer = mock(SessionSerializer.class);
|
||||
|
||||
DataSerializerSessionSerializerAdapter<Session> dataSerializer = new DataSerializerSessionSerializerAdapter<>();
|
||||
|
||||
dataSerializer.setSessionSerializer(mockSessionSerializer);
|
||||
|
||||
assertThat(dataSerializer.getSessionSerializer()).isSameAs(mockSessionSerializer);
|
||||
|
||||
dataSerializer.serialize(mockSession, mockDataOutput);
|
||||
|
||||
verify(mockSessionSerializer, times(1)).serialize(eq(mockSession), eq(mockDataOutput));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void deserializeDelegatesToSessionSerializerDeserialize() {
|
||||
|
||||
DataInput mockDataInput = mock(DataInput.class);
|
||||
|
||||
Session mockSession = mock(Session.class);
|
||||
|
||||
SessionSerializer<Session, DataInput, DataOutput> mockSessionSerializer = mock(SessionSerializer.class);
|
||||
|
||||
when(mockSessionSerializer.deserialize(any(DataInput.class))).thenReturn(mockSession);
|
||||
|
||||
DataSerializerSessionSerializerAdapter<Session> dataSerializer = new DataSerializerSessionSerializerAdapter<>();
|
||||
|
||||
dataSerializer.setSessionSerializer(mockSessionSerializer);
|
||||
|
||||
assertThat(dataSerializer.getSessionSerializer()).isSameAs(mockSessionSerializer);
|
||||
assertThat(dataSerializer.deserialize(mockDataInput)).isEqualTo(mockSession);
|
||||
|
||||
verify(mockSessionSerializer, times(1)).deserialize(eq(mockDataInput));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||
import org.springframework.data.gemfire.support.GemfireBeanFactoryLocator;
|
||||
import org.springframework.session.Session;
|
||||
|
||||
/**
|
||||
* The WirableDataSerializerTests class...
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class WirableDataSerializerTests {
|
||||
|
||||
@Mock
|
||||
private ConfigurableListableBeanFactory mockBeanFactory;
|
||||
|
||||
@Spy
|
||||
private WirableDataSerializer<Session> dataSerializer;
|
||||
|
||||
@Test
|
||||
public void autowiresThis() {
|
||||
|
||||
AtomicReference<BeanConfigurerSupport> beanConfigurerReference = new AtomicReference<>(null);
|
||||
|
||||
doReturn(Optional.of(this.mockBeanFactory)).when(this.dataSerializer).locateBeanFactory();
|
||||
|
||||
doAnswer(invocation -> {
|
||||
BeanConfigurerSupport beanConfigurer = spy((BeanConfigurerSupport) invocation.callRealMethod());
|
||||
doNothing().when(beanConfigurer).configureBean(any());
|
||||
beanConfigurerReference.compareAndSet(null, beanConfigurer);
|
||||
return beanConfigurer;
|
||||
}).when(this.dataSerializer).newBeanConfigurer(any(BeanFactory.class));
|
||||
|
||||
this.dataSerializer.autowire();
|
||||
|
||||
assertThat(beanConfigurerReference.get()).isNotNull();
|
||||
|
||||
verify(this.dataSerializer, times(1)).locateBeanFactory();
|
||||
verify(this.dataSerializer, times(1)).newBeanConfigurer(eq(this.mockBeanFactory));
|
||||
verify(beanConfigurerReference.get(), times(1)).configureBean(eq(this.dataSerializer));
|
||||
verify(beanConfigurerReference.get(), times(1)).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noAutowiringWhenBeanFactoryCannotBeLocated() {
|
||||
|
||||
doReturn(Optional.empty()).when(this.dataSerializer).locateBeanFactory();
|
||||
|
||||
this.dataSerializer.autowire();
|
||||
|
||||
verify(this.dataSerializer, times(1)).locateBeanFactory();
|
||||
verify(this.dataSerializer, never()).newBeanConfigurer(any(BeanFactory.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void locatesBeanFactory() {
|
||||
|
||||
GemfireBeanFactoryLocator beanFactoryLocator = null;
|
||||
|
||||
try {
|
||||
when(this.mockBeanFactory.getAliases(anyString())).thenReturn(new String[0]);
|
||||
|
||||
beanFactoryLocator = GemfireBeanFactoryLocator.newBeanFactoryLocator(this.mockBeanFactory,
|
||||
"testBeanFactory");
|
||||
|
||||
assertThat(this.dataSerializer.locateBeanFactory().orElse(null)).isSameAs(this.mockBeanFactory);
|
||||
}
|
||||
finally {
|
||||
verify(this.mockBeanFactory, times(1)).getAliases(eq("testBeanFactory"));
|
||||
Optional.ofNullable(beanFactoryLocator).ifPresent(GemfireBeanFactoryLocator::destroy);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unableToLocateBeanFactory() {
|
||||
assertThat(this.dataSerializer.locateBeanFactory().orElse(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructsNewBeanConfigurerSupportWithBeanFactory() {
|
||||
|
||||
BeanConfigurerSupport beanConfigurer = null;
|
||||
|
||||
try {
|
||||
beanConfigurer = this.dataSerializer.newBeanConfigurer(this.mockBeanFactory);
|
||||
|
||||
assertThat(beanConfigurer).isNotNull();
|
||||
}
|
||||
finally {
|
||||
Optional.ofNullable(beanConfigurer).ifPresent(BeanConfigurerSupport::destroy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.pdx;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSession;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.apache.geode.pdx.PdxReader;
|
||||
import org.apache.geode.pdx.PdxWriter;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractPdxSerializableSessionSerializer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.Spy
|
||||
* @see org.apache.geode.pdx.PdxReader
|
||||
* @see org.apache.geode.pdx.PdxWriter
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.serialization.pdx.AbstractPdxSerializableSessionSerializer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractPdxSerializableSessionSerializerTests {
|
||||
|
||||
@Spy
|
||||
private AbstractPdxSerializableSessionSerializer<Session> sessionSerializer;
|
||||
|
||||
@Mock
|
||||
private PdxReader mockPdxReader;
|
||||
|
||||
@Mock
|
||||
private PdxWriter mockPdxWriter;
|
||||
|
||||
@Mock
|
||||
private Session mockSession;
|
||||
|
||||
@Test
|
||||
public void toDataSerializesSessionAndReturnsTrue() {
|
||||
|
||||
when(this.sessionSerializer.canSerialize(any(Object.class))).thenReturn(true);
|
||||
|
||||
assertThat(this.sessionSerializer.toData(this.mockSession, this.mockPdxWriter)).isTrue();
|
||||
|
||||
verify(this.sessionSerializer, times(1))
|
||||
.serialize(eq(this.mockSession), eq(this.mockPdxWriter));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDataWithNonSerializableObjectReturnsFalse() {
|
||||
|
||||
when(this.sessionSerializer.canSerialize(any(Object.class))).thenReturn(false);
|
||||
|
||||
assertThat(this.sessionSerializer.toData("test", this.mockPdxWriter)).isFalse();
|
||||
|
||||
verify(this.sessionSerializer, never()).serialize(any(), any(PdxWriter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDataWithNullReturnsFalse() {
|
||||
|
||||
assertThat(this.sessionSerializer.toData(null, this.mockPdxWriter)).isFalse();
|
||||
|
||||
verify(this.sessionSerializer, never()).serialize(any(), any(PdxWriter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromDataWithSessionTypeReturnsSessionObject() {
|
||||
|
||||
when(this.sessionSerializer.deserialize(eq(this.mockPdxReader))).thenReturn(this.mockSession);
|
||||
|
||||
assertThat(this.sessionSerializer.fromData(Session.class, this.mockPdxReader)).isEqualTo(this.mockSession);
|
||||
|
||||
verify(this.sessionSerializer, times(1)).canSerialize(eq(Session.class));
|
||||
verify(this.sessionSerializer, times(1)).deserialize(eq(this.mockPdxReader));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromDataWithNonSerializableTypeReturnsNull() {
|
||||
|
||||
when(this.sessionSerializer.canSerialize(any(Class.class))).thenReturn(false);
|
||||
|
||||
assertThat(this.sessionSerializer.fromData(Object.class, this.mockPdxReader)).isNull();
|
||||
|
||||
verify(this.sessionSerializer, times(1)).canSerialize(eq(Object.class));
|
||||
verify(this.sessionSerializer, never()).deserialize(any(PdxReader.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromDataWithNullReturnsNull() {
|
||||
|
||||
assertThat(this.sessionSerializer.fromData(null, this.mockPdxReader)).isNull();
|
||||
|
||||
verify(this.sessionSerializer, never()).canSerialize(any());
|
||||
verify(this.sessionSerializer, never()).deserialize(any(PdxReader.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSerializeSessionIsTrue() {
|
||||
assertThat(this.sessionSerializer.canSerialize(Session.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSerializeGemFireSessionIsTrue() {
|
||||
assertThat(this.sessionSerializer.canSerialize(GemFireSession.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSerializeObjectIsFalse() {
|
||||
assertThat(this.sessionSerializer.canSerialize(Object.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSerializeNullIsFalse() {
|
||||
assertThat(this.sessionSerializer.canSerialize(null)).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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.pdx.provider;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.DeltaCapableGemFireSession;
|
||||
import static org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSession;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.apache.geode.pdx.PdxReader;
|
||||
import org.apache.geode.pdx.PdxWriter;
|
||||
|
||||
import org.springframework.session.FindByIndexNameSessionRepository;
|
||||
|
||||
/**
|
||||
* The PdxSerializableSessionSerializerTests class...
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PdxSerializableSessionSerializerTests {
|
||||
|
||||
@Mock
|
||||
private PdxReader mockPdxReader;
|
||||
|
||||
@Mock
|
||||
private PdxWriter mockPdxWriter;
|
||||
|
||||
private PdxSerializableSessionSerializer sessionSerializer = new PdxSerializableSessionSerializer();
|
||||
|
||||
@Test
|
||||
public void serializeSessionIsCorrect() {
|
||||
|
||||
GemFireSession session = GemFireSession.create();
|
||||
|
||||
session.setMaxInactiveInterval(Duration.ofMinutes(30));
|
||||
session.setAttribute("attributeOne", "valueOne");
|
||||
session.setAttribute("attributeTwo", "valueTwo");
|
||||
|
||||
this.sessionSerializer.serialize(session, this.mockPdxWriter);
|
||||
|
||||
verify(this.mockPdxWriter, times(1))
|
||||
.writeString(eq("id"), eq(session.getId()));
|
||||
|
||||
verify(this.mockPdxWriter, times(1))
|
||||
.writeLong(eq("creationTime"), eq(session.getCreationTime().toEpochMilli()));
|
||||
|
||||
verify(this.mockPdxWriter, times(1))
|
||||
.writeLong(eq("lastAccessedTime"), eq(session.getLastAccessedTime().toEpochMilli()));
|
||||
|
||||
verify(this.mockPdxWriter, times(1))
|
||||
.writeLong(eq("maxInactiveIntervalInSeconds"), eq(session.getMaxInactiveInterval().getSeconds()));
|
||||
|
||||
verify(this.mockPdxWriter, times(1))
|
||||
.writeString(eq("principalName"), eq(session.getPrincipalName()));
|
||||
|
||||
verify(this.mockPdxWriter, times(1))
|
||||
.writeObject(eq("attributes"), eq(new HashMap<>(session.getAttributes())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newMapCopiesMap() {
|
||||
|
||||
Map<String, String> mapCopy = this.sessionSerializer.newMap(Collections.singletonMap("testKey", "testValue"));
|
||||
|
||||
assertThat(mapCopy).isInstanceOf(HashMap.class);
|
||||
assertThat(mapCopy).hasSize(1);
|
||||
assertThat(mapCopy).containsKey("testKey");
|
||||
assertThat(mapCopy.get("testKey")).isEqualTo("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void deserializeSessionIsCorrect() {
|
||||
|
||||
Duration expectedMaxInactiveInterval = Duration.ofMinutes(30);
|
||||
|
||||
Instant expectedCreationTime = Instant.now();
|
||||
Instant expectedLastAccessedTime = Instant.now();
|
||||
|
||||
Map<String, String> expectedAttributes = new HashMap<>(2);
|
||||
|
||||
expectedAttributes.put("attributeOne", "valueOne");
|
||||
expectedAttributes.put("attributeTwo", "valueTwo");
|
||||
expectedAttributes.put(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, "jonDoe");
|
||||
|
||||
when(this.mockPdxReader.readString(eq("id"))).thenReturn("123");
|
||||
when(this.mockPdxReader.readLong(eq("creationTime"))).thenReturn(expectedCreationTime.toEpochMilli());
|
||||
|
||||
when(this.mockPdxReader.readLong(eq("lastAccessedTime")))
|
||||
.thenReturn(expectedLastAccessedTime.toEpochMilli());
|
||||
|
||||
when(this.mockPdxReader.readLong(eq("maxInactiveIntervalInSeconds")))
|
||||
.thenReturn(expectedMaxInactiveInterval.getSeconds());
|
||||
|
||||
when(this.mockPdxReader.readString(eq("principalName"))).thenReturn("jonDoe");
|
||||
when(this.mockPdxReader.readObject(eq("attributes"))).thenReturn(expectedAttributes);
|
||||
|
||||
GemFireSession session = this.sessionSerializer.deserialize(this.mockPdxReader);
|
||||
|
||||
assertThat(session).isNotNull();
|
||||
assertThat(session.getId()).isEqualTo("123");
|
||||
assertThat(session.getCreationTime()).isEqualTo(expectedCreationTime);
|
||||
assertThat(session.getLastAccessedTime()).isEqualTo(expectedLastAccessedTime);
|
||||
assertThat(session.getMaxInactiveInterval()).isEqualTo(expectedMaxInactiveInterval);
|
||||
assertThat(session.getPrincipalName()).isEqualTo("jonDoe");
|
||||
assertThat(this.sessionSerializer.newMap(session.getAttributes())).isEqualTo(expectedAttributes);
|
||||
|
||||
verify(this.mockPdxReader, times(1)).readString(eq("id"));
|
||||
verify(this.mockPdxReader, times(1)).readLong(eq("creationTime"));
|
||||
verify(this.mockPdxReader, times(1)).readLong(eq("lastAccessedTime"));
|
||||
verify(this.mockPdxReader, times(1)).readLong(eq("maxInactiveIntervalInSeconds"));
|
||||
verify(this.mockPdxReader, times(1)).readString(eq("principalName"));
|
||||
verify(this.mockPdxReader, times(1)).readObject(eq("attributes"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSerializeGemFireSessionClassTypeIsTrue() {
|
||||
assertThat(this.sessionSerializer.canSerialize(GemFireSession.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSerializeDeltaCapableGemFireSessionClassTypeIsTrue() {
|
||||
assertThat(this.sessionSerializer.canSerialize(DeltaCapableGemFireSession.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSerializeObjectClassTypeIsFalse() {
|
||||
assertThat(this.sessionSerializer.canSerialize(Object.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSerializeNullClassTypeIsFalse() {
|
||||
assertThat(this.sessionSerializer.canSerialize(null)).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* 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.pdx.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.apache.geode.pdx.PdxReader;
|
||||
import org.apache.geode.pdx.PdxSerializer;
|
||||
import org.apache.geode.pdx.PdxWriter;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ComposablePdxSerializer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.pdx.PdxReader
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @see org.apache.geode.pdx.PdxWriter
|
||||
* @see org.springframework.session.data.gemfire.serialization.pdx.support.ComposablePdxSerializer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ComposablePdxSerializerTests {
|
||||
|
||||
@Mock
|
||||
private PdxReader mockPdxReader;
|
||||
|
||||
@Mock
|
||||
private PdxWriter mockPdxWriter;
|
||||
|
||||
@Mock
|
||||
private PdxSerializer mockPdxSerializerOne;
|
||||
|
||||
@Mock
|
||||
private PdxSerializer mockPdxSerializerTwo;
|
||||
|
||||
@Test
|
||||
public void composeArrayWithTwoPdxSerializers() {
|
||||
|
||||
PdxSerializer pdxSerializer =
|
||||
ComposablePdxSerializer.compose(this.mockPdxSerializerOne, this.mockPdxSerializerTwo);
|
||||
|
||||
assertThat(pdxSerializer).isInstanceOf(ComposablePdxSerializer.class);
|
||||
assertThat((ComposablePdxSerializer) pdxSerializer)
|
||||
.contains(this.mockPdxSerializerOne, this.mockPdxSerializerTwo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeArrayWithOnePdxSerializer() {
|
||||
assertThat(ComposablePdxSerializer.compose(this.mockPdxSerializerOne)).isSameAs(this.mockPdxSerializerOne);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeArrayWithNoPdxSerializers() {
|
||||
assertThat(ComposablePdxSerializer.compose()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeIterableWithTwoPdxSerializers() {
|
||||
|
||||
PdxSerializer pdxSerializer =
|
||||
ComposablePdxSerializer.compose(Arrays.asList(this.mockPdxSerializerOne, this.mockPdxSerializerTwo));
|
||||
|
||||
assertThat(pdxSerializer).isInstanceOf(ComposablePdxSerializer.class);
|
||||
assertThat((ComposablePdxSerializer) pdxSerializer)
|
||||
.contains(this.mockPdxSerializerOne, this.mockPdxSerializerTwo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeIterableWithOnePdxSerializer() {
|
||||
assertThat(ComposablePdxSerializer.compose(Collections.singleton(this.mockPdxSerializerTwo)))
|
||||
.isSameAs(this.mockPdxSerializerTwo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeIterableWithNoPdxSerializers() {
|
||||
assertThat(ComposablePdxSerializer.compose(Collections.emptyList())).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDataSerializesObjectWithFirstPdxSerializer() {
|
||||
|
||||
when(this.mockPdxSerializerOne.toData(any(), any(PdxWriter.class))).thenReturn(true);
|
||||
|
||||
PdxSerializer pdxSerializer =
|
||||
ComposablePdxSerializer.compose(this.mockPdxSerializerOne, this.mockPdxSerializerTwo);
|
||||
|
||||
assertThat(pdxSerializer).isNotNull();
|
||||
assertThat(pdxSerializer.toData("test", this.mockPdxWriter)).isTrue();
|
||||
|
||||
verify(this.mockPdxSerializerOne, times(1))
|
||||
.toData(eq("test"), eq(this.mockPdxWriter));
|
||||
|
||||
verify(this.mockPdxSerializerTwo, never()).toData(any(), any(PdxWriter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDataSerializesObjectWithSecondPdxSerializer() {
|
||||
|
||||
when(this.mockPdxSerializerOne.toData(any(), any(PdxWriter.class))).thenReturn(false);
|
||||
when(this.mockPdxSerializerTwo.toData(any(), any(PdxWriter.class))).thenReturn(true);
|
||||
|
||||
PdxSerializer pdxSerializer =
|
||||
ComposablePdxSerializer.compose(this.mockPdxSerializerOne, this.mockPdxSerializerTwo);
|
||||
|
||||
assertThat(pdxSerializer).isNotNull();
|
||||
assertThat(pdxSerializer.toData("test", this.mockPdxWriter)).isTrue();
|
||||
|
||||
verify(this.mockPdxSerializerOne, times(1))
|
||||
.toData(eq("test"), eq(this.mockPdxWriter));
|
||||
|
||||
verify(this.mockPdxSerializerTwo, times(1))
|
||||
.toData(eq("test"), eq(this.mockPdxWriter));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDataCannotSerializeObject() {
|
||||
|
||||
when(this.mockPdxSerializerOne.toData(any(), any(PdxWriter.class))).thenReturn(false);
|
||||
when(this.mockPdxSerializerTwo.toData(any(), any(PdxWriter.class))).thenReturn(false);
|
||||
|
||||
PdxSerializer pdxSerializer =
|
||||
ComposablePdxSerializer.compose(this.mockPdxSerializerOne, this.mockPdxSerializerTwo);
|
||||
|
||||
assertThat(pdxSerializer).isNotNull();
|
||||
assertThat(pdxSerializer.toData("test", this.mockPdxWriter)).isFalse();
|
||||
|
||||
verify(this.mockPdxSerializerOne, times(1))
|
||||
.toData(eq("test"), eq(this.mockPdxWriter));
|
||||
|
||||
verify(this.mockPdxSerializerTwo, times(1))
|
||||
.toData(eq("test"), eq(this.mockPdxWriter));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromDataDeserializesObjectWithFirstPdxSerializer() {
|
||||
|
||||
when(this.mockPdxSerializerOne.fromData(any(Class.class), any(PdxReader.class))).thenReturn("test");
|
||||
|
||||
PdxSerializer pdxSerializer =
|
||||
ComposablePdxSerializer.compose(this.mockPdxSerializerOne, this.mockPdxSerializerTwo);
|
||||
|
||||
assertThat(pdxSerializer).isNotNull();
|
||||
assertThat(pdxSerializer.fromData(Object.class, this.mockPdxReader)).isEqualTo("test");
|
||||
|
||||
verify(this.mockPdxSerializerOne, times(1))
|
||||
.fromData(eq(Object.class), eq(this.mockPdxReader));
|
||||
|
||||
verify(this.mockPdxSerializerTwo, never()).fromData(any(Class.class), any(PdxReader.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromDataDeserializesObjectWithSecondPdxSerializer() {
|
||||
|
||||
when(this.mockPdxSerializerOne.fromData(any(Class.class), any(PdxReader.class))).thenReturn(null);
|
||||
when(this.mockPdxSerializerTwo.fromData(any(Class.class), any(PdxReader.class))).thenReturn("two");
|
||||
|
||||
PdxSerializer pdxSerializer =
|
||||
ComposablePdxSerializer.compose(this.mockPdxSerializerOne, this.mockPdxSerializerTwo);
|
||||
|
||||
assertThat(pdxSerializer).isNotNull();
|
||||
assertThat(pdxSerializer.fromData(Object.class, this.mockPdxReader)).isEqualTo("two");
|
||||
|
||||
verify(this.mockPdxSerializerOne, times(1))
|
||||
.fromData(eq(Object.class), eq(this.mockPdxReader));
|
||||
|
||||
verify(this.mockPdxSerializerTwo, times(1))
|
||||
.fromData(eq(Object.class), eq(this.mockPdxReader));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromDataCannotDeserializeObject() {
|
||||
|
||||
when(this.mockPdxSerializerOne.fromData(any(Class.class), any(PdxReader.class))).thenReturn(null);
|
||||
when(this.mockPdxSerializerTwo.fromData(any(Class.class), any(PdxReader.class))).thenReturn(null);
|
||||
|
||||
PdxSerializer pdxSerializer =
|
||||
ComposablePdxSerializer.compose(this.mockPdxSerializerOne, this.mockPdxSerializerTwo);
|
||||
|
||||
assertThat(pdxSerializer).isNotNull();
|
||||
assertThat(pdxSerializer.fromData(Object.class, this.mockPdxReader)).isNull();
|
||||
|
||||
verify(this.mockPdxSerializerOne, times(1))
|
||||
.fromData(eq(Object.class), eq(this.mockPdxReader));
|
||||
|
||||
verify(this.mockPdxSerializerTwo, times(1))
|
||||
.fromData(eq(Object.class), eq(this.mockPdxReader));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.pdx.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.apache.geode.pdx.PdxReader;
|
||||
import org.apache.geode.pdx.PdxWriter;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.gemfire.serialization.SessionSerializer;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PdxSerializerSessionSerializerAdapter}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.pdx.PdxReader
|
||||
* @see org.apache.geode.pdx.PdxWriter
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.serialization.pdx.support.PdxSerializerSessionSerializerAdapter
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PdxSerializerSessionSerializerAdapterTests {
|
||||
|
||||
@Mock
|
||||
private PdxReader mockPdxReader;
|
||||
|
||||
@Mock
|
||||
private PdxWriter mockPdxWriter;
|
||||
|
||||
@Mock
|
||||
private Session mockSession;
|
||||
|
||||
@Mock
|
||||
private SessionSerializer<Session, PdxReader, PdxWriter> mockSessionSerializer;
|
||||
|
||||
@Test
|
||||
public void constructPdxSerializerSessionSerializerAdapterWithSessionSerializer() {
|
||||
|
||||
PdxSerializerSessionSerializerAdapter<Session> sessionSerializerAdapter =
|
||||
new PdxSerializerSessionSerializerAdapter<>(this.mockSessionSerializer);
|
||||
|
||||
assertThat(sessionSerializerAdapter).isNotNull();
|
||||
assertThat(sessionSerializerAdapter.getSessionSerializer()).isSameAs(this.mockSessionSerializer);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructPdxSerializerSessionSerializerAdapterWithNull() {
|
||||
|
||||
try {
|
||||
new PdxSerializerSessionSerializerAdapter<>(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("SessionSerializer is required");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeSessionCallsSessionSerializerSerialize() {
|
||||
|
||||
PdxSerializerSessionSerializerAdapter<Session> sessionSerializerAdapter =
|
||||
new PdxSerializerSessionSerializerAdapter<>(this.mockSessionSerializer);
|
||||
|
||||
sessionSerializerAdapter.serialize(this.mockSession, this.mockPdxWriter);
|
||||
|
||||
verify(this.mockSessionSerializer, times(1))
|
||||
.serialize(eq(this.mockSession), eq(this.mockPdxWriter));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeSessionCallsSessionSerializerDeserialize() {
|
||||
|
||||
when(this.mockSessionSerializer.deserialize(any(PdxReader.class))).thenReturn(this.mockSession);
|
||||
|
||||
PdxSerializerSessionSerializerAdapter<Session> sessionSerializerAdapter =
|
||||
new PdxSerializerSessionSerializerAdapter<>(this.mockSessionSerializer);
|
||||
|
||||
assertThat(sessionSerializerAdapter.deserialize(this.mockPdxReader)).isEqualTo(this.mockSession);
|
||||
|
||||
verify(this.mockSessionSerializer, times(1)).deserialize(eq(this.mockPdxReader));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDataSerializesSessionWithSessionSerializer() {
|
||||
|
||||
PdxSerializerSessionSerializerAdapter<Session> sessionSerializerAdapter =
|
||||
new PdxSerializerSessionSerializerAdapter<>(this.mockSessionSerializer);
|
||||
|
||||
sessionSerializerAdapter.toData(this.mockSession, this.mockPdxWriter);
|
||||
|
||||
verify(this.mockSessionSerializer, times(1))
|
||||
.serialize(eq(this.mockSession), eq(this.mockPdxWriter));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromDataDeserializesSessionWithSessionSerializer() {
|
||||
|
||||
when(this.mockSessionSerializer.deserialize(any(PdxReader.class))).thenReturn(this.mockSession);
|
||||
|
||||
PdxSerializerSessionSerializerAdapter<Session> sessionSerializerAdapter =
|
||||
new PdxSerializerSessionSerializerAdapter<>(this.mockSessionSerializer);
|
||||
|
||||
assertThat(sessionSerializerAdapter.fromData(Session.class, this.mockPdxReader)).isEqualTo(this.mockSession);
|
||||
|
||||
verify(this.mockSessionSerializer, times(1)).deserialize(eq(this.mockPdxReader));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user