Additional Checkstyle Fixes
Issue gh-393
This commit is contained in:
@@ -48,8 +48,8 @@ import org.springframework.session.events.AbstractSessionEvent;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* AbstractGemFireIntegrationTests is an abstract base class encapsulating common operations for writing
|
||||
* Spring Session GemFire integration tests.
|
||||
* AbstractGemFireIntegrationTests is an abstract base class encapsulating common
|
||||
* operations for writing Spring Session GemFire integration tests.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
@@ -64,24 +64,25 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @see com.gemstone.gemfire.cache.server.CacheServer
|
||||
*/
|
||||
public class AbstractGemFireIntegrationTests {
|
||||
public static final String GEMFIRE_LOG_LEVEL = System.getProperty(
|
||||
"spring.session.data.gemfire.log-level", "warning");
|
||||
public static final String GEMFIRE_LOG_LEVEL = System
|
||||
.getProperty("spring.session.data.gemfire.log-level", "warning");
|
||||
|
||||
protected static final boolean DEFAULT_ENABLE_QUERY_DEBUGGING = false;
|
||||
protected static final boolean GEMFIRE_QUERY_DEBUG = Boolean.getBoolean("spring.session.data.gemfire.query.debug");
|
||||
protected static final boolean GEMFIRE_QUERY_DEBUG = Boolean
|
||||
.getBoolean("spring.session.data.gemfire.query.debug");
|
||||
|
||||
protected static final int DEFAULT_GEMFIRE_SERVER_PORT = CacheServer.DEFAULT_PORT;
|
||||
|
||||
protected static final long DEFAULT_WAIT_DURATION = TimeUnit.SECONDS.toMillis(20);
|
||||
protected static final long DEFAULT_WAIT_INTERVAL = 500L;
|
||||
|
||||
protected static final File WORKING_DIRECTORY = new File(System.getProperty("user.dir"));
|
||||
protected static final File WORKING_DIRECTORY = new File(
|
||||
System.getProperty("user.dir"));
|
||||
|
||||
protected static final String DEFAULT_PROCESS_CONTROL_FILENAME = "process.ctl";
|
||||
|
||||
protected static final String GEMFIRE_LOG_FILE_NAME = System.getProperty(
|
||||
"spring.session.data.gemfire.log-file", "server.log");
|
||||
|
||||
protected static final String GEMFIRE_LOG_FILE_NAME = System
|
||||
.getProperty("spring.session.data.gemfire.log-file", "server.log");
|
||||
|
||||
@Autowired
|
||||
protected Cache gemfireCache;
|
||||
@@ -91,15 +92,17 @@ public class AbstractGemFireIntegrationTests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
System.setProperty("gemfire.Query.VERBOSE", String.valueOf(isQueryDebuggingEnabled()));
|
||||
System.setProperty("gemfire.Query.VERBOSE",
|
||||
String.valueOf(isQueryDebuggingEnabled()));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static File createDirectory(String pathname) {
|
||||
File directory = new File(WORKING_DIRECTORY, pathname);
|
||||
|
||||
assertThat(directory.isDirectory() || directory.mkdirs()).as(
|
||||
String.format("Failed to create directory (%1$s)", directory)).isTrue();
|
||||
assertThat(directory.isDirectory() || directory.mkdirs())
|
||||
.as(String.format("Failed to create directory (%1$s)", directory))
|
||||
.isTrue();
|
||||
|
||||
directory.deleteOnExit();
|
||||
|
||||
@@ -107,7 +110,8 @@ public class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static List<String> createJavaProcessCommandLine(Class<?> type, String... args) {
|
||||
protected static List<String> createJavaProcessCommandLine(Class<?> type,
|
||||
String... args) {
|
||||
List<String> commandLine = new ArrayList<String>();
|
||||
|
||||
String javaHome = System.getProperty("java.home");
|
||||
@@ -118,7 +122,8 @@ public class AbstractGemFireIntegrationTests {
|
||||
commandLine.add("-ea");
|
||||
commandLine.add(String.format("-Dgemfire.log-file=%1$s", GEMFIRE_LOG_FILE_NAME));
|
||||
commandLine.add(String.format("-Dgemfire.log-level=%1$s", GEMFIRE_LOG_LEVEL));
|
||||
commandLine.add(String.format("-Dgemfire.Query.VERBOSE=%1$s", GEMFIRE_QUERY_DEBUG));
|
||||
commandLine
|
||||
.add(String.format("-Dgemfire.Query.VERBOSE=%1$s", GEMFIRE_QUERY_DEBUG));
|
||||
commandLine.addAll(extractJvmArguments(args));
|
||||
commandLine.add("-classpath");
|
||||
commandLine.add(System.getProperty("java.class.path"));
|
||||
@@ -157,11 +162,10 @@ public class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static Process run(Class<?> type, File directory, String... args) throws IOException {
|
||||
return new ProcessBuilder()
|
||||
.command(createJavaProcessCommandLine(type, args))
|
||||
.directory(directory)
|
||||
.start();
|
||||
protected static Process run(Class<?> type, File directory, String... args)
|
||||
throws IOException {
|
||||
return new ProcessBuilder().command(createJavaProcessCommandLine(type, args))
|
||||
.directory(directory).start();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -170,8 +174,10 @@ public class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static boolean waitForCacheServerToStart(CacheServer cacheServer, long duration) {
|
||||
return waitForCacheServerToStart(cacheServer.getBindAddress(), cacheServer.getPort(), duration);
|
||||
protected static boolean waitForCacheServerToStart(CacheServer cacheServer,
|
||||
long duration) {
|
||||
return waitForCacheServerToStart(cacheServer.getBindAddress(),
|
||||
cacheServer.getPort(), duration);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -180,7 +186,8 @@ public class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static boolean waitForCacheServerToStart(final String host, final int port, long duration) {
|
||||
protected static boolean waitForCacheServerToStart(final String host, final int port,
|
||||
long duration) {
|
||||
return waitOnCondition(new Condition() {
|
||||
AtomicBoolean connected = new AtomicBoolean(false);
|
||||
|
||||
@@ -204,7 +211,8 @@ public class AbstractGemFireIntegrationTests {
|
||||
}, duration);
|
||||
}
|
||||
|
||||
// NOTE this method would not be necessary except Spring Sessions' build does not fork the test JVM
|
||||
// NOTE this method would not be necessary except Spring Sessions' build does not fork
|
||||
// the test JVM
|
||||
// for every test class.
|
||||
/* (non-Javadoc) */
|
||||
protected static boolean waitForClientCacheToClose() {
|
||||
@@ -239,7 +247,8 @@ public class AbstractGemFireIntegrationTests {
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("all")
|
||||
protected static boolean waitForProcessToStart(Process process, File directory, long duration) {
|
||||
protected static boolean waitForProcessToStart(Process process, File directory,
|
||||
long duration) {
|
||||
final File processControl = new File(directory, DEFAULT_PROCESS_CONTROL_FILENAME);
|
||||
|
||||
waitOnCondition(new Condition() {
|
||||
@@ -257,7 +266,8 @@ public class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static int waitForProcessToStop(Process process, File directory, long duration) {
|
||||
protected static int waitForProcessToStop(Process process, File directory,
|
||||
long duration) {
|
||||
final long timeout = (System.currentTimeMillis() + duration);
|
||||
|
||||
try {
|
||||
@@ -312,24 +322,30 @@ public class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void assertRegion(Region<?, ?> actualRegion, String expectedName, DataPolicy expectedDataPolicy) {
|
||||
protected void assertRegion(Region<?, ?> actualRegion, String expectedName,
|
||||
DataPolicy expectedDataPolicy) {
|
||||
assertThat(actualRegion).isNotNull();
|
||||
assertThat(actualRegion.getName()).isEqualTo(expectedName);
|
||||
assertThat(actualRegion.getFullPath()).isEqualTo(GemFireUtils.toRegionPath(expectedName));
|
||||
assertThat(actualRegion.getFullPath())
|
||||
.isEqualTo(GemFireUtils.toRegionPath(expectedName));
|
||||
assertThat(actualRegion.getAttributes()).isNotNull();
|
||||
assertThat(actualRegion.getAttributes().getDataPolicy()).isEqualTo(expectedDataPolicy);
|
||||
assertThat(actualRegion.getAttributes().getDataPolicy())
|
||||
.isEqualTo(expectedDataPolicy);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void assertIndex(Index index, String expectedExpression, String expectedFromClause) {
|
||||
protected void assertIndex(Index index, String expectedExpression,
|
||||
String expectedFromClause) {
|
||||
assertThat(index).isNotNull();
|
||||
assertThat(index.getIndexedExpression()).isEqualTo(expectedExpression);
|
||||
assertThat(index.getFromClause()).isEqualTo(expectedFromClause);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void assertEntryIdleTimeout(Region<?, ?> region, ExpirationAction expectedAction, int expectedTimeout) {
|
||||
assertEntryIdleTimeout(region.getAttributes().getEntryIdleTimeout(), expectedAction, expectedTimeout);
|
||||
protected void assertEntryIdleTimeout(Region<?, ?> region,
|
||||
ExpirationAction expectedAction, int expectedTimeout) {
|
||||
assertEntryIdleTimeout(region.getAttributes().getEntryIdleTimeout(),
|
||||
expectedAction, expectedTimeout);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -404,13 +420,14 @@ public class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* The SessionEventListener class is a Spring {@link ApplicationListener} listening for Spring HTTP Session
|
||||
* application events.
|
||||
* The SessionEventListener class is a Spring {@link ApplicationListener} listening
|
||||
* for Spring HTTP Session application events.
|
||||
*
|
||||
* @see org.springframework.context.ApplicationListener
|
||||
* @see org.springframework.session.events.AbstractSessionEvent
|
||||
*/
|
||||
public static class SessionEventListener implements ApplicationListener<AbstractSessionEvent> {
|
||||
public static class SessionEventListener
|
||||
implements ApplicationListener<AbstractSessionEvent> {
|
||||
|
||||
private volatile AbstractSessionEvent sessionEvent;
|
||||
|
||||
@@ -440,7 +457,8 @@ public class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* The Condition interface defines a logical condition that must be satisfied before it is safe to proceed.
|
||||
* The Condition interface defines a logical condition that must be satisfied before
|
||||
* it is safe to proceed.
|
||||
*/
|
||||
protected interface Condition {
|
||||
boolean evaluate();
|
||||
|
||||
@@ -60,7 +60,8 @@ public class HttpSessionGemFireIndexingITests extends AbstractGemFireIntegration
|
||||
sessionRepository.save(session);
|
||||
|
||||
// tag::findbyindexname-get[]
|
||||
Map<String, ExpiringSession> idToSessions = sessionRepository.findByIndexNameAndIndexValue(indexName, username);
|
||||
Map<String, ExpiringSession> idToSessions = sessionRepository
|
||||
.findByIndexNameAndIndexValue(indexName, username);
|
||||
// end::findbyindexname-get[]
|
||||
|
||||
assertThat(idToSessions.keySet()).containsOnly(session.getId());
|
||||
@@ -78,12 +79,15 @@ public class HttpSessionGemFireIndexingITests extends AbstractGemFireIntegration
|
||||
Authentication authentication = context.getAuthentication();
|
||||
// end::findbyspringsecurityindexname-context[]
|
||||
|
||||
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context);
|
||||
session.setAttribute(
|
||||
HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
|
||||
context);
|
||||
sessionRepository.save(session);
|
||||
|
||||
// tag::findbyspringsecurityindexname-get[]
|
||||
String indexName = FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME;
|
||||
Map<String, ExpiringSession> idToSessions = sessionRepository.findByIndexNameAndIndexValue(indexName, authentication.getName());
|
||||
Map<String, ExpiringSession> idToSessions = sessionRepository
|
||||
.findByIndexNameAndIndexValue(indexName, authentication.getName());
|
||||
// end::findbyspringsecurityindexname-get[]
|
||||
|
||||
assertThat(idToSessions.keySet()).containsOnly(session.getId());
|
||||
|
||||
@@ -39,7 +39,8 @@ public class GemFireHttpSessionConfig {
|
||||
|
||||
gemfireProperties.setProperty("name", GemFireHttpSessionConfig.class.getName());
|
||||
gemfireProperties.setProperty("mcast-port", "0");
|
||||
gemfireProperties.setProperty("log-level", AbstractGemFireIntegrationTests.GEMFIRE_LOG_LEVEL);
|
||||
gemfireProperties.setProperty("log-level",
|
||||
AbstractGemFireIntegrationTests.GEMFIRE_LOG_LEVEL);
|
||||
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = GemFireHttpSessionConfig.class)
|
||||
public class HttpSessionGemFireIndexingCustomITests extends AbstractGemFireIntegrationTests {
|
||||
public class HttpSessionGemFireIndexingCustomITests
|
||||
extends AbstractGemFireIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void findByIndexName() {
|
||||
@@ -49,7 +50,8 @@ public class HttpSessionGemFireIndexingCustomITests extends AbstractGemFireInteg
|
||||
sessionRepository.save(session);
|
||||
|
||||
// tag::findbyindexname-get[]
|
||||
Map<String, ExpiringSession> idToSessions = sessionRepository.findByIndexNameAndIndexValue(indexName, attrValue);
|
||||
Map<String, ExpiringSession> idToSessions = sessionRepository
|
||||
.findByIndexNameAndIndexValue(indexName, attrValue);
|
||||
// end::findbyindexname-get[]
|
||||
|
||||
assertThat(idToSessions.keySet()).containsOnly(session.getId());
|
||||
|
||||
@@ -41,7 +41,8 @@ public class FindByIndexNameSessionRepositoryTests {
|
||||
public void setUsername() {
|
||||
// tag::set-username[]
|
||||
String username = "username";
|
||||
this.session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
|
||||
this.session.setAttribute(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
|
||||
// end::set-username[]
|
||||
}
|
||||
|
||||
@@ -50,8 +51,10 @@ public class FindByIndexNameSessionRepositoryTests {
|
||||
public void findByUsername() {
|
||||
// tag::findby-username[]
|
||||
String username = "username";
|
||||
Map<String, Session> sessionIdToSession =
|
||||
this.sessionRepository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
|
||||
Map<String, Session> sessionIdToSession = this.sessionRepository
|
||||
.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
username);
|
||||
// end::findby-username[]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ public class HttpSessionConfigurationNoOpConfigureRedisActionXmlTests {
|
||||
assertThat(this.filter).isNotNull();
|
||||
}
|
||||
|
||||
|
||||
static RedisConnectionFactory connectionFactory() {
|
||||
return mock(RedisConnectionFactory.class);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,6 @@ public class IndexDocTests {
|
||||
}
|
||||
// end::repository-demo[]
|
||||
|
||||
|
||||
@Test
|
||||
public void expireRepositoryDemo() {
|
||||
ExpiringRepositoryDemo<ExpiringSession> demo = new ExpiringRepositoryDemo<ExpiringSession>();
|
||||
@@ -102,8 +101,8 @@ public class IndexDocTests {
|
||||
public void newRedisOperationsSessionRepository() {
|
||||
// tag::new-redisoperationssessionrepository[]
|
||||
JedisConnectionFactory factory = new JedisConnectionFactory();
|
||||
SessionRepository<? extends ExpiringSession> repository =
|
||||
new RedisOperationsSessionRepository(factory);
|
||||
SessionRepository<? extends ExpiringSession> repository = new RedisOperationsSessionRepository(
|
||||
factory);
|
||||
// end::new-redisoperationssessionrepository[]
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,9 @@ public abstract class AbstractHttpSessionListenerTests {
|
||||
public void springSessionDestroyedTranslatedToSpringSecurityDestroyed() {
|
||||
Session session = new MapSession();
|
||||
|
||||
this.publisher.publishEvent(new org.springframework.session.events.SessionDestroyedEvent(this, session));
|
||||
this.publisher.publishEvent(
|
||||
new org.springframework.session.events.SessionDestroyedEvent(this,
|
||||
session));
|
||||
|
||||
assertThat(this.listener.getEvent().getId()).isEqualTo(session.getId());
|
||||
}
|
||||
@@ -64,12 +66,16 @@ public abstract class AbstractHttpSessionListenerTests {
|
||||
return factory;
|
||||
}
|
||||
|
||||
static class SecuritySessionDestroyedListener implements ApplicationListener<SessionDestroyedEvent> {
|
||||
static class SecuritySessionDestroyedListener
|
||||
implements ApplicationListener<SessionDestroyedEvent> {
|
||||
|
||||
private SessionDestroyedEvent event;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.
|
||||
* springframework.context.ApplicationEvent)
|
||||
*/
|
||||
public void onApplicationEvent(SessionDestroyedEvent event) {
|
||||
this.event = event;
|
||||
|
||||
@@ -30,12 +30,10 @@ import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
@EnableWebSocketMessageBroker
|
||||
public class WebSocketConfig
|
||||
extends AbstractWebSocketMessageBrokerConfigurer {
|
||||
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
|
||||
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
registry.addEndpoint("/messages")
|
||||
.withSockJS();
|
||||
registry.addEndpoint("/messages").withSockJS();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,8 +18,8 @@ package sample.config;
|
||||
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
|
||||
|
||||
// tag::class[]
|
||||
@EnableRedisHttpSession // <1>
|
||||
public class HttpSessionConfig { }
|
||||
public class HttpSessionConfig {
|
||||
}
|
||||
// end::class[]
|
||||
|
||||
@@ -29,8 +29,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER");
|
||||
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.springframework.session.data.redis.config.annotation.web.http.EnableR
|
||||
import org.springframework.session.web.http.CookieSerializer;
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
|
||||
|
||||
@EnableRedisHttpSession
|
||||
public class Config {
|
||||
|
||||
|
||||
@@ -19,8 +19,7 @@ package sample;
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
||||
|
||||
// tag::class[]
|
||||
public class Initializer
|
||||
extends AbstractHttpSessionApplicationInitializer { // <1>
|
||||
public class Initializer extends AbstractHttpSessionApplicationInitializer { // <1>
|
||||
|
||||
public Initializer() {
|
||||
super(Config.class); // <2>
|
||||
|
||||
@@ -29,7 +29,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||
public class SessionServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
String attributeName = req.getParameter("attributeName");
|
||||
String attributeValue = req.getParameter("attributeValue");
|
||||
req.getSession().setAttribute(attributeName, attributeValue);
|
||||
|
||||
@@ -33,7 +33,9 @@ import org.springframework.context.annotation.Configuration;
|
||||
public class GeoConfig {
|
||||
|
||||
@Bean
|
||||
public DatabaseReader geoDatabaseReader(@Value("classpath:GeoLite2-City.mmdb") InputStream geoInputStream) throws Exception {
|
||||
public DatabaseReader geoDatabaseReader(
|
||||
@Value("classpath:GeoLite2-City.mmdb") InputStream geoInputStream)
|
||||
throws Exception {
|
||||
return new DatabaseReader.Builder(geoInputStream).build();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,5 +25,6 @@ import org.springframework.session.data.redis.config.annotation.web.http.EnableR
|
||||
*/
|
||||
// tag::class[]
|
||||
@EnableRedisHttpSession // <1>
|
||||
public class HttpSessionConfig { }
|
||||
public class HttpSessionConfig {
|
||||
}
|
||||
// end::class[]
|
||||
|
||||
@@ -31,24 +31,14 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
// tag::config[]
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.formLogin()
|
||||
.loginPage("/login")
|
||||
.permitAll()
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.antMatchers("/resources/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.logout()
|
||||
.permitAll();
|
||||
http.formLogin().loginPage("/login").permitAll().and().authorizeRequests()
|
||||
.antMatchers("/resources/**").permitAll().anyRequest().authenticated()
|
||||
.and().logout().permitAll();
|
||||
}
|
||||
// end::config[]
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER");
|
||||
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,17 +43,21 @@ public class IndexController {
|
||||
|
||||
@RequestMapping("/")
|
||||
public String index(Principal principal, Model model) {
|
||||
Collection<? extends ExpiringSession> usersSessions =
|
||||
this.sessions.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
principal.getName()).values();
|
||||
Collection<? extends ExpiringSession> usersSessions = this.sessions
|
||||
.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
principal.getName())
|
||||
.values();
|
||||
model.addAttribute("sessions", usersSessions);
|
||||
return "index";
|
||||
}
|
||||
// end::findbyusername[]
|
||||
|
||||
@RequestMapping(value = "/sessions/{sessionIdToDelete}", method = RequestMethod.DELETE)
|
||||
public String removeSession(Principal principal, @PathVariable String sessionIdToDelete) {
|
||||
Set<String> usersSessionIds = this.sessions.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
public String removeSession(Principal principal,
|
||||
@PathVariable String sessionIdToDelete) {
|
||||
Set<String> usersSessionIds = this.sessions.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
principal.getName()).keySet();
|
||||
if (usersSessionIds.contains(sessionIdToDelete)) {
|
||||
this.sessions.delete(sessionIdToDelete);
|
||||
|
||||
@@ -35,10 +35,10 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
* Inserts the session details into the session for every request. Some users
|
||||
* may prefer to insert session details only after authentication. This is fine,
|
||||
* but it may be valuable to the most up to date information so that if someone
|
||||
* stole the user's session id it can be observed.
|
||||
* Inserts the session details into the session for every request. Some users may prefer
|
||||
* to insert session details only after authentication. This is fine, but it may be
|
||||
* valuable to the most up to date information so that if someone stole the user's session
|
||||
* id it can be observed.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
@@ -57,8 +57,8 @@ public class SessionDetailsFilter extends OncePerRequestFilter {
|
||||
}
|
||||
|
||||
// tag::dofilterinternal[]
|
||||
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
chain.doFilter(request, response);
|
||||
|
||||
HttpSession session = request.getSession(false);
|
||||
@@ -109,4 +109,3 @@ public class SessionDetailsFilter extends OncePerRequestFilter {
|
||||
}
|
||||
}
|
||||
// end::class[]
|
||||
|
||||
|
||||
@@ -48,16 +48,19 @@ public class SessionDetailsFilterTests {
|
||||
|
||||
@Test
|
||||
public void getGeoLocationHanldesInvalidIp() {
|
||||
assertThat(this.filter.getGeoLocation("a")).isEqualTo(SessionDetailsFilter.UNKNOWN);
|
||||
assertThat(this.filter.getGeoLocation("a"))
|
||||
.isEqualTo(SessionDetailsFilter.UNKNOWN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getGeoLocationNullCity() {
|
||||
assertThat(this.filter.getGeoLocation("22.231.113.64")).isEqualTo("United States");
|
||||
assertThat(this.filter.getGeoLocation("22.231.113.64"))
|
||||
.isEqualTo("United States");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getGeoLocationBoth() {
|
||||
assertThat(this.filter.getGeoLocation("184.154.83.119")).isEqualTo("Chicago, United States");
|
||||
assertThat(this.filter.getGeoLocation("184.154.83.119"))
|
||||
.isEqualTo("Chicago, United States");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ public class Config {
|
||||
netConfig.setPort(SocketUtils.findAvailableTcpPort());
|
||||
System.out.println("Hazelcast port #: " + netConfig.getPort());
|
||||
cfg.setNetworkConfig(netConfig);
|
||||
SerializerConfig serializer = new SerializerConfig().setTypeClass(
|
||||
Object.class).setImplementation(new ObjectStreamSerializer());
|
||||
SerializerConfig serializer = new SerializerConfig().setTypeClass(Object.class)
|
||||
.setImplementation(new ObjectStreamSerializer());
|
||||
cfg.getSerializationConfig().addSerializerConfig(serializer);
|
||||
|
||||
return Hazelcast.newHazelcastInstance(cfg);
|
||||
|
||||
@@ -27,11 +27,10 @@ import com.hazelcast.nio.ObjectDataOutput;
|
||||
import com.hazelcast.nio.serialization.StreamSerializer;
|
||||
|
||||
/**
|
||||
* A {@link StreamSerializer} that uses Java serialization to persist the
|
||||
* session. This is certainly not the most efficient way to persist sessions,
|
||||
* but the example is intended to demonstrate using minimal dependencies. For
|
||||
* better serialization methods try using <a
|
||||
* href="https://github.com/EsotericSoftware/kryo">Kryo</a>.
|
||||
* A {@link StreamSerializer} that uses Java serialization to persist the session. This is
|
||||
* certainly not the most efficient way to persist sessions, but the example is intended
|
||||
* to demonstrate using minimal dependencies. For better serialization methods try using
|
||||
* <a href="https://github.com/EsotericSoftware/kryo">Kryo</a>.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
@@ -48,8 +47,7 @@ public class ObjectStreamSerializer implements StreamSerializer<Object> {
|
||||
out.flush();
|
||||
}
|
||||
|
||||
public Object read(ObjectDataInput objectDataInput)
|
||||
throws IOException {
|
||||
public Object read(ObjectDataInput objectDataInput) throws IOException {
|
||||
ObjectInputStream in = new ObjectInputStream((InputStream) objectDataInput);
|
||||
try {
|
||||
return in.readObject();
|
||||
|
||||
@@ -28,8 +28,6 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
||||
public class SecurityConfig {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER");
|
||||
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@ package sample;
|
||||
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
||||
|
||||
// tag::class[]
|
||||
public class SecurityInitializer extends
|
||||
AbstractSecurityWebApplicationInitializer {
|
||||
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
|
||||
|
||||
public SecurityInitializer() {
|
||||
super(SecurityConfig.class, Config.class);
|
||||
|
||||
@@ -28,7 +28,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||
public class SessionServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
String attributeName = req.getParameter("attributeName");
|
||||
String attributeValue = req.getParameter("attributeValue");
|
||||
req.getSession().setAttribute(attributeName, attributeValue);
|
||||
|
||||
@@ -53,8 +53,7 @@ public class Initializer implements ServletContextListener {
|
||||
NetworkConfig netConfig = new NetworkConfig();
|
||||
netConfig.setPort(getAvailablePort());
|
||||
cfg.setNetworkConfig(netConfig);
|
||||
SerializerConfig serializer = new SerializerConfig()
|
||||
.setTypeClass(Object.class)
|
||||
SerializerConfig serializer = new SerializerConfig().setTypeClass(Object.class)
|
||||
.setImplementation(new ObjectStreamSerializer());
|
||||
cfg.getSerializationConfig().addSerializerConfig(serializer);
|
||||
MapConfig mc = new MapConfig();
|
||||
@@ -65,10 +64,10 @@ public class Initializer implements ServletContextListener {
|
||||
this.instance = Hazelcast.newHazelcastInstance(cfg);
|
||||
Map<String, ExpiringSession> sessions = this.instance.getMap(sessionMapName);
|
||||
|
||||
SessionRepository<ExpiringSession> sessionRepository =
|
||||
new MapSessionRepository(sessions);
|
||||
SessionRepositoryFilter<ExpiringSession> filter =
|
||||
new SessionRepositoryFilter<ExpiringSession>(sessionRepository);
|
||||
SessionRepository<ExpiringSession> sessionRepository = new MapSessionRepository(
|
||||
sessions);
|
||||
SessionRepositoryFilter<ExpiringSession> filter = new SessionRepositoryFilter<ExpiringSession>(
|
||||
sessionRepository);
|
||||
Dynamic fr = sc.addFilter("springSessionFilter", filter);
|
||||
fr.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
|
||||
}
|
||||
|
||||
@@ -27,11 +27,10 @@ import com.hazelcast.nio.ObjectDataOutput;
|
||||
import com.hazelcast.nio.serialization.StreamSerializer;
|
||||
|
||||
/**
|
||||
* A {@link StreamSerializer} that uses Java serialization to persist the
|
||||
* session. This is certainly not the most efficient way to persist sessions,
|
||||
* but the example is intended to demonstrate using minimal dependencies. For
|
||||
* better serialization methods try using <a
|
||||
* href="https://github.com/EsotericSoftware/kryo">Kryo</a>.
|
||||
* A {@link StreamSerializer} that uses Java serialization to persist the session. This is
|
||||
* certainly not the most efficient way to persist sessions, but the example is intended
|
||||
* to demonstrate using minimal dependencies. For better serialization methods try using
|
||||
* <a href="https://github.com/EsotericSoftware/kryo">Kryo</a>.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
@@ -48,8 +47,7 @@ public class ObjectStreamSerializer implements StreamSerializer<Object> {
|
||||
out.flush();
|
||||
}
|
||||
|
||||
public Object read(ObjectDataInput objectDataInput)
|
||||
throws IOException {
|
||||
public Object read(ObjectDataInput objectDataInput) throws IOException {
|
||||
ObjectInputStream in = new ObjectInputStream((InputStream) objectDataInput);
|
||||
try {
|
||||
return in.readObject();
|
||||
|
||||
@@ -31,7 +31,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||
public class SessionServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
String attributeName = req.getParameter("attributeName");
|
||||
String attributeValue = req.getParameter("attributeValue");
|
||||
req.getSession().setAttribute(attributeName, attributeValue);
|
||||
|
||||
@@ -27,7 +27,8 @@ import org.springframework.context.annotation.ImportResource;
|
||||
public class Application {
|
||||
|
||||
public static void main(final String[] args) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
Application.class);
|
||||
context.registerShutdownHook();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ public class GemFireCacheServerReadyBeanPostProcessor implements BeanPostProcess
|
||||
|
||||
// tag::class[]
|
||||
static {
|
||||
ClientMembership.registerClientMembershipListener(new ClientMembershipListenerAdapter() {
|
||||
ClientMembership
|
||||
.registerClientMembershipListener(new ClientMembershipListenerAdapter() {
|
||||
public void memberJoined(final ClientMembershipEvent event) {
|
||||
if (!event.isClient()) {
|
||||
latch.countDown();
|
||||
@@ -64,17 +65,21 @@ public class GemFireCacheServerReadyBeanPostProcessor implements BeanPostProcess
|
||||
@Resource(name = "applicationProperties")
|
||||
private Properties applicationProperties;
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof PoolFactoryBean || bean instanceof Pool) {
|
||||
String host = getServerHost(DEFAULT_SERVER_HOST);
|
||||
Assert.isTrue(waitForCacheServerToStart(host, this.port), String.format(
|
||||
"GemFire Server failed to start [host: '%1$s', port: %2$d]%n", host, this.port));
|
||||
Assert.isTrue(waitForCacheServerToStart(host, this.port),
|
||||
String.format(
|
||||
"GemFire Server failed to start [host: '%1$s', port: %2$d]%n",
|
||||
host, this.port));
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof PoolFactoryBean || bean instanceof Pool) {
|
||||
try {
|
||||
latch.await(DEFAULT_WAIT_DURATION, TimeUnit.MILLISECONDS);
|
||||
@@ -93,7 +98,8 @@ public class GemFireCacheServerReadyBeanPostProcessor implements BeanPostProcess
|
||||
}
|
||||
|
||||
String getServerHost(String defaultServerHost) {
|
||||
return this.applicationProperties.getProperty("application.gemfire.client-server.host", defaultServerHost);
|
||||
return this.applicationProperties
|
||||
.getProperty("application.gemfire.client-server.host", defaultServerHost);
|
||||
}
|
||||
|
||||
boolean waitForCacheServerToStart(String host, int port) {
|
||||
@@ -109,8 +115,10 @@ public class GemFireCacheServerReadyBeanPostProcessor implements BeanPostProcess
|
||||
Socket socket = null;
|
||||
|
||||
try {
|
||||
// NOTE: this code is not intended to be an atomic, compound action (a possible race condition);
|
||||
// opening another connection (at the expense of using system resources) after connectivity
|
||||
// NOTE: this code is not intended to be an atomic, compound action (a
|
||||
// possible race condition);
|
||||
// opening another connection (at the expense of using system
|
||||
// resources) after connectivity
|
||||
// has already been established is not detrimental in this use case
|
||||
if (!connected.get()) {
|
||||
socket = new Socket(host, port);
|
||||
|
||||
@@ -55,8 +55,8 @@ public class ClientConfig {
|
||||
System.setProperty("gemfire.log-level",
|
||||
System.getProperty("sample.httpsession.gemfire.log-level", "warning"));
|
||||
|
||||
ClientMembership.registerClientMembershipListener(
|
||||
new ClientMembershipListenerAdapter() {
|
||||
ClientMembership
|
||||
.registerClientMembershipListener(new ClientMembershipListenerAdapter() {
|
||||
public void memberJoined(ClientMembershipEvent event) {
|
||||
if (!event.isClient()) {
|
||||
latch.countDown();
|
||||
@@ -77,7 +77,8 @@ public class ClientConfig {
|
||||
|
||||
@Bean(name = GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME)
|
||||
PoolFactoryBean gemfirePool(// <3>
|
||||
@Value("${spring.session.data.gemfire.port:" + ServerConfig.SERVER_PORT + "}") int port) {
|
||||
@Value("${spring.session.data.gemfire.port:" + ServerConfig.SERVER_PORT
|
||||
+ "}") int port) {
|
||||
|
||||
PoolFactoryBean poolFactory = new PoolFactoryBean();
|
||||
|
||||
@@ -91,8 +92,8 @@ public class ClientConfig {
|
||||
poolFactory.setSubscriptionEnabled(true);
|
||||
poolFactory.setThreadLocalConnections(false);
|
||||
|
||||
poolFactory.setServerEndpoints(Collections.singletonList(new ConnectionEndpoint(
|
||||
ServerConfig.SERVER_HOSTNAME, port)));
|
||||
poolFactory.setServerEndpoints(Collections.singletonList(
|
||||
new ConnectionEndpoint(ServerConfig.SERVER_HOSTNAME, port)));
|
||||
|
||||
return poolFactory;
|
||||
}
|
||||
@@ -111,27 +112,29 @@ public class ClientConfig {
|
||||
|
||||
@Bean
|
||||
BeanPostProcessor gemfireCacheServerReadyBeanPostProcessor(// <5>
|
||||
@Value("${spring.session.data.gemfire.port:" + ServerConfig.SERVER_PORT + "}") final int port) {
|
||||
@Value("${spring.session.data.gemfire.port:" + ServerConfig.SERVER_PORT
|
||||
+ "}") final int port) {
|
||||
|
||||
return new BeanPostProcessor() {
|
||||
|
||||
public Object postProcessBeforeInitialization(
|
||||
Object bean, String beanName) throws BeansException {
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof PoolFactoryBean || bean instanceof Pool) {
|
||||
Assert.isTrue(waitForCacheServerToStart(ServerConfig.SERVER_HOSTNAME, port),
|
||||
String.format("GemFire Server failed to start [hostname: %1$s, port: %2$d]",
|
||||
Assert.isTrue(
|
||||
waitForCacheServerToStart(ServerConfig.SERVER_HOSTNAME, port),
|
||||
String.format(
|
||||
"GemFire Server failed to start [hostname: %1$s, port: %2$d]",
|
||||
ServerConfig.SERVER_HOSTNAME, port));
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(
|
||||
Object bean, String beanName) throws BeansException {
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof PoolFactoryBean || bean instanceof Pool) {
|
||||
try {
|
||||
latch.await(DEFAULT_WAIT_DURATION,
|
||||
TimeUnit.MILLISECONDS);
|
||||
latch.await(DEFAULT_WAIT_DURATION, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
@@ -161,8 +164,10 @@ public class ClientConfig {
|
||||
Socket socket = null;
|
||||
|
||||
try {
|
||||
// NOTE: this code is not intended to be an atomic, compound action (a possible race condition);
|
||||
// opening another connection (at the expense of using system resources) after connectivity
|
||||
// NOTE: this code is not intended to be an atomic, compound action (a
|
||||
// possible race condition);
|
||||
// opening another connection (at the expense of using system
|
||||
// resources) after connectivity
|
||||
// has already been established is not detrimental in this use case
|
||||
if (!connected.get()) {
|
||||
socket = new Socket(host, port);
|
||||
|
||||
@@ -19,8 +19,7 @@ package sample;
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
||||
|
||||
// tag::class[]
|
||||
public class Initializer
|
||||
extends AbstractHttpSessionApplicationInitializer { // <1>
|
||||
public class Initializer extends AbstractHttpSessionApplicationInitializer { // <1>
|
||||
|
||||
public Initializer() {
|
||||
super(ClientConfig.class); // <2>
|
||||
|
||||
@@ -84,8 +84,7 @@ public class ServerConfig {
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public static void main(final String[] args) throws IOException { // <5>
|
||||
new AnnotationConfigApplicationContext(ServerConfig.class)
|
||||
.registerShutdownHook();
|
||||
new AnnotationConfigApplicationContext(ServerConfig.class).registerShutdownHook();
|
||||
}
|
||||
}
|
||||
// end::class[]
|
||||
|
||||
@@ -19,8 +19,7 @@ package sample;
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
||||
|
||||
// tag::class[]
|
||||
public class Initializer
|
||||
extends AbstractHttpSessionApplicationInitializer { // <1>
|
||||
public class Initializer extends AbstractHttpSessionApplicationInitializer { // <1>
|
||||
|
||||
public Initializer() {
|
||||
super(Config.class); // <2>
|
||||
|
||||
@@ -15,15 +15,19 @@
|
||||
*/
|
||||
package sample;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
// tag::class[]
|
||||
public class SessionServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
String attributeName = req.getParameter("attributeName");
|
||||
String attributeValue = req.getParameter("attributeValue");
|
||||
req.getSession().setAttribute(attributeName, attributeValue);
|
||||
|
||||
@@ -34,8 +34,7 @@ public class Config {
|
||||
public EmbeddedDatabase dataSource() {
|
||||
return new EmbeddedDatabaseBuilder() // <2>
|
||||
.setType(EmbeddedDatabaseType.H2)
|
||||
.addScript("org/springframework/session/jdbc/schema-h2.sql")
|
||||
.build();
|
||||
.addScript("org/springframework/session/jdbc/schema-h2.sql").build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -18,8 +18,7 @@ package sample;
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
||||
|
||||
// tag::class[]
|
||||
public class Initializer
|
||||
extends AbstractHttpSessionApplicationInitializer { // <1>
|
||||
public class Initializer extends AbstractHttpSessionApplicationInitializer { // <1>
|
||||
|
||||
public Initializer() {
|
||||
super(Config.class); // <2>
|
||||
|
||||
@@ -15,17 +15,21 @@
|
||||
*/
|
||||
package sample;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.annotation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
// tag::class[]
|
||||
@WebServlet("/session")
|
||||
public class SessionServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
String attributeName = req.getParameter("attributeName");
|
||||
String attributeValue = req.getParameter("attributeValue");
|
||||
req.getSession().setAttribute(attributeName, attributeValue);
|
||||
|
||||
@@ -27,7 +27,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||
public class SessionServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
String attributeName = req.getParameter("attributeName");
|
||||
String attributeValue = req.getParameter("attributeValue");
|
||||
req.getSession().setAttribute(attributeName, attributeValue);
|
||||
|
||||
@@ -19,8 +19,7 @@ package sample;
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
||||
|
||||
// tag::class[]
|
||||
public class Initializer
|
||||
extends AbstractHttpSessionApplicationInitializer { // <1>
|
||||
public class Initializer extends AbstractHttpSessionApplicationInitializer { // <1>
|
||||
|
||||
public Initializer() {
|
||||
super(Config.class); // <2>
|
||||
|
||||
@@ -29,7 +29,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||
public class SessionServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
String attributeName = req.getParameter("attributeName");
|
||||
String attributeValue = req.getParameter("attributeValue");
|
||||
req.getSession().setAttribute(attributeName, attributeValue);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,16 +16,15 @@
|
||||
package sample
|
||||
|
||||
import geb.spock.*
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.boot.test.IntegrationTest
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration
|
||||
import org.springframework.boot.test.SpringApplicationContextLoader
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.test.context.web.WebAppConfiguration
|
||||
import pages.*
|
||||
import sample.pages.HomePage
|
||||
import sample.pages.LoginPage
|
||||
import spock.lang.Stepwise
|
||||
import pages.*
|
||||
|
||||
import org.springframework.boot.test.IntegrationTest
|
||||
import org.springframework.boot.test.SpringApplicationContextLoader
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.test.context.web.WebAppConfiguration
|
||||
|
||||
/**
|
||||
* Tests the demo that supports multiple sessions
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
* 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.
|
||||
* 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 sample;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,8 +17,8 @@ package sample.config;
|
||||
|
||||
import org.springframework.session.data.mongo.config.annotation.web.http.EnableMongoHttpSession;
|
||||
|
||||
|
||||
// tag::class[]
|
||||
@EnableMongoHttpSession // <1>
|
||||
public class HttpSessionConfig { }
|
||||
public class HttpSessionConfig {
|
||||
}
|
||||
// end::class[]
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
* 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.
|
||||
* 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 sample.config;
|
||||
|
||||
@@ -28,8 +28,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER");
|
||||
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
* 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.
|
||||
* 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 sample.mvc;
|
||||
|
||||
|
||||
@@ -43,9 +43,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = {HttpSessionConfig.class, SecurityConfig.class, MvcConfig.class})
|
||||
@ContextConfiguration(classes = { HttpSessionConfig.class, SecurityConfig.class,
|
||||
MvcConfig.class })
|
||||
@WebAppConfiguration
|
||||
public class RestMockMvcTests {
|
||||
|
||||
@@ -59,25 +59,20 @@ public class RestMockMvcTests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.mvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.alwaysDo(print())
|
||||
.addFilters(this.sessionRepositoryFilter)
|
||||
.apply(springSecurity())
|
||||
.build();
|
||||
this.mvc = MockMvcBuilders.webAppContextSetup(this.context).alwaysDo(print())
|
||||
.addFilters(this.sessionRepositoryFilter).apply(springSecurity()).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noSessionOnNoCredentials() throws Exception {
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(header().doesNotExist("x-auth-token"))
|
||||
this.mvc.perform(get("/")).andExpect(header().doesNotExist("x-auth-token"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@WithMockUser
|
||||
@Test
|
||||
public void autheticatedAnnotation() throws Exception {
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(content().string("{\"username\":\"user\"}"));
|
||||
this.mvc.perform(get("/")).andExpect(content().string("{\"username\":\"user\"}"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.springframework.security.web.context.AbstractSecurityWebApplicationIn
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class SecurityInitializer extends
|
||||
AbstractSecurityWebApplicationInitializer {
|
||||
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
|
||||
|
||||
}
|
||||
|
||||
@@ -28,8 +28,6 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
||||
public class SecurityConfig {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER");
|
||||
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@ package sample;
|
||||
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
||||
|
||||
// tag::class[]
|
||||
public class SecurityInitializer extends
|
||||
AbstractSecurityWebApplicationInitializer {
|
||||
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
|
||||
|
||||
public SecurityInitializer() {
|
||||
super(SecurityConfig.class, Config.class);
|
||||
|
||||
@@ -28,7 +28,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||
public class SessionServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
String attributeName = req.getParameter("attributeName");
|
||||
String attributeValue = req.getParameter("attributeValue");
|
||||
req.getSession().setAttribute(attributeName, attributeValue);
|
||||
|
||||
@@ -44,11 +44,11 @@ public class UserAccountsFilter implements Filter {
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
|
||||
// tag::HttpSessionManager[]
|
||||
HttpSessionManager sessionManager =
|
||||
(HttpSessionManager) httpRequest.getAttribute(HttpSessionManager.class.getName());
|
||||
HttpSessionManager sessionManager = (HttpSessionManager) httpRequest
|
||||
.getAttribute(HttpSessionManager.class.getName());
|
||||
// end::HttpSessionManager[]
|
||||
SessionRepository<Session> repo =
|
||||
(SessionRepository<Session>) httpRequest.getAttribute(SessionRepository.class.getName());
|
||||
SessionRepository<Session> repo = (SessionRepository<Session>) httpRequest
|
||||
.getAttribute(SessionRepository.class.getName());
|
||||
|
||||
String currentSessionAlias = sessionManager.getCurrentSessionAlias(httpRequest);
|
||||
Map<String, String> sessionIds = sessionManager.getSessionIds(httpRequest);
|
||||
@@ -85,7 +85,8 @@ public class UserAccountsFilter implements Filter {
|
||||
|
||||
// tag::addAccountUrl[]
|
||||
String addAlias = unauthenticatedAlias == null ? // <1>
|
||||
sessionManager.getNewSessionAlias(httpRequest) : // <2>
|
||||
sessionManager.getNewSessionAlias(httpRequest)
|
||||
: // <2>
|
||||
unauthenticatedAlias; // <3>
|
||||
String addAccountUrl = sessionManager.encodeURL(contextPath, addAlias); // <4>
|
||||
// end::addAccountUrl[]
|
||||
|
||||
@@ -23,8 +23,8 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Initializes the H2 {@link WebServlet} so we can access our in memory database
|
||||
* from the URL "/h2".
|
||||
* Initializes the H2 {@link WebServlet} so we can access our in memory database from the
|
||||
* URL "/h2".
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
|
||||
@@ -34,8 +34,7 @@ import org.springframework.session.data.redis.config.annotation.web.http.EnableR
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
// tag::enable-redis-httpsession[]
|
||||
@EnableRedisHttpSession // (maxInactiveIntervalInSeconds = 60)
|
||||
public class WebSecurityConfig
|
||||
extends WebSecurityConfigurerAdapter {
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
// end::enable-redis-httpsession[]
|
||||
|
||||
// @formatter:off
|
||||
|
||||
@@ -32,8 +32,7 @@ public class WebSocketConfig
|
||||
extends AbstractSessionWebSocketMessageBrokerConfigurer<ExpiringSession> { // <1>
|
||||
|
||||
protected void configureStompEndpoints(StompEndpointRegistry registry) { // <2>
|
||||
registry.addEndpoint("/messages")
|
||||
.withSockJS();
|
||||
registry.addEndpoint("/messages").withSockJS();
|
||||
}
|
||||
|
||||
public void configureMessageBroker(MessageBrokerRegistry registry) {
|
||||
|
||||
@@ -24,8 +24,10 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.messaging.simp.SimpMessageSendingOperations;
|
||||
import org.springframework.session.ExpiringSession;
|
||||
|
||||
/**
|
||||
* These handlers are separated from WebSocketConfig because they are specific to this application and do not demonstrate a typical Spring Session setup.
|
||||
* These handlers are separated from WebSocketConfig because they are specific to this
|
||||
* application and do not demonstrate a typical Spring Session setup.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@@ -33,12 +35,16 @@ import org.springframework.session.ExpiringSession;
|
||||
public class WebSocketHandlersConfig<S extends ExpiringSession> {
|
||||
|
||||
@Bean
|
||||
public WebSocketConnectHandler<S> webSocketConnectHandler(SimpMessageSendingOperations messagingTemplate, ActiveWebSocketUserRepository repository) {
|
||||
public WebSocketConnectHandler<S> webSocketConnectHandler(
|
||||
SimpMessageSendingOperations messagingTemplate,
|
||||
ActiveWebSocketUserRepository repository) {
|
||||
return new WebSocketConnectHandler<S>(messagingTemplate, repository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebSocketDisconnectHandler<S> webSocketDisconnectHandler(SimpMessageSendingOperations messagingTemplate, ActiveWebSocketUserRepository repository) {
|
||||
public WebSocketDisconnectHandler<S> webSocketDisconnectHandler(
|
||||
SimpMessageSendingOperations messagingTemplate,
|
||||
ActiveWebSocketUserRepository repository) {
|
||||
return new WebSocketDisconnectHandler<S>(messagingTemplate, repository);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ import org.springframework.security.config.annotation.web.socket.AbstractSecurit
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
|
||||
public class WebSocketSecurityConfig
|
||||
extends AbstractSecurityWebSocketMessageBrokerConfigurer {
|
||||
|
||||
// @formatter:off
|
||||
@Override
|
||||
|
||||
@@ -56,5 +56,4 @@ public class ActiveWebSocketUser {
|
||||
this.connectionTime = connectionTime;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ import java.util.List;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
public interface ActiveWebSocketUserRepository extends CrudRepository<ActiveWebSocketUser, String> {
|
||||
public interface ActiveWebSocketUserRepository
|
||||
extends CrudRepository<ActiveWebSocketUser, String> {
|
||||
|
||||
@Query("select DISTINCT(u.username) from ActiveWebSocketUser u where u.username != ?#{principal?.username}")
|
||||
List<String> findAllActiveUsers();
|
||||
|
||||
@@ -59,6 +59,4 @@ public class InstantMessage {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -44,7 +44,8 @@ public class MessageController {
|
||||
private ActiveWebSocketUserRepository activeUserRepository;
|
||||
|
||||
@Autowired
|
||||
public MessageController(ActiveWebSocketUserRepository activeUserRepository, SimpMessageSendingOperations messagingTemplate) {
|
||||
public MessageController(ActiveWebSocketUserRepository activeUserRepository,
|
||||
SimpMessageSendingOperations messagingTemplate) {
|
||||
this.activeUserRepository = activeUserRepository;
|
||||
this.messagingTemplate = messagingTemplate;
|
||||
}
|
||||
|
||||
@@ -27,16 +27,14 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
/**
|
||||
* Annotate Spring MVC method arguments with this annotation to indicate you
|
||||
* wish to specify the argument with the value of the current
|
||||
* {@link Authentication#getPrincipal()} found on the
|
||||
* {@link SecurityContextHolder}.
|
||||
* Annotate Spring MVC method arguments with this annotation to indicate you wish to
|
||||
* specify the argument with the value of the current
|
||||
* {@link Authentication#getPrincipal()} found on the {@link SecurityContextHolder}.
|
||||
*
|
||||
* <p>
|
||||
* Creating your own annotation that uses {@link AuthenticationPrincipal} as a
|
||||
* meta annotation creates a layer of indirection between your code and Spring
|
||||
* Security's. For simplicity, you could instead use the
|
||||
* {@link AuthenticationPrincipal} directly.
|
||||
* Creating your own annotation that uses {@link AuthenticationPrincipal} as a meta
|
||||
* annotation creates a layer of indirection between your code and Spring Security's. For
|
||||
* simplicity, you could instead use the {@link AuthenticationPrincipal} directly.
|
||||
* </p>
|
||||
*
|
||||
* @author Rob Winch
|
||||
|
||||
@@ -42,8 +42,12 @@ public class UserRepositoryUserDetailsService implements UserDetailsService {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername
|
||||
* (java.lang.String)
|
||||
*/
|
||||
public UserDetails loadUserByUsername(String username)
|
||||
throws UsernameNotFoundException {
|
||||
|
||||
@@ -29,11 +29,13 @@ import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
|
||||
import org.springframework.messaging.simp.SimpMessageSendingOperations;
|
||||
import org.springframework.web.socket.messaging.SessionConnectEvent;
|
||||
|
||||
public class WebSocketConnectHandler<S> implements ApplicationListener<SessionConnectEvent> {
|
||||
public class WebSocketConnectHandler<S>
|
||||
implements ApplicationListener<SessionConnectEvent> {
|
||||
private ActiveWebSocketUserRepository repository;
|
||||
private SimpMessageSendingOperations messagingTemplate;
|
||||
|
||||
public WebSocketConnectHandler(SimpMessageSendingOperations messagingTemplate, ActiveWebSocketUserRepository repository) {
|
||||
public WebSocketConnectHandler(SimpMessageSendingOperations messagingTemplate,
|
||||
ActiveWebSocketUserRepository repository) {
|
||||
super();
|
||||
this.messagingTemplate = messagingTemplate;
|
||||
this.repository = repository;
|
||||
@@ -46,7 +48,9 @@ public class WebSocketConnectHandler<S> implements ApplicationListener<SessionCo
|
||||
return;
|
||||
}
|
||||
String id = SimpMessageHeaderAccessor.getSessionId(headers);
|
||||
this.repository.save(new ActiveWebSocketUser(id, user.getName(), Calendar.getInstance()));
|
||||
this.messagingTemplate.convertAndSend("/topic/friends/signin", Arrays.asList(user.getName()));
|
||||
this.repository.save(
|
||||
new ActiveWebSocketUser(id, user.getName(), Calendar.getInstance()));
|
||||
this.messagingTemplate.convertAndSend("/topic/friends/signin",
|
||||
Arrays.asList(user.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,13 @@ import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.messaging.simp.SimpMessageSendingOperations;
|
||||
import org.springframework.web.socket.messaging.SessionDisconnectEvent;
|
||||
|
||||
public class WebSocketDisconnectHandler<S> implements ApplicationListener<SessionDisconnectEvent> {
|
||||
public class WebSocketDisconnectHandler<S>
|
||||
implements ApplicationListener<SessionDisconnectEvent> {
|
||||
private ActiveWebSocketUserRepository repository;
|
||||
private SimpMessageSendingOperations messagingTemplate;
|
||||
|
||||
public WebSocketDisconnectHandler(SimpMessageSendingOperations messagingTemplate, ActiveWebSocketUserRepository repository) {
|
||||
public WebSocketDisconnectHandler(SimpMessageSendingOperations messagingTemplate,
|
||||
ActiveWebSocketUserRepository repository) {
|
||||
super();
|
||||
this.messagingTemplate = messagingTemplate;
|
||||
this.repository = repository;
|
||||
@@ -46,7 +48,8 @@ public class WebSocketDisconnectHandler<S> implements ApplicationListener<Sessio
|
||||
}
|
||||
|
||||
this.repository.delete(id);
|
||||
this.messagingTemplate.convertAndSend("/topic/friends/signout", Arrays.asList(user.getUsername()));
|
||||
this.messagingTemplate.convertAndSend("/topic/friends/signout",
|
||||
Arrays.asList(user.getUsername()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,25 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.session.data;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
@@ -10,8 +28,6 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Base class for repositories integration tests
|
||||
*
|
||||
@@ -30,14 +46,18 @@ public abstract class AbstractITests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
if (registry != null) {
|
||||
registry.clear();
|
||||
if (this.registry != null) {
|
||||
this.registry.clear();
|
||||
}
|
||||
context = SecurityContextHolder.createEmptyContext();
|
||||
context.setAuthentication(new UsernamePasswordAuthenticationToken("username-" + UUID.randomUUID(), "na", AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
this.context = SecurityContextHolder.createEmptyContext();
|
||||
this.context.setAuthentication(
|
||||
new UsernamePasswordAuthenticationToken("username-" + UUID.randomUUID(),
|
||||
"na", AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
|
||||
changedContext = SecurityContextHolder.createEmptyContext();
|
||||
changedContext.setAuthentication(new UsernamePasswordAuthenticationToken("changedContext-" + UUID.randomUUID(), "na", AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
this.changedContext = SecurityContextHolder.createEmptyContext();
|
||||
this.changedContext.setAuthentication(new UsernamePasswordAuthenticationToken(
|
||||
"changedContext-" + UUID.randomUUID(), "na",
|
||||
AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,12 +45,14 @@ public class SessionEventRegistry implements ApplicationListener<AbstractSession
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <E extends AbstractSessionEvent> E getEvent(String sessionId) throws InterruptedException {
|
||||
public <E extends AbstractSessionEvent> E getEvent(String sessionId)
|
||||
throws InterruptedException {
|
||||
return (E) waitForEvent(sessionId);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <E extends AbstractSessionEvent> E waitForEvent(String sessionId) throws InterruptedException {
|
||||
private <E extends AbstractSessionEvent> E waitForEvent(String sessionId)
|
||||
throws InterruptedException {
|
||||
Object lock = getLock(sessionId);
|
||||
synchronized (lock) {
|
||||
if (!this.events.containsKey(sessionId)) {
|
||||
|
||||
@@ -47,8 +47,8 @@ import org.springframework.session.events.AbstractSessionEvent;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* AbstractGemFireIntegrationTests is an abstract base class encapsulating common operations for writing
|
||||
* Spring Session GemFire integration tests.
|
||||
* AbstractGemFireIntegrationTests is an abstract base class encapsulating common
|
||||
* operations for writing Spring Session GemFire integration tests.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
@@ -65,22 +65,24 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public abstract class AbstractGemFireIntegrationTests {
|
||||
|
||||
protected static final boolean DEFAULT_ENABLE_QUERY_DEBUGGING = false;
|
||||
protected static final boolean GEMFIRE_QUERY_DEBUG = Boolean.getBoolean("spring.session.data.gemfire.query.debug");
|
||||
protected static final boolean GEMFIRE_QUERY_DEBUG = Boolean
|
||||
.getBoolean("spring.session.data.gemfire.query.debug");
|
||||
|
||||
protected static final int DEFAULT_GEMFIRE_SERVER_PORT = CacheServer.DEFAULT_PORT;
|
||||
|
||||
protected static final long DEFAULT_WAIT_DURATION = TimeUnit.SECONDS.toMillis(20);
|
||||
protected static final long DEFAULT_WAIT_INTERVAL = 500L;
|
||||
|
||||
protected static final File WORKING_DIRECTORY = new File(System.getProperty("user.dir"));
|
||||
protected static final File WORKING_DIRECTORY = new File(
|
||||
System.getProperty("user.dir"));
|
||||
|
||||
protected static final String DEFAULT_PROCESS_CONTROL_FILENAME = "process.ctl";
|
||||
|
||||
protected static final String GEMFIRE_LOG_FILE_NAME = System.getProperty(
|
||||
"spring.session.data.gemfire.log-file", "server.log");
|
||||
protected static final String GEMFIRE_LOG_FILE_NAME = System
|
||||
.getProperty("spring.session.data.gemfire.log-file", "server.log");
|
||||
|
||||
protected static final String GEMFIRE_LOG_LEVEL = System.getProperty(
|
||||
"spring.session.data.gemfire.log-level", "warning");
|
||||
protected static final String GEMFIRE_LOG_LEVEL = System
|
||||
.getProperty("spring.session.data.gemfire.log-level", "warning");
|
||||
|
||||
@Autowired
|
||||
protected Cache gemfireCache;
|
||||
@@ -90,15 +92,17 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
System.setProperty("gemfire.Query.VERBOSE", String.valueOf(isQueryDebuggingEnabled()));
|
||||
System.setProperty("gemfire.Query.VERBOSE",
|
||||
String.valueOf(isQueryDebuggingEnabled()));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static File createDirectory(String pathname) {
|
||||
File directory = new File(WORKING_DIRECTORY, pathname);
|
||||
|
||||
assertThat(directory.isDirectory() || directory.mkdirs()).as(
|
||||
String.format("Failed to create directory (%1$s)", directory)).isTrue();
|
||||
assertThat(directory.isDirectory() || directory.mkdirs())
|
||||
.as(String.format("Failed to create directory (%1$s)", directory))
|
||||
.isTrue();
|
||||
|
||||
directory.deleteOnExit();
|
||||
|
||||
@@ -106,7 +110,8 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static List<String> createJavaProcessCommandLine(Class<?> type, String... args) {
|
||||
protected static List<String> createJavaProcessCommandLine(Class<?> type,
|
||||
String... args) {
|
||||
List<String> commandLine = new ArrayList<String>();
|
||||
|
||||
String javaHome = System.getProperty("java.home");
|
||||
@@ -117,7 +122,8 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
commandLine.add("-ea");
|
||||
commandLine.add(String.format("-Dgemfire.log-file=%1$s", GEMFIRE_LOG_FILE_NAME));
|
||||
commandLine.add(String.format("-Dgemfire.log-level=%1$s", GEMFIRE_LOG_LEVEL));
|
||||
commandLine.add(String.format("-Dgemfire.Query.VERBOSE=%1$s", GEMFIRE_QUERY_DEBUG));
|
||||
commandLine
|
||||
.add(String.format("-Dgemfire.Query.VERBOSE=%1$s", GEMFIRE_QUERY_DEBUG));
|
||||
commandLine.addAll(extractJvmArguments(args));
|
||||
commandLine.add("-classpath");
|
||||
commandLine.add(System.getProperty("java.class.path"));
|
||||
@@ -156,11 +162,10 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static Process run(Class<?> type, File directory, String... args) throws IOException {
|
||||
return new ProcessBuilder()
|
||||
.command(createJavaProcessCommandLine(type, args))
|
||||
.directory(directory)
|
||||
.start();
|
||||
protected static Process run(Class<?> type, File directory, String... args)
|
||||
throws IOException {
|
||||
return new ProcessBuilder().command(createJavaProcessCommandLine(type, args))
|
||||
.directory(directory).start();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -169,8 +174,10 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static boolean waitForCacheServerToStart(CacheServer cacheServer, long duration) {
|
||||
return waitForCacheServerToStart(cacheServer.getBindAddress(), cacheServer.getPort(), duration);
|
||||
protected static boolean waitForCacheServerToStart(CacheServer cacheServer,
|
||||
long duration) {
|
||||
return waitForCacheServerToStart(cacheServer.getBindAddress(),
|
||||
cacheServer.getPort(), duration);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -179,7 +186,8 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static boolean waitForCacheServerToStart(final String host, final int port, long duration) {
|
||||
protected static boolean waitForCacheServerToStart(final String host, final int port,
|
||||
long duration) {
|
||||
return waitOnCondition(new Condition() {
|
||||
AtomicBoolean connected = new AtomicBoolean(false);
|
||||
|
||||
@@ -203,7 +211,8 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
}, duration);
|
||||
}
|
||||
|
||||
// NOTE this method would not be necessary except Spring Sessions' build does not fork the test JVM
|
||||
// NOTE this method would not be necessary except Spring Sessions' build does not fork
|
||||
// the test JVM
|
||||
// for every test class.
|
||||
/* (non-Javadoc) */
|
||||
protected static boolean waitForClientCacheToClose() {
|
||||
@@ -238,7 +247,8 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("all")
|
||||
protected static boolean waitForProcessToStart(Process process, File directory, long duration) {
|
||||
protected static boolean waitForProcessToStart(Process process, File directory,
|
||||
long duration) {
|
||||
final File processControl = new File(directory, DEFAULT_PROCESS_CONTROL_FILENAME);
|
||||
|
||||
waitOnCondition(new Condition() {
|
||||
@@ -256,7 +266,8 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static int waitForProcessToStop(Process process, File directory, long duration) {
|
||||
protected static int waitForProcessToStop(Process process, File directory,
|
||||
long duration) {
|
||||
final long timeout = (System.currentTimeMillis() + duration);
|
||||
|
||||
try {
|
||||
@@ -311,24 +322,30 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void assertRegion(Region<?, ?> actualRegion, String expectedName, DataPolicy expectedDataPolicy) {
|
||||
protected void assertRegion(Region<?, ?> actualRegion, String expectedName,
|
||||
DataPolicy expectedDataPolicy) {
|
||||
assertThat(actualRegion).isNotNull();
|
||||
assertThat(actualRegion.getName()).isEqualTo(expectedName);
|
||||
assertThat(actualRegion.getFullPath()).isEqualTo(GemFireUtils.toRegionPath(expectedName));
|
||||
assertThat(actualRegion.getFullPath())
|
||||
.isEqualTo(GemFireUtils.toRegionPath(expectedName));
|
||||
assertThat(actualRegion.getAttributes()).isNotNull();
|
||||
assertThat(actualRegion.getAttributes().getDataPolicy()).isEqualTo(expectedDataPolicy);
|
||||
assertThat(actualRegion.getAttributes().getDataPolicy())
|
||||
.isEqualTo(expectedDataPolicy);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void assertIndex(Index index, String expectedExpression, String expectedFromClause) {
|
||||
protected void assertIndex(Index index, String expectedExpression,
|
||||
String expectedFromClause) {
|
||||
assertThat(index).isNotNull();
|
||||
assertThat(index.getIndexedExpression()).isEqualTo(expectedExpression);
|
||||
assertThat(index.getFromClause()).isEqualTo(expectedFromClause);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void assertEntryIdleTimeout(Region<?, ?> region, ExpirationAction expectedAction, int expectedTimeout) {
|
||||
assertEntryIdleTimeout(region.getAttributes().getEntryIdleTimeout(), expectedAction, expectedTimeout);
|
||||
protected void assertEntryIdleTimeout(Region<?, ?> region,
|
||||
ExpirationAction expectedAction, int expectedTimeout) {
|
||||
assertEntryIdleTimeout(region.getAttributes().getEntryIdleTimeout(),
|
||||
expectedAction, expectedTimeout);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -403,13 +420,14 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* The SessionEventListener class is a Spring {@link ApplicationListener} listening for Spring HTTP Session
|
||||
* application events.
|
||||
* The SessionEventListener class is a Spring {@link ApplicationListener} listening
|
||||
* for Spring HTTP Session application events.
|
||||
*
|
||||
* @see org.springframework.context.ApplicationListener
|
||||
* @see org.springframework.session.events.AbstractSessionEvent
|
||||
*/
|
||||
public static class SessionEventListener implements ApplicationListener<AbstractSessionEvent> {
|
||||
public static class SessionEventListener
|
||||
implements ApplicationListener<AbstractSessionEvent> {
|
||||
|
||||
private volatile AbstractSessionEvent sessionEvent;
|
||||
|
||||
@@ -439,7 +457,8 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* The Condition interface defines a logical condition that must be satisfied before it is safe to proceed.
|
||||
* The Condition interface defines a logical condition that must be satisfied before
|
||||
* it is safe to proceed.
|
||||
*/
|
||||
protected interface Condition {
|
||||
boolean evaluate();
|
||||
|
||||
@@ -69,16 +69,19 @@ import org.springframework.util.SocketUtils;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* The ClientServerGemFireOperationsSessionRepositoryIntegrationTests class is a test suite of test cases testing
|
||||
* the functionality of GemFire-backed Spring Sessions using a GemFire client-server topology.
|
||||
* The ClientServerGemFireOperationsSessionRepositoryIntegrationTests class is a test
|
||||
* suite of test cases testing the functionality of GemFire-backed Spring Sessions using a
|
||||
* GemFire client-server topology.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.
|
||||
* EnableGemFireHttpSession
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.
|
||||
* GemFireHttpSessionConfiguration
|
||||
* @see org.springframework.test.annotation.DirtiesContext
|
||||
* @see org.springframework.test.context.ContextConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
|
||||
@@ -89,15 +92,16 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @see com.gemstone.gemfire.cache.server.CacheServer
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes =
|
||||
ClientServerGemFireOperationsSessionRepositoryIntegrationTests.SpringSessionGemFireClientConfiguration.class)
|
||||
@ContextConfiguration(classes = ClientServerGemFireOperationsSessionRepositoryIntegrationTests.SpringSessionGemFireClientConfiguration.class)
|
||||
@DirtiesContext
|
||||
@WebAppConfiguration
|
||||
public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests extends AbstractGemFireIntegrationTests {
|
||||
public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
|
||||
extends AbstractGemFireIntegrationTests {
|
||||
|
||||
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 1;
|
||||
|
||||
private static final DateFormat TIMESTAMP = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
|
||||
private static final DateFormat TIMESTAMP = new SimpleDateFormat(
|
||||
"yyyy-MM-dd-HH-mm-ss");
|
||||
|
||||
private static File processWorkingDirectory;
|
||||
|
||||
@@ -114,21 +118,25 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
|
||||
final int port = SocketUtils.findAvailableTcpPort();
|
||||
|
||||
System.err.printf("Starting GemFire Server running on [%1$s] listening on port [%2$d]%n",
|
||||
System.err.printf(
|
||||
"Starting GemFire Server running on [%1$s] listening on port [%2$d]%n",
|
||||
InetAddress.getLocalHost().getHostName(), port);
|
||||
|
||||
System.setProperty("spring.session.data.gemfire.port", String.valueOf(port));
|
||||
|
||||
String processWorkingDirectoryPathname = String.format("gemfire-client-server-tests-%1$s",
|
||||
TIMESTAMP.format(new Date()));
|
||||
String processWorkingDirectoryPathname = String
|
||||
.format("gemfire-client-server-tests-%1$s", TIMESTAMP.format(new Date()));
|
||||
|
||||
processWorkingDirectory = createDirectory(processWorkingDirectoryPathname);
|
||||
gemfireServer = run(SpringSessionGemFireServerConfiguration.class, processWorkingDirectory,
|
||||
gemfireServer = run(SpringSessionGemFireServerConfiguration.class,
|
||||
processWorkingDirectory,
|
||||
String.format("-Dspring.session.data.gemfire.port=%1$d", port));
|
||||
|
||||
assertThat(waitForCacheServerToStart(SpringSessionGemFireServerConfiguration.SERVER_HOSTNAME, port)).isTrue();
|
||||
assertThat(waitForCacheServerToStart(
|
||||
SpringSessionGemFireServerConfiguration.SERVER_HOSTNAME, port)).isTrue();
|
||||
|
||||
System.err.printf("GemFire Server [startup time = %1$d ms]%n", System.currentTimeMillis() - t0);
|
||||
System.err.printf("GemFire Server [startup time = %1$d ms]%n",
|
||||
System.currentTimeMillis() - t0);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@@ -139,7 +147,8 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
waitForProcessToStop(gemfireServer, processWorkingDirectory));
|
||||
}
|
||||
|
||||
if (Boolean.valueOf(System.getProperty("spring.session.data.gemfire.fork.clean", Boolean.TRUE.toString()))) {
|
||||
if (Boolean.valueOf(System.getProperty("spring.session.data.gemfire.fork.clean",
|
||||
Boolean.TRUE.toString()))) {
|
||||
FileSystemUtils.deleteRecursively(processWorkingDirectory);
|
||||
}
|
||||
|
||||
@@ -150,16 +159,17 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
public void setup() {
|
||||
assertThat(GemFireUtils.isClient(gemfireCache)).isTrue();
|
||||
|
||||
Region<Object, ExpiringSession> springSessionGemFireRegion = gemfireCache.getRegion(
|
||||
SPRING_SESSION_GEMFIRE_REGION_NAME);
|
||||
Region<Object, ExpiringSession> springSessionGemFireRegion = gemfireCache
|
||||
.getRegion(SPRING_SESSION_GEMFIRE_REGION_NAME);
|
||||
|
||||
assertThat(springSessionGemFireRegion).isNotNull();
|
||||
|
||||
RegionAttributes<Object, ExpiringSession> springSessionGemFireRegionAttributes =
|
||||
springSessionGemFireRegion.getAttributes();
|
||||
RegionAttributes<Object, ExpiringSession> springSessionGemFireRegionAttributes = springSessionGemFireRegion
|
||||
.getAttributes();
|
||||
|
||||
assertThat(springSessionGemFireRegionAttributes).isNotNull();
|
||||
assertThat(springSessionGemFireRegionAttributes.getDataPolicy()).isEqualTo(DataPolicy.EMPTY);
|
||||
assertThat(springSessionGemFireRegionAttributes.getDataPolicy())
|
||||
.isEqualTo(DataPolicy.EMPTY);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -173,7 +183,8 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
|
||||
ExpiringSession expectedSession = save(createSession());
|
||||
|
||||
AbstractSessionEvent sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
|
||||
AbstractSessionEvent sessionEvent = this.sessionEventListener
|
||||
.waitForSessionEvent(500);
|
||||
|
||||
assertThat(sessionEvent).isInstanceOf(SessionCreatedEvent.class);
|
||||
|
||||
@@ -181,9 +192,12 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
|
||||
assertThat(createdSession).isEqualTo(expectedSession);
|
||||
assertThat(createdSession.getId()).isNotNull();
|
||||
assertThat(createdSession.getCreationTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime);
|
||||
assertThat(createdSession.getLastAccessedTime()).isEqualTo(createdSession.getCreationTime());
|
||||
assertThat(createdSession.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
assertThat(createdSession.getCreationTime())
|
||||
.isGreaterThanOrEqualTo(beforeOrAtCreationTime);
|
||||
assertThat(createdSession.getLastAccessedTime())
|
||||
.isEqualTo(createdSession.getCreationTime());
|
||||
assertThat(createdSession.getMaxInactiveIntervalInSeconds())
|
||||
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
|
||||
this.gemfireSessionRepository.delete(expectedSession.getId());
|
||||
}
|
||||
@@ -192,28 +206,32 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
public void getExistingNonExpiredSessionBeforeAndAfterExpiration() {
|
||||
ExpiringSession expectedSession = save(touch(createSession()));
|
||||
|
||||
AbstractSessionEvent sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
|
||||
AbstractSessionEvent sessionEvent = this.sessionEventListener
|
||||
.waitForSessionEvent(500);
|
||||
|
||||
assertThat(sessionEvent).isInstanceOf(SessionCreatedEvent.class);
|
||||
assertThat(sessionEvent.<ExpiringSession>getSession()).isEqualTo(expectedSession);
|
||||
assertThat(this.sessionEventListener.getSessionEvent()).isNull();
|
||||
|
||||
ExpiringSession savedSession = this.gemfireSessionRepository.getSession(expectedSession.getId());
|
||||
ExpiringSession savedSession = this.gemfireSessionRepository
|
||||
.getSession(expectedSession.getId());
|
||||
|
||||
assertThat(savedSession).isEqualTo(expectedSession);
|
||||
|
||||
// NOTE for some reason or another, performing a GemFire (Client)Cache Region.get(key)
|
||||
// NOTE for some reason or another, performing a GemFire (Client)Cache
|
||||
// Region.get(key)
|
||||
// causes a Region CREATE event... o.O
|
||||
// calling sessionEventListener.getSessionEvent() here to clear the event
|
||||
this.sessionEventListener.getSessionEvent();
|
||||
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(TimeUnit.SECONDS.toMillis(
|
||||
MAX_INACTIVE_INTERVAL_IN_SECONDS + 1));
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(
|
||||
TimeUnit.SECONDS.toMillis(MAX_INACTIVE_INTERVAL_IN_SECONDS + 1));
|
||||
|
||||
assertThat(sessionEvent).isInstanceOf(SessionExpiredEvent.class);
|
||||
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSession.getId());
|
||||
|
||||
ExpiringSession expiredSession = this.gemfireSessionRepository.getSession(expectedSession.getId());
|
||||
ExpiringSession expiredSession = this.gemfireSessionRepository
|
||||
.getSession(expectedSession.getId());
|
||||
|
||||
assertThat(expiredSession).isNull();
|
||||
}
|
||||
@@ -222,7 +240,8 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
public void deleteExistingNonExpiredSessionFiresSessionDeletedEventAndReturnsNullOnGet() {
|
||||
ExpiringSession expectedSession = save(touch(createSession()));
|
||||
|
||||
AbstractSessionEvent sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
|
||||
AbstractSessionEvent sessionEvent = this.sessionEventListener
|
||||
.waitForSessionEvent(500);
|
||||
|
||||
assertThat(sessionEvent).isInstanceOf(SessionCreatedEvent.class);
|
||||
assertThat(sessionEvent.<ExpiringSession>getSession()).isEqualTo(expectedSession);
|
||||
@@ -234,13 +253,13 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
assertThat(sessionEvent).isInstanceOf(SessionDeletedEvent.class);
|
||||
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSession.getId());
|
||||
|
||||
ExpiringSession deletedSession = this.gemfireSessionRepository.getSession(expectedSession.getId());
|
||||
ExpiringSession deletedSession = this.gemfireSessionRepository
|
||||
.getSession(expectedSession.getId());
|
||||
|
||||
assertThat(deletedSession).isNull();
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME,
|
||||
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME, maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
static class SpringSessionGemFireClientConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -251,13 +270,16 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
@Bean
|
||||
Properties gemfireProperties() {
|
||||
Properties gemfireProperties = new Properties();
|
||||
gemfireProperties.setProperty("name", ClientServerGemFireOperationsSessionRepositoryIntegrationTests.class.getName());
|
||||
gemfireProperties.setProperty("name",
|
||||
ClientServerGemFireOperationsSessionRepositoryIntegrationTests.class
|
||||
.getName());
|
||||
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
@Bean(name = GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME)
|
||||
PoolFactoryBean gemfirePool(@Value("${spring.session.data.gemfire.port:" + DEFAULT_GEMFIRE_SERVER_PORT + "}") int port) {
|
||||
PoolFactoryBean gemfirePool(@Value("${spring.session.data.gemfire.port:"
|
||||
+ DEFAULT_GEMFIRE_SERVER_PORT + "}") int port) {
|
||||
PoolFactoryBean poolFactory = new PoolFactoryBean() {
|
||||
@Override
|
||||
protected Properties resolveGemfireProperties() {
|
||||
@@ -268,15 +290,18 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
poolFactory.setName(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME);
|
||||
poolFactory.setFreeConnectionTimeout(5000); // 5 seconds
|
||||
poolFactory.setKeepAlive(false);
|
||||
poolFactory.setMaxConnections(SpringSessionGemFireServerConfiguration.MAX_CONNECTIONS);
|
||||
poolFactory.setMaxConnections(
|
||||
SpringSessionGemFireServerConfiguration.MAX_CONNECTIONS);
|
||||
poolFactory.setPingInterval(TimeUnit.SECONDS.toMillis(5));
|
||||
poolFactory.setReadTimeout(2000); // 2 seconds
|
||||
poolFactory.setRetryAttempts(2);
|
||||
poolFactory.setSubscriptionEnabled(true);
|
||||
poolFactory.setThreadLocalConnections(false);
|
||||
|
||||
poolFactory.setServerEndpoints(Collections.singletonList(new ConnectionEndpoint(
|
||||
SpringSessionGemFireServerConfiguration.SERVER_HOSTNAME, port)));
|
||||
poolFactory
|
||||
.setServerEndpoints(Collections.singletonList(new ConnectionEndpoint(
|
||||
SpringSessionGemFireServerConfiguration.SERVER_HOSTNAME,
|
||||
port)));
|
||||
|
||||
return poolFactory;
|
||||
}
|
||||
@@ -315,8 +340,7 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
}
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME,
|
||||
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME, maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
static class SpringSessionGemFireServerConfiguration {
|
||||
|
||||
static final int MAX_CONNECTIONS = 50;
|
||||
@@ -331,7 +355,8 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
Properties gemfireProperties() {
|
||||
Properties gemfireProperties = new Properties();
|
||||
|
||||
gemfireProperties.setProperty("name", SpringSessionGemFireServerConfiguration.class.getName());
|
||||
gemfireProperties.setProperty("name",
|
||||
SpringSessionGemFireServerConfiguration.class.getName());
|
||||
gemfireProperties.setProperty("mcast-port", "0");
|
||||
gemfireProperties.setProperty("log-file", "server.log");
|
||||
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
|
||||
@@ -351,7 +376,8 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
|
||||
@Bean
|
||||
CacheServerFactoryBean gemfireCacheServer(Cache gemfireCache,
|
||||
@Value("${spring.session.data.gemfire.port:" + DEFAULT_GEMFIRE_SERVER_PORT + "}") int port) {
|
||||
@Value("${spring.session.data.gemfire.port:" + DEFAULT_GEMFIRE_SERVER_PORT
|
||||
+ "}") int port) {
|
||||
|
||||
CacheServerFactoryBean cacheServerFactory = new CacheServerFactoryBean();
|
||||
|
||||
@@ -366,7 +392,8 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests exte
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public static void main(final String[] args) throws IOException {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringSessionGemFireServerConfiguration.class);
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
SpringSessionGemFireServerConfiguration.class);
|
||||
context.registerShutdownHook();
|
||||
writeProcessControlFile(WORKING_DIRECTORY);
|
||||
}
|
||||
|
||||
@@ -55,8 +55,9 @@ import org.springframework.util.ObjectUtils;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* The GemFireOperationsSessionRepositoryIntegrationTests class is a test suite of test cases testing
|
||||
* the findByPrincipalName query method on the GemFireOpeationsSessionRepository class.
|
||||
* The GemFireOperationsSessionRepositoryIntegrationTests class is a test suite of test
|
||||
* cases testing the findByPrincipalName query method on the
|
||||
* GemFireOpeationsSessionRepository class.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
@@ -75,7 +76,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ContextConfiguration
|
||||
@DirtiesContext
|
||||
@WebAppConfiguration
|
||||
public class GemFireOperationsSessionRepositoryIntegrationTests extends AbstractGemFireIntegrationTests {
|
||||
public class GemFireOperationsSessionRepositoryIntegrationTests
|
||||
extends AbstractGemFireIntegrationTests {
|
||||
|
||||
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 300;
|
||||
|
||||
@@ -90,48 +92,63 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
@Before
|
||||
public void setup() {
|
||||
this.context = SecurityContextHolder.createEmptyContext();
|
||||
this.context.setAuthentication(new UsernamePasswordAuthenticationToken("username-" + UUID.randomUUID(), "na", AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
this.context.setAuthentication(
|
||||
new UsernamePasswordAuthenticationToken("username-" + UUID.randomUUID(),
|
||||
"na", AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
|
||||
this.changedContext = SecurityContextHolder.createEmptyContext();
|
||||
this.changedContext.setAuthentication(new UsernamePasswordAuthenticationToken("changedContext-" + UUID.randomUUID(), "na", AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
this.changedContext.setAuthentication(new UsernamePasswordAuthenticationToken(
|
||||
"changedContext-" + UUID.randomUUID(), "na",
|
||||
AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
|
||||
assertThat(this.gemfireCache).isNotNull();
|
||||
assertThat(this.gemfireSessionRepository).isNotNull();
|
||||
assertThat(this.gemfireSessionRepository.getMaxInactiveIntervalInSeconds()).isEqualTo(
|
||||
assertThat(this.gemfireSessionRepository.getMaxInactiveIntervalInSeconds())
|
||||
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
|
||||
Region<Object, ExpiringSession> sessionRegion = this.gemfireCache
|
||||
.getRegion(SPRING_SESSION_GEMFIRE_REGION_NAME);
|
||||
|
||||
assertRegion(sessionRegion, SPRING_SESSION_GEMFIRE_REGION_NAME,
|
||||
DataPolicy.PARTITION);
|
||||
assertEntryIdleTimeout(sessionRegion, ExpirationAction.INVALIDATE,
|
||||
MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
|
||||
Region<Object, ExpiringSession> sessionRegion = this.gemfireCache.getRegion(SPRING_SESSION_GEMFIRE_REGION_NAME);
|
||||
|
||||
assertRegion(sessionRegion, SPRING_SESSION_GEMFIRE_REGION_NAME, DataPolicy.PARTITION);
|
||||
assertEntryIdleTimeout(sessionRegion, ExpirationAction.INVALIDATE, MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
}
|
||||
|
||||
protected Map<String, ExpiringSession> doFindByIndexNameAndIndexValue(String indexName, String indexValue) {
|
||||
return this.gemfireSessionRepository.findByIndexNameAndIndexValue(indexName, indexValue);
|
||||
protected Map<String, ExpiringSession> doFindByIndexNameAndIndexValue(
|
||||
String indexName, String indexValue) {
|
||||
return this.gemfireSessionRepository.findByIndexNameAndIndexValue(indexName,
|
||||
indexValue);
|
||||
}
|
||||
|
||||
protected Map<String, ExpiringSession> doFindByPrincipalName(String principalName) {
|
||||
return doFindByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
|
||||
return doFindByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
principalName);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected Map<String, ExpiringSession> doFindByPrincipalName(String regionName, String principalName) {
|
||||
protected Map<String, ExpiringSession> doFindByPrincipalName(String regionName,
|
||||
String principalName) {
|
||||
try {
|
||||
Region<String, ExpiringSession> region = this.gemfireCache.getRegion(regionName);
|
||||
Region<String, ExpiringSession> region = this.gemfireCache
|
||||
.getRegion(regionName);
|
||||
|
||||
assertThat(region).isNotNull();
|
||||
|
||||
QueryService queryService = region.getRegionService().getQueryService();
|
||||
|
||||
String queryString = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
|
||||
String queryString = String.format(
|
||||
GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
|
||||
region.getFullPath());
|
||||
|
||||
Query query = queryService.newQuery(queryString);
|
||||
|
||||
SelectResults<ExpiringSession> results = (SelectResults<ExpiringSession>) query.execute(
|
||||
new Object[] { principalName });
|
||||
SelectResults<ExpiringSession> results = (SelectResults<ExpiringSession>) query
|
||||
.execute(new Object[] { principalName });
|
||||
|
||||
Map<String, ExpiringSession> sessions = new HashMap<String, ExpiringSession>(results.size());
|
||||
Map<String, ExpiringSession> sessions = new HashMap<String, ExpiringSession>(
|
||||
results.size());
|
||||
|
||||
for (ExpiringSession session : results.asList()) {
|
||||
sessions.put(session.getId(), session);
|
||||
@@ -149,17 +166,22 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
return true;
|
||||
}
|
||||
|
||||
protected ExpiringSession setAttribute(ExpiringSession session, String attributeName, Object attributeValue) {
|
||||
protected ExpiringSession setAttribute(ExpiringSession session, String attributeName,
|
||||
Object attributeValue) {
|
||||
session.setAttribute(attributeName, attributeValue);
|
||||
return session;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findSessionsByIndexedSessionAttributeNameValues() {
|
||||
ExpiringSession johnBlumSession = save(touch(setAttribute(createSession("johnBlum"), "vip", "yes")));
|
||||
ExpiringSession robWinchSession = save(touch(setAttribute(createSession("robWinch"), "vip", "yes")));
|
||||
ExpiringSession jonDoeSession = save(touch(setAttribute(createSession("jonDoe"), "vip", "no")));
|
||||
ExpiringSession pieDoeSession = save(touch(setAttribute(createSession("pieDoe"), "viper", "true")));
|
||||
ExpiringSession johnBlumSession = save(
|
||||
touch(setAttribute(createSession("johnBlum"), "vip", "yes")));
|
||||
ExpiringSession robWinchSession = save(
|
||||
touch(setAttribute(createSession("robWinch"), "vip", "yes")));
|
||||
ExpiringSession jonDoeSession = save(
|
||||
touch(setAttribute(createSession("jonDoe"), "vip", "no")));
|
||||
ExpiringSession pieDoeSession = save(
|
||||
touch(setAttribute(createSession("pieDoe"), "viper", "true")));
|
||||
ExpiringSession sourDoeSession = save(touch(createSession("sourDoe")));
|
||||
|
||||
assertThat(get(johnBlumSession.getId())).isEqualTo(johnBlumSession);
|
||||
@@ -173,7 +195,8 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
assertThat(get(sourDoeSession.getId())).isEqualTo(sourDoeSession);
|
||||
assertThat(sourDoeSession.getAttributeNames().contains("vip")).isFalse();
|
||||
|
||||
Map<String, ExpiringSession> vipSessions = doFindByIndexNameAndIndexValue("vip", "yes");
|
||||
Map<String, ExpiringSession> vipSessions = doFindByIndexNameAndIndexValue("vip",
|
||||
"yes");
|
||||
|
||||
assertThat(vipSessions).isNotNull();
|
||||
assertThat(vipSessions.size()).isEqualTo(2);
|
||||
@@ -183,7 +206,8 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
assertThat(vipSessions.containsKey(pieDoeSession.getId()));
|
||||
assertThat(vipSessions.containsKey(sourDoeSession.getId()));
|
||||
|
||||
Map<String, ExpiringSession> nonVipSessions = doFindByIndexNameAndIndexValue("vip", "no");
|
||||
Map<String, ExpiringSession> nonVipSessions = doFindByIndexNameAndIndexValue(
|
||||
"vip", "no");
|
||||
|
||||
assertThat(nonVipSessions).isNotNull();
|
||||
assertThat(nonVipSessions.size()).isEqualTo(1);
|
||||
@@ -193,7 +217,8 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
assertThat(nonVipSessions.containsKey(pieDoeSession.getId()));
|
||||
assertThat(nonVipSessions.containsKey(sourDoeSession.getId()));
|
||||
|
||||
Map<String, ExpiringSession> noSessions = doFindByIndexNameAndIndexValue("nonExistingAttribute", "test");
|
||||
Map<String, ExpiringSession> noSessions = doFindByIndexNameAndIndexValue(
|
||||
"nonExistingAttribute", "test");
|
||||
|
||||
assertThat(noSessions).isNotNull();
|
||||
assertThat(noSessions.isEmpty()).isTrue();
|
||||
@@ -241,7 +266,8 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
|
||||
save(toSave);
|
||||
|
||||
Map<String, ExpiringSession> findByPrincipalName = doFindByPrincipalName(getSecurityName());
|
||||
Map<String, ExpiringSession> findByPrincipalName = doFindByPrincipalName(
|
||||
getSecurityName());
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
}
|
||||
@@ -255,7 +281,8 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
|
||||
save(toSave);
|
||||
|
||||
Map<String, ExpiringSession> findByPrincipalName = doFindByPrincipalName(getSecurityName());
|
||||
Map<String, ExpiringSession> findByPrincipalName = doFindByPrincipalName(
|
||||
getSecurityName());
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = doFindByPrincipalName(getChangedSecurityName());
|
||||
@@ -264,7 +291,8 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
|
||||
@Test
|
||||
public void findsNoSessionsByNonExistingPrincipal() {
|
||||
Map<String, ExpiringSession> nonExistingPrincipalSessions = doFindByPrincipalName("nonExistingPrincipalName");
|
||||
Map<String, ExpiringSession> nonExistingPrincipalSessions = doFindByPrincipalName(
|
||||
"nonExistingPrincipalName");
|
||||
|
||||
assertThat(nonExistingPrincipalSessions).isNotNull();
|
||||
assertThat(nonExistingPrincipalSessions.isEmpty()).isTrue();
|
||||
@@ -274,10 +302,12 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
public void findsNoSessionsAfterPrincipalIsRemoved() {
|
||||
String username = "doesNotFindAfterPrincipalRemoved";
|
||||
ExpiringSession session = save(touch(createSession(username)));
|
||||
session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, null);
|
||||
session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
null);
|
||||
save(session);
|
||||
|
||||
Map<String, ExpiringSession> nonExistingPrincipalSessions = doFindByPrincipalName(username);
|
||||
Map<String, ExpiringSession> nonExistingPrincipalSessions = doFindByPrincipalName(
|
||||
username);
|
||||
|
||||
assertThat(nonExistingPrincipalSessions).isNotNull();
|
||||
assertThat(nonExistingPrincipalSessions.isEmpty()).isTrue();
|
||||
@@ -287,12 +317,14 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
public void saveAndReadSessionWithAttributes() {
|
||||
ExpiringSession expectedSession = this.gemfireSessionRepository.createSession();
|
||||
|
||||
assertThat(expectedSession).isInstanceOf(AbstractGemFireOperationsSessionRepository.GemFireSession.class);
|
||||
assertThat(expectedSession).isInstanceOf(
|
||||
AbstractGemFireOperationsSessionRepository.GemFireSession.class);
|
||||
|
||||
((AbstractGemFireOperationsSessionRepository.GemFireSession) expectedSession).setPrincipalName("jblum");
|
||||
((AbstractGemFireOperationsSessionRepository.GemFireSession) expectedSession)
|
||||
.setPrincipalName("jblum");
|
||||
|
||||
List<String> expectedAttributeNames = Arrays.asList(
|
||||
"booleanAttribute", "numericAttribute", "stringAttribute", "personAttribute");
|
||||
List<String> expectedAttributeNames = Arrays.asList("booleanAttribute",
|
||||
"numericAttribute", "stringAttribute", "personAttribute");
|
||||
|
||||
Person jonDoe = new Person("Jon", "Doe");
|
||||
|
||||
@@ -303,21 +335,32 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
|
||||
this.gemfireSessionRepository.save(touch(expectedSession));
|
||||
|
||||
ExpiringSession savedSession = this.gemfireSessionRepository.getSession(expectedSession.getId());
|
||||
ExpiringSession savedSession = this.gemfireSessionRepository
|
||||
.getSession(expectedSession.getId());
|
||||
|
||||
assertThat(savedSession).isEqualTo(expectedSession);
|
||||
assertThat(savedSession).isInstanceOf(AbstractGemFireOperationsSessionRepository.GemFireSession.class);
|
||||
assertThat(((AbstractGemFireOperationsSessionRepository.GemFireSession) savedSession).getPrincipalName()).isEqualTo("jblum");
|
||||
assertThat(savedSession).isInstanceOf(
|
||||
AbstractGemFireOperationsSessionRepository.GemFireSession.class);
|
||||
assertThat(
|
||||
((AbstractGemFireOperationsSessionRepository.GemFireSession) savedSession)
|
||||
.getPrincipalName()).isEqualTo("jblum");
|
||||
|
||||
assertThat(savedSession.getAttributeNames().containsAll(expectedAttributeNames)).as(
|
||||
String.format("Expected (%1$s); but was (%2$s)", expectedAttributeNames, savedSession.getAttributeNames()))
|
||||
assertThat(savedSession.getAttributeNames().containsAll(expectedAttributeNames))
|
||||
.as(String.format("Expected (%1$s); but was (%2$s)",
|
||||
expectedAttributeNames, savedSession.getAttributeNames()))
|
||||
.isTrue();
|
||||
|
||||
assertThat(Boolean.valueOf(String.valueOf(savedSession.getAttribute(expectedAttributeNames.get(0))))).isTrue();
|
||||
assertThat(Double.valueOf(String.valueOf(savedSession.getAttribute(expectedAttributeNames.get(1)))))
|
||||
assertThat(Boolean.valueOf(
|
||||
String.valueOf(savedSession.getAttribute(expectedAttributeNames.get(0)))))
|
||||
.isTrue();
|
||||
assertThat(Double.valueOf(
|
||||
String.valueOf(savedSession.getAttribute(expectedAttributeNames.get(1)))))
|
||||
.isEqualTo(Math.PI);
|
||||
assertThat(String.valueOf(savedSession.getAttribute(expectedAttributeNames.get(2)))).isEqualTo("test");
|
||||
assertThat(savedSession.getAttribute(expectedAttributeNames.get(3))).isEqualTo(jonDoe);
|
||||
assertThat(
|
||||
String.valueOf(savedSession.getAttribute(expectedAttributeNames.get(2))))
|
||||
.isEqualTo("test");
|
||||
assertThat(savedSession.getAttribute(expectedAttributeNames.get(3)))
|
||||
.isEqualTo(jonDoe);
|
||||
}
|
||||
|
||||
private String getSecurityName() {
|
||||
@@ -328,15 +371,15 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
return this.changedContext.getAuthentication().getName();
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME,
|
||||
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME, maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
static class SpringSessionGemFireConfiguration {
|
||||
|
||||
@Bean
|
||||
Properties gemfireProperties() {
|
||||
Properties gemfireProperties = new Properties();
|
||||
|
||||
gemfireProperties.setProperty("name", GemFireOperationsSessionRepositoryIntegrationTests.class.getName());
|
||||
gemfireProperties.setProperty("name",
|
||||
GemFireOperationsSessionRepositoryIntegrationTests.class.getName());
|
||||
gemfireProperties.setProperty("mcast-port", "0");
|
||||
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
|
||||
|
||||
@@ -370,7 +413,8 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
}
|
||||
|
||||
private String validate(String value) {
|
||||
Assert.hasText(value, String.format("The String value (%1$s) must be specified!", value));
|
||||
Assert.hasText(value,
|
||||
String.format("The String value (%1$s) must be specified!", value));
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -399,7 +443,8 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
|
||||
@SuppressWarnings("all")
|
||||
public int compareTo(final Person person) {
|
||||
int compareValue = getLastName().compareTo(person.getLastName());
|
||||
return (compareValue != 0 ? compareValue : getFirstName().compareTo(person.getFirstName()));
|
||||
return (compareValue != 0 ? compareValue
|
||||
: getFirstName().compareTo(person.getFirstName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -47,8 +47,9 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* The EnableGemFireHttpSessionEventsIntegrationTests class is a test suite of test cases testing the Session Event
|
||||
* functionality and behavior of the GemFireOperationsSessionRepository and GemFire's configuration.
|
||||
* The EnableGemFireHttpSessionEventsIntegrationTests class is a test suite of test cases
|
||||
* testing the Session Event functionality and behavior of the
|
||||
* GemFireOperationsSessionRepository and GemFire's configuration.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
@@ -70,7 +71,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ContextConfiguration
|
||||
@DirtiesContext
|
||||
@WebAppConfiguration
|
||||
public class EnableGemFireHttpSessionEventsIntegrationTests extends AbstractGemFireIntegrationTests {
|
||||
public class EnableGemFireHttpSessionEventsIntegrationTests
|
||||
extends AbstractGemFireIntegrationTests {
|
||||
|
||||
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 1;
|
||||
|
||||
@@ -84,14 +86,17 @@ public class EnableGemFireHttpSessionEventsIntegrationTests extends AbstractGemF
|
||||
public void setup() {
|
||||
assertThat(GemFireUtils.isPeer(this.gemfireCache)).isTrue();
|
||||
assertThat(this.gemfireSessionRepository).isNotNull();
|
||||
assertThat(this.gemfireSessionRepository.getMaxInactiveIntervalInSeconds()).isEqualTo(
|
||||
MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
assertThat(this.gemfireSessionRepository.getMaxInactiveIntervalInSeconds())
|
||||
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
assertThat(this.sessionEventListener).isNotNull();
|
||||
|
||||
Region<Object, ExpiringSession> sessionRegion = this.gemfireCache.getRegion(SPRING_SESSION_GEMFIRE_REGION_NAME);
|
||||
Region<Object, ExpiringSession> sessionRegion = this.gemfireCache
|
||||
.getRegion(SPRING_SESSION_GEMFIRE_REGION_NAME);
|
||||
|
||||
assertRegion(sessionRegion, SPRING_SESSION_GEMFIRE_REGION_NAME, DataPolicy.REPLICATE);
|
||||
assertEntryIdleTimeout(sessionRegion, ExpirationAction.INVALIDATE, MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
assertRegion(sessionRegion, SPRING_SESSION_GEMFIRE_REGION_NAME,
|
||||
DataPolicy.REPLICATE);
|
||||
assertEntryIdleTimeout(sessionRegion, ExpirationAction.INVALIDATE,
|
||||
MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -113,9 +118,12 @@ public class EnableGemFireHttpSessionEventsIntegrationTests extends AbstractGemF
|
||||
|
||||
assertThat(createdSession).isEqualTo(expectedSession);
|
||||
assertThat(createdSession.getId()).isNotNull();
|
||||
assertThat(createdSession.getCreationTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime);
|
||||
assertThat(createdSession.getLastAccessedTime()).isEqualTo(createdSession.getCreationTime());
|
||||
assertThat(createdSession.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
assertThat(createdSession.getCreationTime())
|
||||
.isGreaterThanOrEqualTo(beforeOrAtCreationTime);
|
||||
assertThat(createdSession.getLastAccessedTime())
|
||||
.isEqualTo(createdSession.getCreationTime());
|
||||
assertThat(createdSession.getMaxInactiveIntervalInSeconds())
|
||||
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
assertThat(createdSession.isExpired()).isFalse();
|
||||
}
|
||||
|
||||
@@ -126,7 +134,8 @@ public class EnableGemFireHttpSessionEventsIntegrationTests extends AbstractGemF
|
||||
assertThat(expectedSession.isExpired()).isFalse();
|
||||
|
||||
// NOTE though unlikely, a possible race condition exists between save and get...
|
||||
ExpiringSession savedSession = this.gemfireSessionRepository.getSession(expectedSession.getId());
|
||||
ExpiringSession savedSession = this.gemfireSessionRepository
|
||||
.getSession(expectedSession.getId());
|
||||
|
||||
assertThat(savedSession).isEqualTo(expectedSession);
|
||||
}
|
||||
@@ -143,18 +152,21 @@ public class EnableGemFireHttpSessionEventsIntegrationTests extends AbstractGemF
|
||||
|
||||
assertThat(createdSession).isEqualTo(expectedSession);
|
||||
assertThat(createdSession.isExpired()).isTrue();
|
||||
assertThat(this.gemfireSessionRepository.getSession(createdSession.getId())).isNull();
|
||||
assertThat(this.gemfireSessionRepository.getSession(createdSession.getId()))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNonExistingSession() {
|
||||
assertThat(this.gemfireSessionRepository.getSession(UUID.randomUUID().toString())).isNull();
|
||||
assertThat(this.gemfireSessionRepository.getSession(UUID.randomUUID().toString()))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteExistingNonExpiredSession() {
|
||||
ExpiringSession expectedSession = save(touch(createSession()));
|
||||
ExpiringSession savedSession = this.gemfireSessionRepository.getSession(expectedSession.getId());
|
||||
ExpiringSession savedSession = this.gemfireSessionRepository
|
||||
.getSession(expectedSession.getId());
|
||||
|
||||
assertThat(savedSession).isEqualTo(expectedSession);
|
||||
assertThat(savedSession.isExpired()).isFalse();
|
||||
@@ -169,7 +181,8 @@ public class EnableGemFireHttpSessionEventsIntegrationTests extends AbstractGemF
|
||||
ExpiringSession deletedSession = sessionEvent.getSession();
|
||||
|
||||
assertThat(deletedSession).isEqualTo(savedSession);
|
||||
assertThat(this.gemfireSessionRepository.getSession(deletedSession.getId())).isNull();
|
||||
assertThat(this.gemfireSessionRepository.getSession(deletedSession.getId()))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -184,8 +197,9 @@ public class EnableGemFireHttpSessionEventsIntegrationTests extends AbstractGemF
|
||||
|
||||
assertThat(createdSession).isEqualTo(expectedSession);
|
||||
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(TimeUnit.SECONDS.toMillis(
|
||||
this.gemfireSessionRepository.getMaxInactiveIntervalInSeconds() + 1));
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(TimeUnit.SECONDS
|
||||
.toMillis(this.gemfireSessionRepository.getMaxInactiveIntervalInSeconds()
|
||||
+ 1));
|
||||
|
||||
assertThat(sessionEvent).isInstanceOf(SessionExpiredEvent.class);
|
||||
|
||||
@@ -201,7 +215,8 @@ public class EnableGemFireHttpSessionEventsIntegrationTests extends AbstractGemF
|
||||
assertThat(sessionEvent).isInstanceOf(SessionDeletedEvent.class);
|
||||
assertThat(sessionEvent.getSession()).isNull();
|
||||
assertThat(sessionEvent.getSessionId()).isEqualTo(expiredSession.getId());
|
||||
assertThat(this.gemfireSessionRepository.getSession(sessionEvent.getSessionId())).isNull();
|
||||
assertThat(this.gemfireSessionRepository.getSession(sessionEvent.getSessionId()))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -219,16 +234,15 @@ public class EnableGemFireHttpSessionEventsIntegrationTests extends AbstractGemF
|
||||
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME,
|
||||
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS,
|
||||
serverRegionShortcut = RegionShortcut.REPLICATE)
|
||||
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME, maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS, serverRegionShortcut = RegionShortcut.REPLICATE)
|
||||
static class SpringSessionGemFireConfiguration {
|
||||
|
||||
@Bean
|
||||
Properties gemfireProperties() {
|
||||
Properties gemfireProperties = new Properties();
|
||||
|
||||
gemfireProperties.setProperty("name", EnableGemFireHttpSessionEventsIntegrationTests.class.getName());
|
||||
gemfireProperties.setProperty("name",
|
||||
EnableGemFireHttpSessionEventsIntegrationTests.class.getName());
|
||||
gemfireProperties.setProperty("mcast-port", "0");
|
||||
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
|
||||
|
||||
|
||||
@@ -42,8 +42,9 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* The GemFireHttpSessionJavaConfigurationTests class is a test suite of test cases testing the configuration of
|
||||
* Spring Session backed by GemFire using Java-based configuration meta-data.
|
||||
* The GemFireHttpSessionJavaConfigurationTests class is a test suite of test cases
|
||||
* testing the configuration of Spring Session backed by GemFire using Java-based
|
||||
* configuration meta-data.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
@@ -61,12 +62,14 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ContextConfiguration
|
||||
@DirtiesContext
|
||||
@WebAppConfiguration
|
||||
public class GemFireHttpSessionJavaConfigurationTests extends AbstractGemFireIntegrationTests {
|
||||
public class GemFireHttpSessionJavaConfigurationTests
|
||||
extends AbstractGemFireIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private Cache gemfireCache;
|
||||
|
||||
protected <K, V> Region<K, V> assertCacheAndRegion(Cache gemfireCache, String regionName, DataPolicy dataPolicy) {
|
||||
protected <K, V> Region<K, V> assertCacheAndRegion(Cache gemfireCache,
|
||||
String regionName, DataPolicy dataPolicy) {
|
||||
assertThat(GemFireUtils.isPeer(gemfireCache)).isTrue();
|
||||
|
||||
Region<K, V> region = gemfireCache.getRegion(regionName);
|
||||
@@ -78,16 +81,16 @@ public class GemFireHttpSessionJavaConfigurationTests extends AbstractGemFireInt
|
||||
|
||||
@Test
|
||||
public void gemfireCacheConfigurationIsValid() {
|
||||
Region<Object, ExpiringSession> example = assertCacheAndRegion(this.gemfireCache, "JavaExample",
|
||||
DataPolicy.REPLICATE);
|
||||
Region<Object, ExpiringSession> example = assertCacheAndRegion(this.gemfireCache,
|
||||
"JavaExample", DataPolicy.REPLICATE);
|
||||
|
||||
assertEntryIdleTimeout(example, ExpirationAction.INVALIDATE, 900);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyGemFireExampleCacheRegionPrincipalNameIndexWasCreatedSuccessfully() {
|
||||
Region<Object, ExpiringSession> example = assertCacheAndRegion(this.gemfireCache, "JavaExample",
|
||||
DataPolicy.REPLICATE);
|
||||
Region<Object, ExpiringSession> example = assertCacheAndRegion(this.gemfireCache,
|
||||
"JavaExample", DataPolicy.REPLICATE);
|
||||
|
||||
QueryService queryService = example.getRegionService().getQueryService();
|
||||
|
||||
@@ -100,26 +103,27 @@ public class GemFireHttpSessionJavaConfigurationTests extends AbstractGemFireInt
|
||||
|
||||
@Test
|
||||
public void verifyGemFireExampleCacheRegionSessionAttributesIndexWasNotCreated() {
|
||||
Region<Object, ExpiringSession> example = assertCacheAndRegion(this.gemfireCache, "JavaExample",
|
||||
DataPolicy.REPLICATE);
|
||||
Region<Object, ExpiringSession> example = assertCacheAndRegion(this.gemfireCache,
|
||||
"JavaExample", DataPolicy.REPLICATE);
|
||||
|
||||
QueryService queryService = example.getRegionService().getQueryService();
|
||||
|
||||
assertThat(queryService).isNotNull();
|
||||
|
||||
Index sessionAttributesIndex = queryService.getIndex(example, "sessionAttributesIndex");
|
||||
Index sessionAttributesIndex = queryService.getIndex(example,
|
||||
"sessionAttributesIndex");
|
||||
|
||||
assertThat(sessionAttributesIndex).isNull();
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession(indexableSessionAttributes = {}, maxInactiveIntervalInSeconds = 900,
|
||||
regionName = "JavaExample", serverRegionShortcut = RegionShortcut.REPLICATE)
|
||||
@EnableGemFireHttpSession(indexableSessionAttributes = {}, maxInactiveIntervalInSeconds = 900, regionName = "JavaExample", serverRegionShortcut = RegionShortcut.REPLICATE)
|
||||
public static class GemFireConfiguration {
|
||||
|
||||
@Bean
|
||||
Properties gemfireProperties() {
|
||||
Properties gemfireProperties = new Properties();
|
||||
gemfireProperties.setProperty("name", GemFireHttpSessionJavaConfigurationTests.class.getName());
|
||||
gemfireProperties.setProperty("name",
|
||||
GemFireHttpSessionJavaConfigurationTests.class.getName());
|
||||
gemfireProperties.setProperty("mcast-port", "0");
|
||||
gemfireProperties.setProperty("log-level", "warning");
|
||||
return gemfireProperties;
|
||||
|
||||
@@ -37,8 +37,9 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* The GemFireHttpSessionXmlConfigurationTests class is a test suite of test cases testing the configuration of
|
||||
* Spring Session backed by GemFire using XML configuration meta-data.
|
||||
* The GemFireHttpSessionXmlConfigurationTests class is a test suite of test cases testing
|
||||
* the configuration of Spring Session backed by GemFire using XML configuration
|
||||
* meta-data.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
@@ -56,12 +57,14 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ContextConfiguration
|
||||
@DirtiesContext
|
||||
@WebAppConfiguration
|
||||
public class GemFireHttpSessionXmlConfigurationTests extends AbstractGemFireIntegrationTests {
|
||||
public class GemFireHttpSessionXmlConfigurationTests
|
||||
extends AbstractGemFireIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private Cache gemfireCache;
|
||||
|
||||
protected <K, V> Region<K, V> assertCacheAndRegion(Cache gemfireCache, String regionName, DataPolicy dataPolicy) {
|
||||
protected <K, V> Region<K, V> assertCacheAndRegion(Cache gemfireCache,
|
||||
String regionName, DataPolicy dataPolicy) {
|
||||
assertThat(GemFireUtils.isPeer(gemfireCache)).isTrue();
|
||||
|
||||
Region<K, V> region = gemfireCache.getRegion(regionName);
|
||||
@@ -73,14 +76,16 @@ public class GemFireHttpSessionXmlConfigurationTests extends AbstractGemFireInte
|
||||
|
||||
@Test
|
||||
public void gemfireCacheConfigurationIsValid() {
|
||||
Region<Object, ExpiringSession> example = assertCacheAndRegion(this.gemfireCache, "XmlExample", DataPolicy.NORMAL);
|
||||
Region<Object, ExpiringSession> example = assertCacheAndRegion(this.gemfireCache,
|
||||
"XmlExample", DataPolicy.NORMAL);
|
||||
|
||||
assertEntryIdleTimeout(example, ExpirationAction.INVALIDATE, 3600);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyGemFireExampleCacheRegionPrincipalNameIndexWasCreatedSuccessfully() {
|
||||
Region<Object, ExpiringSession> example = assertCacheAndRegion(this.gemfireCache, "XmlExample", DataPolicy.NORMAL);
|
||||
Region<Object, ExpiringSession> example = assertCacheAndRegion(this.gemfireCache,
|
||||
"XmlExample", DataPolicy.NORMAL);
|
||||
|
||||
QueryService queryService = example.getRegionService().getQueryService();
|
||||
|
||||
@@ -93,13 +98,15 @@ public class GemFireHttpSessionXmlConfigurationTests extends AbstractGemFireInte
|
||||
|
||||
@Test
|
||||
public void verifyGemFireExampleCacheRegionSessionAttributesIndexWasCreatedSuccessfully() {
|
||||
Region<Object, ExpiringSession> example = assertCacheAndRegion(this.gemfireCache, "XmlExample", DataPolicy.NORMAL);
|
||||
Region<Object, ExpiringSession> example = assertCacheAndRegion(this.gemfireCache,
|
||||
"XmlExample", DataPolicy.NORMAL);
|
||||
|
||||
QueryService queryService = example.getRegionService().getQueryService();
|
||||
|
||||
assertThat(queryService).isNotNull();
|
||||
|
||||
Index sessionAttributesIndex = queryService.getIndex(example, "sessionAttributesIndex");
|
||||
Index sessionAttributesIndex = queryService.getIndex(example,
|
||||
"sessionAttributesIndex");
|
||||
|
||||
assertIndex(sessionAttributesIndex, "s.attributes['one', 'two', 'three']",
|
||||
String.format("%1$s s", example.getFullPath()));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,8 +15,14 @@
|
||||
*/
|
||||
package org.springframework.session.data.mongo;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -33,11 +39,6 @@ import org.springframework.session.data.AbstractITests;
|
||||
import org.springframework.session.data.mongo.config.annotation.web.http.EnableMongoHttpSession;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
@@ -57,69 +58,71 @@ public class MongoRepositoryITests extends AbstractITests {
|
||||
public void saves() throws InterruptedException {
|
||||
String username = "saves-" + System.currentTimeMillis();
|
||||
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
String expectedAttributeName = "a";
|
||||
String expectedAttributeValue = "b";
|
||||
toSave.setAttribute(expectedAttributeName, expectedAttributeValue);
|
||||
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username, "password",
|
||||
AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username,
|
||||
"password", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
SecurityContext toSaveContext = SecurityContextHolder.createEmptyContext();
|
||||
toSaveContext.setAuthentication(toSaveToken);
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, toSaveContext);
|
||||
toSave.setAttribute(INDEX_NAME, username);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Session session = repository.getSession(toSave.getId());
|
||||
Session session = this.repository.getSession(toSave.getId());
|
||||
|
||||
assertThat(session.getId()).isEqualTo(toSave.getId());
|
||||
assertThat(session.getAttributeNames()).isEqualTo(toSave.getAttributeNames());
|
||||
assertThat(session.getAttribute(expectedAttributeName)).isEqualTo(toSave.getAttribute(expectedAttributeName));
|
||||
assertThat(session.getAttribute(expectedAttributeName))
|
||||
.isEqualTo(toSave.getAttribute(expectedAttributeName));
|
||||
|
||||
repository.delete(toSave.getId());
|
||||
this.repository.delete(toSave.getId());
|
||||
|
||||
String id = toSave.getId();
|
||||
assertThat(repository.getSession(id)).isNull();
|
||||
assertThat(this.repository.getSession(id)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAllOnSingleAttrDoesNotRemoveOld() {
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute("a", "b");
|
||||
|
||||
repository.save(toSave);
|
||||
toSave = repository.getSession(toSave.getId());
|
||||
this.repository.save(toSave);
|
||||
toSave = this.repository.getSession(toSave.getId());
|
||||
|
||||
toSave.setAttribute("1", "2");
|
||||
|
||||
repository.save(toSave);
|
||||
toSave = repository.getSession(toSave.getId());
|
||||
this.repository.save(toSave);
|
||||
toSave = this.repository.getSession(toSave.getId());
|
||||
|
||||
Session session = repository.getSession(toSave.getId());
|
||||
Session session = this.repository.getSession(toSave.getId());
|
||||
assertThat(session.getAttributeNames().size()).isEqualTo(2);
|
||||
assertThat(session.getAttribute("a")).isEqualTo("b");
|
||||
assertThat(session.getAttribute("1")).isEqualTo("2");
|
||||
|
||||
repository.delete(toSave.getId());
|
||||
this.repository.delete(toSave.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByPrincipalName() throws Exception {
|
||||
String principalName = "findByPrincipalName" + UUID.randomUUID();
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
|
||||
repository.delete(toSave.getId());
|
||||
this.repository.delete(toSave.getId());
|
||||
|
||||
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(0);
|
||||
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
|
||||
@@ -127,17 +130,18 @@ public class MongoRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameNoPrincipalNameChange() throws Exception {
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChange" + UUID.randomUUID();
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChange"
|
||||
+ UUID.randomUUID();
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave.setAttribute("other", "value");
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -145,19 +149,20 @@ public class MongoRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameNoPrincipalNameChangeReload() throws Exception {
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChangeReload" + UUID.randomUUID();
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChangeReload"
|
||||
+ UUID.randomUUID();
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave = repository.getSession(toSave.getId());
|
||||
toSave = this.repository.getSession(toSave.getId());
|
||||
|
||||
toSave.setAttribute("other", "value");
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -166,16 +171,16 @@ public class MongoRepositoryITests extends AbstractITests {
|
||||
@Test
|
||||
public void findByDeletedPrincipalName() throws Exception {
|
||||
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave.setAttribute(INDEX_NAME, null);
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
@@ -184,19 +189,20 @@ public class MongoRepositoryITests extends AbstractITests {
|
||||
public void findByChangedPrincipalName() throws Exception {
|
||||
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave.setAttribute(INDEX_NAME, principalNameChanged);
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalNameChanged);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -205,17 +211,17 @@ public class MongoRepositoryITests extends AbstractITests {
|
||||
@Test
|
||||
public void findByDeletedPrincipalNameReload() throws Exception {
|
||||
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
MongoExpiringSession getSession = repository.getSession(toSave.getId());
|
||||
MongoExpiringSession getSession = this.repository.getSession(toSave.getId());
|
||||
getSession.setAttribute(INDEX_NAME, null);
|
||||
repository.save(getSession);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
@@ -224,21 +230,22 @@ public class MongoRepositoryITests extends AbstractITests {
|
||||
public void findByChangedPrincipalNameReload() throws Exception {
|
||||
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
MongoExpiringSession getSession = repository.getSession(toSave.getId());
|
||||
MongoExpiringSession getSession = this.repository.getSession(toSave.getId());
|
||||
|
||||
getSession.setAttribute(INDEX_NAME, principalNameChanged);
|
||||
repository.save(getSession);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalNameChanged);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -246,20 +253,21 @@ public class MongoRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findBySecurityPrincipalName() throws Exception {
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
|
||||
repository.delete(toSave.getId());
|
||||
this.repository.delete(toSave.getId());
|
||||
|
||||
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(0);
|
||||
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
|
||||
@@ -267,35 +275,36 @@ public class MongoRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameNoSecurityPrincipalNameChange() throws Exception {
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave.setAttribute("other", "value");
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameNoSecurityPrincipalNameChangeReload() throws Exception {
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
public void findByPrincipalNameNoSecurityPrincipalNameChangeReload()
|
||||
throws Exception {
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave = repository.getSession(toSave.getId());
|
||||
toSave = this.repository.getSession(toSave.getId());
|
||||
|
||||
toSave.setAttribute("other", "value");
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -303,35 +312,36 @@ public class MongoRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findByDeletedSecurityPrincipalName() throws Exception {
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, null);
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByChangedSecurityPrincipalName() throws Exception {
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, changedContext);
|
||||
repository.save(toSave);
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getChangedSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -339,38 +349,39 @@ public class MongoRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findByDeletedSecurityPrincipalNameReload() throws Exception {
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
MongoExpiringSession getSession = repository.getSession(toSave.getId());
|
||||
MongoExpiringSession getSession = this.repository.getSession(toSave.getId());
|
||||
getSession.setAttribute(INDEX_NAME, null);
|
||||
repository.save(getSession);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getChangedSecurityName());
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByChangedSecurityPrincipalNameReload() throws Exception {
|
||||
MongoExpiringSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
MongoExpiringSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
MongoExpiringSession getSession = repository.getSession(toSave.getId());
|
||||
MongoExpiringSession getSession = this.repository.getSession(toSave.getId());
|
||||
|
||||
getSession.setAttribute(SPRING_SECURITY_CONTEXT, changedContext);
|
||||
repository.save(getSession);
|
||||
getSession.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, MongoExpiringSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getChangedSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -379,22 +390,24 @@ public class MongoRepositoryITests extends AbstractITests {
|
||||
@Test
|
||||
public void loadExpiredSession() throws Exception {
|
||||
// given
|
||||
MongoExpiringSession expiredSession = repository.createSession();
|
||||
long thirtyOneMinutesAgo = System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(31);
|
||||
MongoExpiringSession expiredSession = this.repository.createSession();
|
||||
long thirtyOneMinutesAgo = System.currentTimeMillis()
|
||||
- TimeUnit.MINUTES.toMillis(31);
|
||||
expiredSession.setLastAccessedTime(thirtyOneMinutesAgo);
|
||||
repository.save(expiredSession);
|
||||
this.repository.save(expiredSession);
|
||||
|
||||
// then
|
||||
MongoExpiringSession expiredSessionFromDb = repository.getSession(expiredSession.getId());
|
||||
MongoExpiringSession expiredSessionFromDb = this.repository
|
||||
.getSession(expiredSession.getId());
|
||||
assertThat(expiredSessionFromDb).isNull();
|
||||
}
|
||||
|
||||
private String getSecurityName() {
|
||||
return context.getAuthentication().getName();
|
||||
return this.context.getAuthentication().getName();
|
||||
}
|
||||
|
||||
private String getChangedSecurityName() {
|
||||
return changedContext.getAuthentication().getName();
|
||||
return this.changedContext.getAuthentication().getName();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,12 +15,11 @@
|
||||
*/
|
||||
package org.springframework.session.data.redis;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -42,6 +41,8 @@ import org.springframework.session.events.SessionCreatedEvent;
|
||||
import org.springframework.session.events.SessionDestroyedEvent;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ContextConfiguration
|
||||
public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
|
||||
@@ -58,86 +59,90 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
public void saves() throws InterruptedException {
|
||||
String username = "saves-" + System.currentTimeMillis();
|
||||
|
||||
String usernameSessionKey = "spring:session:RedisOperationsSessionRepositoryITests:index:" + INDEX_NAME + ":"
|
||||
+ username;
|
||||
String usernameSessionKey = "spring:session:RedisOperationsSessionRepositoryITests:index:"
|
||||
+ INDEX_NAME + ":" + username;
|
||||
|
||||
RedisSession toSave = repository.createSession();
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
String expectedAttributeName = "a";
|
||||
String expectedAttributeValue = "b";
|
||||
toSave.setAttribute(expectedAttributeName, expectedAttributeValue);
|
||||
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username, "password",
|
||||
AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username,
|
||||
"password", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
SecurityContext toSaveContext = SecurityContextHolder.createEmptyContext();
|
||||
toSaveContext.setAuthentication(toSaveToken);
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, toSaveContext);
|
||||
toSave.setAttribute(INDEX_NAME, username);
|
||||
registry.clear();
|
||||
this.registry.clear();
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
assertThat(registry.receivedEvent(toSave.getId())).isTrue();
|
||||
assertThat(registry.getEvent(toSave.getId())).isInstanceOf(SessionCreatedEvent.class);
|
||||
assertThat(redis.boundSetOps(usernameSessionKey).members()).contains(toSave.getId());
|
||||
assertThat(this.registry.receivedEvent(toSave.getId())).isTrue();
|
||||
assertThat(this.registry.getEvent(toSave.getId()))
|
||||
.isInstanceOf(SessionCreatedEvent.class);
|
||||
assertThat(this.redis.boundSetOps(usernameSessionKey).members())
|
||||
.contains(toSave.getId());
|
||||
|
||||
Session session = repository.getSession(toSave.getId());
|
||||
Session session = this.repository.getSession(toSave.getId());
|
||||
|
||||
assertThat(session.getId()).isEqualTo(toSave.getId());
|
||||
assertThat(session.getAttributeNames()).isEqualTo(toSave.getAttributeNames());
|
||||
assertThat(session.getAttribute(expectedAttributeName)).isEqualTo(toSave.getAttribute(expectedAttributeName));
|
||||
assertThat(session.getAttribute(expectedAttributeName))
|
||||
.isEqualTo(toSave.getAttribute(expectedAttributeName));
|
||||
|
||||
registry.clear();
|
||||
this.registry.clear();
|
||||
|
||||
repository.delete(toSave.getId());
|
||||
this.repository.delete(toSave.getId());
|
||||
|
||||
assertThat(repository.getSession(toSave.getId())).isNull();
|
||||
assertThat(registry.getEvent(toSave.getId())).isInstanceOf(SessionDestroyedEvent.class);
|
||||
assertThat(redis.boundSetOps(usernameSessionKey).members()).doesNotContain(toSave.getId());
|
||||
assertThat(this.repository.getSession(toSave.getId())).isNull();
|
||||
assertThat(this.registry.getEvent(toSave.getId()))
|
||||
.isInstanceOf(SessionDestroyedEvent.class);
|
||||
assertThat(this.redis.boundSetOps(usernameSessionKey).members())
|
||||
.doesNotContain(toSave.getId());
|
||||
|
||||
assertThat(registry.getEvent(toSave.getId()).getSession().getAttribute(expectedAttributeName))
|
||||
.isEqualTo(expectedAttributeValue);
|
||||
assertThat(this.registry.getEvent(toSave.getId()).getSession()
|
||||
.getAttribute(expectedAttributeName)).isEqualTo(expectedAttributeValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAllOnSingleAttrDoesNotRemoveOld() {
|
||||
RedisSession toSave = repository.createSession();
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute("a", "b");
|
||||
|
||||
repository.save(toSave);
|
||||
toSave = repository.getSession(toSave.getId());
|
||||
this.repository.save(toSave);
|
||||
toSave = this.repository.getSession(toSave.getId());
|
||||
|
||||
toSave.setAttribute("1", "2");
|
||||
|
||||
repository.save(toSave);
|
||||
toSave = repository.getSession(toSave.getId());
|
||||
this.repository.save(toSave);
|
||||
toSave = this.repository.getSession(toSave.getId());
|
||||
|
||||
Session session = repository.getSession(toSave.getId());
|
||||
Session session = this.repository.getSession(toSave.getId());
|
||||
assertThat(session.getAttributeNames().size()).isEqualTo(2);
|
||||
assertThat(session.getAttribute("a")).isEqualTo("b");
|
||||
assertThat(session.getAttribute("1")).isEqualTo("2");
|
||||
|
||||
repository.delete(toSave.getId());
|
||||
this.repository.delete(toSave.getId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void findByPrincipalName() throws Exception {
|
||||
String principalName = "findByPrincipalName" + UUID.randomUUID();
|
||||
RedisSession toSave = repository.createSession();
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
|
||||
repository.delete(toSave.getId());
|
||||
assertThat(registry.receivedEvent(toSave.getId())).isTrue();
|
||||
this.repository.delete(toSave.getId());
|
||||
assertThat(this.registry.receivedEvent(toSave.getId())).isTrue();
|
||||
|
||||
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(0);
|
||||
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
|
||||
@@ -145,20 +150,23 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameExpireRemovesIndex() throws Exception {
|
||||
String principalName = "findByPrincipalNameExpireRemovesIndex" + UUID.randomUUID();
|
||||
RedisSession toSave = repository.createSession();
|
||||
String principalName = "findByPrincipalNameExpireRemovesIndex"
|
||||
+ UUID.randomUUID();
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
String body = "spring:session:RedisOperationsSessionRepositoryITests:sessions:expires:" + toSave.getId();
|
||||
String body = "spring:session:RedisOperationsSessionRepositoryITests:sessions:expires:"
|
||||
+ toSave.getId();
|
||||
String channel = ":expired";
|
||||
DefaultMessage message = new DefaultMessage(channel.getBytes("UTF-8"), body.getBytes("UTF-8"));
|
||||
DefaultMessage message = new DefaultMessage(channel.getBytes("UTF-8"),
|
||||
body.getBytes("UTF-8"));
|
||||
byte[] pattern = new byte[] {};
|
||||
repository.onMessage(message, pattern);
|
||||
this.repository.onMessage(message, pattern);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(0);
|
||||
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
|
||||
@@ -166,17 +174,18 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameNoPrincipalNameChange() throws Exception {
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChange" + UUID.randomUUID();
|
||||
RedisSession toSave = repository.createSession();
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChange"
|
||||
+ UUID.randomUUID();
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave.setAttribute("other", "value");
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -184,19 +193,20 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameNoPrincipalNameChangeReload() throws Exception {
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChangeReload" + UUID.randomUUID();
|
||||
RedisSession toSave = repository.createSession();
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChangeReload"
|
||||
+ UUID.randomUUID();
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave = repository.getSession(toSave.getId());
|
||||
toSave = this.repository.getSession(toSave.getId());
|
||||
|
||||
toSave.setAttribute("other", "value");
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -205,16 +215,16 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
@Test
|
||||
public void findByDeletedPrincipalName() throws Exception {
|
||||
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
|
||||
RedisSession toSave = repository.createSession();
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave.setAttribute(INDEX_NAME, null);
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
@@ -223,19 +233,20 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
public void findByChangedPrincipalName() throws Exception {
|
||||
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
RedisSession toSave = repository.createSession();
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave.setAttribute(INDEX_NAME, principalNameChanged);
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalNameChanged);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -244,17 +255,17 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
@Test
|
||||
public void findByDeletedPrincipalNameReload() throws Exception {
|
||||
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
|
||||
RedisSession toSave = repository.createSession();
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
RedisSession getSession = repository.getSession(toSave.getId());
|
||||
RedisSession getSession = this.repository.getSession(toSave.getId());
|
||||
getSession.setAttribute(INDEX_NAME, null);
|
||||
repository.save(getSession);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
@@ -263,21 +274,22 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
public void findByChangedPrincipalNameReload() throws Exception {
|
||||
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
RedisSession toSave = repository.createSession();
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
RedisSession getSession = repository.getSession(toSave.getId());
|
||||
RedisSession getSession = this.repository.getSession(toSave.getId());
|
||||
|
||||
getSession.setAttribute(INDEX_NAME, principalNameChanged);
|
||||
repository.save(getSession);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalNameChanged);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -285,21 +297,22 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findBySecurityPrincipalName() throws Exception {
|
||||
RedisSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
|
||||
repository.delete(toSave.getId());
|
||||
assertThat(registry.receivedEvent(toSave.getId())).isTrue();
|
||||
this.repository.delete(toSave.getId());
|
||||
assertThat(this.registry.receivedEvent(toSave.getId())).isTrue();
|
||||
|
||||
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(0);
|
||||
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
|
||||
@@ -307,19 +320,21 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findBySecurityPrincipalNameExpireRemovesIndex() throws Exception {
|
||||
RedisSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
String body = "spring:session:RedisOperationsSessionRepositoryITests:sessions:expires:" + toSave.getId();
|
||||
String body = "spring:session:RedisOperationsSessionRepositoryITests:sessions:expires:"
|
||||
+ toSave.getId();
|
||||
String channel = ":expired";
|
||||
DefaultMessage message = new DefaultMessage(channel.getBytes("UTF-8"), body.getBytes("UTF-8"));
|
||||
DefaultMessage message = new DefaultMessage(channel.getBytes("UTF-8"),
|
||||
body.getBytes("UTF-8"));
|
||||
byte[] pattern = new byte[] {};
|
||||
repository.onMessage(message, pattern);
|
||||
this.repository.onMessage(message, pattern);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(0);
|
||||
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
|
||||
@@ -327,35 +342,36 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameNoSecurityPrincipalNameChange() throws Exception {
|
||||
RedisSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave.setAttribute("other", "value");
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameNoSecurityPrincipalNameChangeReload() throws Exception {
|
||||
RedisSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
public void findByPrincipalNameNoSecurityPrincipalNameChangeReload()
|
||||
throws Exception {
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave = repository.getSession(toSave.getId());
|
||||
toSave = this.repository.getSession(toSave.getId());
|
||||
|
||||
toSave.setAttribute("other", "value");
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -363,35 +379,36 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findByDeletedSecurityPrincipalName() throws Exception {
|
||||
RedisSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, null);
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByChangedSecurityPrincipalName() throws Exception {
|
||||
RedisSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, changedContext);
|
||||
repository.save(toSave);
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getChangedSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -399,49 +416,50 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
|
||||
|
||||
@Test
|
||||
public void findByDeletedSecurityPrincipalNameReload() throws Exception {
|
||||
RedisSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
RedisSession getSession = repository.getSession(toSave.getId());
|
||||
RedisSession getSession = this.repository.getSession(toSave.getId());
|
||||
getSession.setAttribute(INDEX_NAME, null);
|
||||
repository.save(getSession);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getChangedSecurityName());
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByChangedSecurityPrincipalNameReload() throws Exception {
|
||||
RedisSession toSave = repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
|
||||
RedisSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
repository.save(toSave);
|
||||
this.repository.save(toSave);
|
||||
|
||||
RedisSession getSession = repository.getSession(toSave.getId());
|
||||
RedisSession getSession = this.repository.getSession(toSave.getId());
|
||||
|
||||
getSession.setAttribute(SPRING_SECURITY_CONTEXT, changedContext);
|
||||
repository.save(getSession);
|
||||
getSession.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
Map<String, RedisSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getChangedSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
}
|
||||
|
||||
private String getSecurityName() {
|
||||
return context.getAuthentication().getName();
|
||||
return this.context.getAuthentication().getName();
|
||||
}
|
||||
|
||||
private String getChangedSecurityName() {
|
||||
return changedContext.getAuthentication().getName();
|
||||
return this.changedContext.getAuthentication().getName();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -62,7 +62,8 @@ public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Expirin
|
||||
public void expireFiresSessionExpiredEvent() throws InterruptedException {
|
||||
S toSave = this.repository.createSession();
|
||||
toSave.setAttribute("a", "b");
|
||||
Authentication toSaveToken = new UsernamePasswordAuthenticationToken("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
Authentication toSaveToken = new UsernamePasswordAuthenticationToken("user",
|
||||
"password", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
SecurityContext toSaveContext = SecurityContextHolder.createEmptyContext();
|
||||
toSaveContext.setAuthentication(toSaveToken);
|
||||
toSave.setAttribute("SPRING_SECURITY_CONTEXT", toSaveContext);
|
||||
@@ -86,7 +87,8 @@ public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Expirin
|
||||
assertThat(this.registry.receivedEvent()).isTrue();
|
||||
}
|
||||
|
||||
static class SessionExpiredEventRegistry implements ApplicationListener<SessionExpiredEvent> {
|
||||
static class SessionExpiredEventRegistry
|
||||
implements ApplicationListener<SessionExpiredEvent> {
|
||||
private boolean receivedEvent;
|
||||
private Object lock;
|
||||
|
||||
|
||||
@@ -53,9 +53,10 @@ public class RedisListenerContainerTaskExecutorITests {
|
||||
RedisOperations<Object, Object> redis;
|
||||
|
||||
@Test
|
||||
public void testRedisDelEventsAreDispatchedInSessionTaskExecutor() throws InterruptedException {
|
||||
BoundSetOperations<Object, Object> ops = this.redis
|
||||
.boundSetOps("spring:session:RedisListenerContainerTaskExecutorITests:expirations:dummy");
|
||||
public void testRedisDelEventsAreDispatchedInSessionTaskExecutor()
|
||||
throws InterruptedException {
|
||||
BoundSetOperations<Object, Object> ops = this.redis.boundSetOps(
|
||||
"spring:session:RedisListenerContainerTaskExecutorITests:expirations:dummy");
|
||||
ops.add("value");
|
||||
ops.remove("value");
|
||||
assertThat(this.executor.taskDispatched()).isTrue();
|
||||
|
||||
@@ -33,8 +33,8 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
/**
|
||||
* Integration tests that check the underlying data source - in this case
|
||||
* Hazelcast Client.
|
||||
* Integration tests that check the underlying data source - in this case Hazelcast
|
||||
* Client.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @author Artem Bilan
|
||||
@@ -50,7 +50,6 @@ public class HazelcastClientRepositoryITests<S extends ExpiringSession>
|
||||
|
||||
private static HazelcastInstance hazelcastInstance;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() {
|
||||
hazelcastInstance = HazelcastITestUtils.embeddedHazelcastServer(PORT);
|
||||
@@ -70,8 +69,7 @@ public class HazelcastClientRepositoryITests<S extends ExpiringSession>
|
||||
@Bean
|
||||
public HazelcastInstance embeddedHazelcastClient() {
|
||||
ClientConfig clientConfig = new ClientConfig();
|
||||
clientConfig.getNetworkConfig()
|
||||
.addAddress("127.0.0.1:" + PORT);
|
||||
clientConfig.getNetworkConfig().addAddress("127.0.0.1:" + PORT);
|
||||
return HazelcastClient.newHazelcastClient(clientConfig);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,7 @@ public final class HazelcastITestUtils {
|
||||
*/
|
||||
public static HazelcastInstance embeddedHazelcastServer(int port) {
|
||||
Config config = new Config();
|
||||
config.getNetworkConfig()
|
||||
.setPort(port);
|
||||
config.getNetworkConfig().setPort(port);
|
||||
return Hazelcast.newHazelcastInstance(config);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests that check the underlying data source - in this case
|
||||
* Hazelcast Server.
|
||||
* Integration tests that check the underlying data source - in this case Hazelcast
|
||||
* Server.
|
||||
*
|
||||
* @author Tommy Ludwig
|
||||
* @author Vedran Pavic
|
||||
|
||||
@@ -45,9 +45,9 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Ensure that the appropriate SessionEvents are fired at the expected times.
|
||||
* Additionally ensure that the interactions with the {@link SessionRepository}
|
||||
* abstraction behave as expected after each SessionEvent.
|
||||
* Ensure that the appropriate SessionEvents are fired at the expected times. Additionally
|
||||
* ensure that the interactions with the {@link SessionRepository} abstraction behave as
|
||||
* expected after each SessionEvent.
|
||||
*
|
||||
* @author Tommy Ludwig
|
||||
*/
|
||||
@@ -78,22 +78,27 @@ public class EnableHazelcastHttpSessionEventsTests<S extends ExpiringSession> {
|
||||
String expectedAttributeName = "a";
|
||||
String expectedAttributeValue = "b";
|
||||
sessionToSave.setAttribute(expectedAttributeName, expectedAttributeValue);
|
||||
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username, "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username,
|
||||
"password", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
SecurityContext toSaveContext = SecurityContextHolder.createEmptyContext();
|
||||
toSaveContext.setAuthentication(toSaveToken);
|
||||
sessionToSave.setAttribute("SPRING_SECURITY_CONTEXT", toSaveContext);
|
||||
sessionToSave.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
|
||||
sessionToSave.setAttribute(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
|
||||
|
||||
this.repository.save(sessionToSave);
|
||||
|
||||
assertThat(this.registry.receivedEvent(sessionToSave.getId())).isTrue();
|
||||
assertThat(this.registry.getEvent(sessionToSave.getId())).isInstanceOf(SessionCreatedEvent.class);
|
||||
assertThat(this.registry.getEvent(sessionToSave.getId()))
|
||||
.isInstanceOf(SessionCreatedEvent.class);
|
||||
|
||||
Session session = this.repository.getSession(sessionToSave.getId());
|
||||
|
||||
assertThat(session.getId()).isEqualTo(sessionToSave.getId());
|
||||
assertThat(session.getAttributeNames()).isEqualTo(sessionToSave.getAttributeNames());
|
||||
assertThat(session.getAttribute(expectedAttributeName)).isEqualTo(sessionToSave.getAttribute(expectedAttributeName));
|
||||
assertThat(session.getAttributeNames())
|
||||
.isEqualTo(sessionToSave.getAttributeNames());
|
||||
assertThat(session.getAttribute(expectedAttributeName))
|
||||
.isEqualTo(sessionToSave.getAttribute(expectedAttributeName));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -103,13 +108,16 @@ public class EnableHazelcastHttpSessionEventsTests<S extends ExpiringSession> {
|
||||
this.repository.save(sessionToSave);
|
||||
|
||||
assertThat(this.registry.receivedEvent(sessionToSave.getId())).isTrue();
|
||||
assertThat(this.registry.getEvent(sessionToSave.getId())).isInstanceOf(SessionCreatedEvent.class);
|
||||
assertThat(this.registry.getEvent(sessionToSave.getId()))
|
||||
.isInstanceOf(SessionCreatedEvent.class);
|
||||
this.registry.clear();
|
||||
|
||||
assertThat(sessionToSave.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
assertThat(sessionToSave.getMaxInactiveIntervalInSeconds())
|
||||
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
|
||||
assertThat(this.registry.receivedEvent(sessionToSave.getId())).isTrue();
|
||||
assertThat(this.registry.getEvent(sessionToSave.getId())).isInstanceOf(SessionExpiredEvent.class);
|
||||
assertThat(this.registry.getEvent(sessionToSave.getId()))
|
||||
.isInstanceOf(SessionExpiredEvent.class);
|
||||
|
||||
assertThat(this.repository.getSession(sessionToSave.getId())).isNull();
|
||||
}
|
||||
@@ -121,13 +129,15 @@ public class EnableHazelcastHttpSessionEventsTests<S extends ExpiringSession> {
|
||||
this.repository.save(sessionToSave);
|
||||
|
||||
assertThat(this.registry.receivedEvent(sessionToSave.getId())).isTrue();
|
||||
assertThat(this.registry.getEvent(sessionToSave.getId())).isInstanceOf(SessionCreatedEvent.class);
|
||||
assertThat(this.registry.getEvent(sessionToSave.getId()))
|
||||
.isInstanceOf(SessionCreatedEvent.class);
|
||||
this.registry.clear();
|
||||
|
||||
this.repository.delete(sessionToSave.getId());
|
||||
|
||||
assertThat(this.registry.receivedEvent(sessionToSave.getId())).isTrue();
|
||||
assertThat(this.registry.getEvent(sessionToSave.getId())).isInstanceOf(SessionDeletedEvent.class);
|
||||
assertThat(this.registry.getEvent(sessionToSave.getId()))
|
||||
.isInstanceOf(SessionDeletedEvent.class);
|
||||
|
||||
assertThat(this.repository.getSession(sessionToSave.getId())).isNull();
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ import org.springframework.util.SocketUtils;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Test the different configuration options for the
|
||||
* {@link EnableHazelcastHttpSession} annotation.
|
||||
* Test the different configuration options for the {@link EnableHazelcastHttpSession}
|
||||
* annotation.
|
||||
*
|
||||
* @author Tommy Ludwig
|
||||
*/
|
||||
|
||||
@@ -73,24 +73,27 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.context = SecurityContextHolder.createEmptyContext();
|
||||
this.context.setAuthentication(new UsernamePasswordAuthenticationToken(
|
||||
"username-" + UUID.randomUUID(), "na", AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
this.context.setAuthentication(
|
||||
new UsernamePasswordAuthenticationToken("username-" + UUID.randomUUID(),
|
||||
"na", AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
|
||||
this.changedContext = SecurityContextHolder.createEmptyContext();
|
||||
this.changedContext.setAuthentication(new UsernamePasswordAuthenticationToken(
|
||||
"changedContext-" + UUID.randomUUID(), "na", AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
"changedContext-" + UUID.randomUUID(), "na",
|
||||
AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saves() throws InterruptedException {
|
||||
String username = "saves-" + System.currentTimeMillis();
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
String expectedAttributeName = "a";
|
||||
String expectedAttributeValue = "b";
|
||||
toSave.setAttribute(expectedAttributeName, expectedAttributeValue);
|
||||
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username, "password",
|
||||
AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username,
|
||||
"password", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
SecurityContext toSaveContext = SecurityContextHolder.createEmptyContext();
|
||||
toSaveContext.setAuthentication(toSaveToken);
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, toSaveContext);
|
||||
@@ -102,7 +105,8 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
|
||||
assertThat(session.getId()).isEqualTo(toSave.getId());
|
||||
assertThat(session.getAttributeNames()).isEqualTo(toSave.getAttributeNames());
|
||||
assertThat(session.getAttribute(expectedAttributeName)).isEqualTo(toSave.getAttribute(expectedAttributeName));
|
||||
assertThat(session.getAttribute(expectedAttributeName))
|
||||
.isEqualTo(toSave.getAttribute(expectedAttributeName));
|
||||
|
||||
this.repository.delete(toSave.getId());
|
||||
|
||||
@@ -111,7 +115,8 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
public void putAllOnSingleAttrDoesNotRemoveOld() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute("a", "b");
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -133,20 +138,22 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
@Test
|
||||
public void findByPrincipalName() throws Exception {
|
||||
String principalName = "findByPrincipalName" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
|
||||
this.repository.delete(toSave.getId());
|
||||
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(0);
|
||||
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
|
||||
@@ -154,17 +161,19 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameExpireRemovesIndex() throws Exception {
|
||||
String principalName = "findByPrincipalNameExpireRemovesIndex" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
String principalName = "findByPrincipalNameExpireRemovesIndex"
|
||||
+ UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
toSave.setLastAccessedTime(System.currentTimeMillis() -
|
||||
(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS * 1000 + 1000));
|
||||
toSave.setLastAccessedTime(System.currentTimeMillis()
|
||||
- (MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS * 1000 + 1000));
|
||||
|
||||
this.repository.save(toSave);
|
||||
this.repository.cleanUpExpiredSessions();
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(0);
|
||||
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
|
||||
@@ -172,8 +181,10 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameNoPrincipalNameChange() throws Exception {
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChange" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChange"
|
||||
+ UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -181,8 +192,8 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute("other", "value");
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -190,8 +201,10 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameNoPrincipalNameChangeReload() throws Exception {
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChangeReload" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChangeReload"
|
||||
+ UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -201,8 +214,8 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute("other", "value");
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -211,7 +224,8 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
@Test
|
||||
public void findByDeletedPrincipalName() throws Exception {
|
||||
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -219,8 +233,8 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute(INDEX_NAME, null);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
@@ -229,7 +243,8 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
public void findByChangedPrincipalName() throws Exception {
|
||||
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -237,11 +252,12 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute(INDEX_NAME, principalNameChanged);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalNameChanged);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -250,17 +266,19 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
@Test
|
||||
public void findByDeletedPrincipalNameReload() throws Exception {
|
||||
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession getSession = this.repository.getSession(toSave.getId());
|
||||
JdbcOperationsSessionRepository.JdbcSession getSession = this.repository
|
||||
.getSession(toSave.getId());
|
||||
getSession.setAttribute(INDEX_NAME, null);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
@@ -269,21 +287,24 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
public void findByChangedPrincipalNameReload() throws Exception {
|
||||
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession getSession = this.repository.getSession(toSave.getId());
|
||||
JdbcOperationsSessionRepository.JdbcSession getSession = this.repository
|
||||
.getSession(toSave.getId());
|
||||
|
||||
getSession.setAttribute(INDEX_NAME, principalNameChanged);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalNameChanged);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -291,20 +312,22 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
public void findBySecurityPrincipalName() throws Exception {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
|
||||
this.repository.delete(toSave.getId());
|
||||
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(0);
|
||||
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
|
||||
@@ -312,16 +335,17 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
public void findBySecurityPrincipalNameExpireRemovesIndex() throws Exception {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
toSave.setLastAccessedTime(System.currentTimeMillis() -
|
||||
(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS * 1000 + 1000));
|
||||
toSave.setLastAccessedTime(System.currentTimeMillis()
|
||||
- (MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS * 1000 + 1000));
|
||||
|
||||
this.repository.save(toSave);
|
||||
this.repository.cleanUpExpiredSessions();
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(0);
|
||||
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
|
||||
@@ -329,7 +353,8 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameNoSecurityPrincipalNameChange() throws Exception {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -337,16 +362,18 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute("other", "value");
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameNoSecurityPrincipalNameChangeReload() throws Exception {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
public void findByPrincipalNameNoSecurityPrincipalNameChangeReload()
|
||||
throws Exception {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -356,8 +383,8 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute("other", "value");
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -365,7 +392,8 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
public void findByDeletedSecurityPrincipalName() throws Exception {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -373,15 +401,16 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, null);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByChangedSecurityPrincipalName() throws Exception {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -389,11 +418,12 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getChangedSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -401,38 +431,43 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
public void findByDeletedSecurityPrincipalNameReload() throws Exception {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession getSession = this.repository.getSession(toSave.getId());
|
||||
JdbcOperationsSessionRepository.JdbcSession getSession = this.repository
|
||||
.getSession(toSave.getId());
|
||||
getSession.setAttribute(INDEX_NAME, null);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByChangedSecurityPrincipalNameReload() throws Exception {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
|
||||
.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession getSession = this.repository.getSession(toSave.getId());
|
||||
JdbcOperationsSessionRepository.JdbcSession getSession = this.repository
|
||||
.getSession(toSave.getId());
|
||||
|
||||
getSession.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
|
||||
repository.save(getSession);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName =
|
||||
this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getChangedSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -452,10 +487,8 @@ public class JdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Bean
|
||||
public EmbeddedDatabase dataSource() {
|
||||
return new EmbeddedDatabaseBuilder()
|
||||
.setType(EmbeddedDatabaseType.H2)
|
||||
.addScript("org/springframework/session/jdbc/schema-h2.sql")
|
||||
.build();
|
||||
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2)
|
||||
.addScript("org/springframework/session/jdbc/schema-h2.sql").build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
package org.springframework.session;
|
||||
|
||||
/**
|
||||
* A {@link Session} that contains additional attributes that are useful for determining if a session is expired.
|
||||
* A {@link Session} that contains additional attributes that are useful for determining
|
||||
* if a session is expired.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 1.0
|
||||
@@ -25,37 +26,47 @@ package org.springframework.session;
|
||||
public interface ExpiringSession extends Session {
|
||||
|
||||
/**
|
||||
* Gets the time when this session was created in milliseconds since midnight of 1/1/1970 GMT.
|
||||
* Gets the time when this session was created in milliseconds since midnight of
|
||||
* 1/1/1970 GMT.
|
||||
*
|
||||
* @return the time when this session was created in milliseconds since midnight of 1/1/1970 GMT.
|
||||
* @return the time when this session was created in milliseconds since midnight of
|
||||
* 1/1/1970 GMT.
|
||||
*/
|
||||
long getCreationTime();
|
||||
|
||||
/**
|
||||
* Sets the last accessed time in milliseconds since midnight of 1/1/1970 GMT.
|
||||
*
|
||||
* @param lastAccessedTime the last accessed time in milliseconds since midnight of 1/1/1970 GMT
|
||||
* @param lastAccessedTime the last accessed time in milliseconds since midnight of
|
||||
* 1/1/1970 GMT
|
||||
*/
|
||||
void setLastAccessedTime(long lastAccessedTime);
|
||||
|
||||
/**
|
||||
* Gets the last time this {@link Session} was accessed expressed in milliseconds since midnight of 1/1/1970 GMT.
|
||||
* Gets the last time this {@link Session} was accessed expressed in milliseconds
|
||||
* since midnight of 1/1/1970 GMT.
|
||||
*
|
||||
* @return the last time the client sent a request associated with the session expressed in milliseconds since midnight of 1/1/1970 GMT
|
||||
* @return the last time the client sent a request associated with the session
|
||||
* expressed in milliseconds since midnight of 1/1/1970 GMT
|
||||
*/
|
||||
long getLastAccessedTime();
|
||||
|
||||
/**
|
||||
* Sets the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout.
|
||||
* Sets the maximum inactive interval in seconds between requests before this session
|
||||
* will be invalidated. A negative time indicates that the session will never timeout.
|
||||
*
|
||||
* @param interval the number of seconds that the {@link Session} should be kept alive between client requests.
|
||||
* @param interval the number of seconds that the {@link Session} should be kept alive
|
||||
* between client requests.
|
||||
*/
|
||||
void setMaxInactiveIntervalInSeconds(int interval);
|
||||
|
||||
/**
|
||||
* Gets the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout.
|
||||
* Gets the maximum inactive interval in seconds between requests before this session
|
||||
* will be invalidated. A negative time indicates that the session will never timeout.
|
||||
*
|
||||
* @return the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout.
|
||||
* @return the maximum inactive interval in seconds between requests before this
|
||||
* session will be invalidated. A negative time indicates that the session will never
|
||||
* timeout.
|
||||
*/
|
||||
int getMaxInactiveIntervalInSeconds();
|
||||
|
||||
|
||||
@@ -19,16 +19,16 @@ package org.springframework.session;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Extends a basic {@link SessionRepository} to allow finding a session id by
|
||||
* the principal name. The principal name is defined by the {@link Session}
|
||||
* attribute with the name {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME}.
|
||||
* Extends a basic {@link SessionRepository} to allow finding a session id by the
|
||||
* principal name. The principal name is defined by the {@link Session} attribute with the
|
||||
* name {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME}.
|
||||
*
|
||||
* @param <S>
|
||||
* the type of Session being managed by this
|
||||
* @param <S> the type of Session being managed by this
|
||||
* {@link FindByIndexNameSessionRepository}
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public interface FindByIndexNameSessionRepository<S extends Session> extends SessionRepository<S> {
|
||||
public interface FindByIndexNameSessionRepository<S extends Session>
|
||||
extends SessionRepository<S> {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -37,28 +37,27 @@ public interface FindByIndexNameSessionRepository<S extends Session> extends Ses
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It is the responsibility of the developer to ensure the attribute
|
||||
* is populated since Spring Session is not aware of the authentication
|
||||
* mechanism being used.
|
||||
* It is the responsibility of the developer to ensure the attribute is populated
|
||||
* since Spring Session is not aware of the authentication mechanism being used.
|
||||
* </p>
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
String PRINCIPAL_NAME_INDEX_NAME = FindByIndexNameSessionRepository.class.getName().concat(".PRINCIPAL_NAME_INDEX_NAME");
|
||||
String PRINCIPAL_NAME_INDEX_NAME = FindByIndexNameSessionRepository.class.getName()
|
||||
.concat(".PRINCIPAL_NAME_INDEX_NAME");
|
||||
|
||||
/**
|
||||
* Find a Map of the session id to the {@link Session} of all sessions that
|
||||
* contain the session attribute with the name
|
||||
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME} and
|
||||
* the value of the specified principal name.
|
||||
* Find a Map of the session id to the {@link Session} of all sessions that contain
|
||||
* the session attribute with the name
|
||||
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME} and the value of
|
||||
* the specified principal name.
|
||||
*
|
||||
* @param indexName
|
||||
* the name if the index (i.e. {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME})
|
||||
* @param indexName the name if the index (i.e.
|
||||
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME})
|
||||
* @param indexValue the value of the index to search for.
|
||||
* @return a Map (never null) of the session id to the {@link Session} of
|
||||
* all sessions that contain the session specified index name and
|
||||
* the value of the specified index name. If no results are found,
|
||||
* an empty Map is returned.
|
||||
* @return a Map (never null) of the session id to the {@link Session} of all sessions
|
||||
* that contain the session specified index name and the value of the specified index
|
||||
* name. If no results are found, an empty Map is returned.
|
||||
*/
|
||||
Map<String, S> findByIndexNameAndIndexValue(String indexName, String indexValue);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A {@link Session} implementation that is backed by a {@link java.util.Map}. The defaults for the properties are:
|
||||
* A {@link Session} implementation that is backed by a {@link java.util.Map}. The
|
||||
* defaults for the properties are:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>id - a secure random generated id</li>
|
||||
@@ -35,7 +36,8 @@ import java.util.concurrent.TimeUnit;
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* This implementation has no synchronization, so it is best to use the copy constructor when working on multiple threads.
|
||||
* This implementation has no synchronization, so it is best to use the copy constructor
|
||||
* when working on multiple threads.
|
||||
* </p>
|
||||
*
|
||||
* @author Rob Winch
|
||||
@@ -65,9 +67,9 @@ public final class MapSession implements ExpiringSession, Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with the specified id. This is preferred to the
|
||||
* default constructor when the id is known to prevent unnecessary consumption on
|
||||
* entropy which can be slow.
|
||||
* Creates a new instance with the specified id. This is preferred to the default
|
||||
* constructor when the id is known to prevent unnecessary consumption on entropy
|
||||
* which can be slow.
|
||||
*
|
||||
* @param id the identifier to use
|
||||
*/
|
||||
@@ -78,14 +80,16 @@ public final class MapSession implements ExpiringSession, Serializable {
|
||||
/**
|
||||
* Creates a new instance from the provided {@link Session}.
|
||||
*
|
||||
* @param session the {@link Session} to initialize this {@link Session} with. Cannot be null.
|
||||
* @param session the {@link Session} to initialize this {@link Session} with. Cannot
|
||||
* be null.
|
||||
*/
|
||||
public MapSession(ExpiringSession session) {
|
||||
if (session == null) {
|
||||
throw new IllegalArgumentException("session cannot be null");
|
||||
}
|
||||
this.id = session.getId();
|
||||
this.sessionAttrs = new HashMap<String, Object>(session.getAttributeNames().size());
|
||||
this.sessionAttrs = new HashMap<String, Object>(
|
||||
session.getAttributeNames().size());
|
||||
for (String attrName : session.getAttributeNames()) {
|
||||
Object attrValue = session.getAttribute(attrName);
|
||||
this.sessionAttrs.put(attrName, attrValue);
|
||||
@@ -127,7 +131,8 @@ public final class MapSession implements ExpiringSession, Serializable {
|
||||
if (this.maxInactiveInterval < 0) {
|
||||
return false;
|
||||
}
|
||||
return now - TimeUnit.SECONDS.toMillis(this.maxInactiveInterval) >= this.lastAccessedTime;
|
||||
return now - TimeUnit.SECONDS
|
||||
.toMillis(this.maxInactiveInterval) >= this.lastAccessedTime;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -153,15 +158,19 @@ public final class MapSession implements ExpiringSession, Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time that this {@link Session} was created in milliseconds since midnight of 1/1/1970 GMT. The default is when the {@link Session} was instantiated.
|
||||
* @param creationTime the time that this {@link Session} was created in milliseconds since midnight of 1/1/1970 GMT.
|
||||
* Sets the time that this {@link Session} was created in milliseconds since midnight
|
||||
* of 1/1/1970 GMT. The default is when the {@link Session} was instantiated.
|
||||
* @param creationTime the time that this {@link Session} was created in milliseconds
|
||||
* since midnight of 1/1/1970 GMT.
|
||||
*/
|
||||
public void setCreationTime(long creationTime) {
|
||||
this.creationTime = creationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the identifier for this {@link Session}. The id should be a secure random generated value to prevent malicious users from guessing this value. The default is a secure random generated identifier.
|
||||
* Sets the identifier for this {@link Session}. The id should be a secure random
|
||||
* generated value to prevent malicious users from guessing this value. The default is
|
||||
* a secure random generated identifier.
|
||||
*
|
||||
* @param id the identifier for this session.
|
||||
*/
|
||||
|
||||
@@ -23,12 +23,14 @@ import org.springframework.session.events.SessionDeletedEvent;
|
||||
import org.springframework.session.events.SessionExpiredEvent;
|
||||
|
||||
/**
|
||||
* A {@link SessionRepository} backed by a {@link java.util.Map} and that uses a {@link MapSession}. By default a
|
||||
* {@link java.util.concurrent.ConcurrentHashMap} is used, but a custom {@link java.util.Map} can be injected to use
|
||||
* distributed maps provided by NoSQL stores like Redis and Hazelcast.
|
||||
* A {@link SessionRepository} backed by a {@link java.util.Map} and that uses a
|
||||
* {@link MapSession}. By default a {@link java.util.concurrent.ConcurrentHashMap} is
|
||||
* used, but a custom {@link java.util.Map} can be injected to use distributed maps
|
||||
* provided by NoSQL stores like Redis and Hazelcast.
|
||||
*
|
||||
* <p>
|
||||
* The implementation does NOT support firing {@link SessionDeletedEvent} or {@link SessionExpiredEvent}.
|
||||
* The implementation does NOT support firing {@link SessionDeletedEvent} or
|
||||
* {@link SessionExpiredEvent}.
|
||||
* </p>
|
||||
*
|
||||
* @author Rob Winch
|
||||
@@ -36,7 +38,8 @@ import org.springframework.session.events.SessionExpiredEvent;
|
||||
*/
|
||||
public class MapSessionRepository implements SessionRepository<ExpiringSession> {
|
||||
/**
|
||||
* If non-null, this value is used to override {@link ExpiringSession#setMaxInactiveIntervalInSeconds(int)}.
|
||||
* If non-null, this value is used to override
|
||||
* {@link ExpiringSession#setMaxInactiveIntervalInSeconds(int)}.
|
||||
*/
|
||||
private Integer defaultMaxInactiveInterval;
|
||||
|
||||
@@ -50,7 +53,8 @@ public class MapSessionRepository implements SessionRepository<ExpiringSession>
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance backed by the provided {@link java.util.Map}. This allows injecting a distributed {@link java.util.Map}.
|
||||
* Creates a new instance backed by the provided {@link java.util.Map}. This allows
|
||||
* injecting a distributed {@link java.util.Map}.
|
||||
*
|
||||
* @param sessions the {@link java.util.Map} to use. Cannot be null.
|
||||
*/
|
||||
@@ -62,8 +66,10 @@ public class MapSessionRepository implements SessionRepository<ExpiringSession>
|
||||
}
|
||||
|
||||
/**
|
||||
* If non-null, this value is used to override {@link ExpiringSession#setMaxInactiveIntervalInSeconds(int)}.
|
||||
* @param defaultMaxInactiveInterval the number of seconds that the {@link Session} should be kept alive between client requests.
|
||||
* If non-null, this value is used to override
|
||||
* {@link ExpiringSession#setMaxInactiveIntervalInSeconds(int)}.
|
||||
* @param defaultMaxInactiveInterval the number of seconds that the {@link Session}
|
||||
* should be kept alive between client requests.
|
||||
*/
|
||||
public void setDefaultMaxInactiveInterval(int defaultMaxInactiveInterval) {
|
||||
this.defaultMaxInactiveInterval = Integer.valueOf(defaultMaxInactiveInterval);
|
||||
|
||||
@@ -19,8 +19,8 @@ package org.springframework.session;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Provides a way to identify a user in an agnostic way. This allows the session to be used by an HttpSession, WebSocket
|
||||
* Session, or even non web related sessions.
|
||||
* Provides a way to identify a user in an agnostic way. This allows the session to be
|
||||
* used by an HttpSession, WebSocket Session, or even non web related sessions.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 1.0
|
||||
@@ -35,16 +35,20 @@ public interface Session {
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Gets the Object associated with the specified name or null if no Object is associated to that name.
|
||||
* Gets the Object associated with the specified name or null if no Object is
|
||||
* associated to that name.
|
||||
*
|
||||
* @param attributeName the name of the attribute to get
|
||||
* @return the Object associated with the specified name or null if no Object is associated to that name
|
||||
* @return the Object associated with the specified name or null if no Object is
|
||||
* associated to that name
|
||||
* @param <T> The return type of the attribute
|
||||
*/
|
||||
<T> T getAttribute(String attributeName);
|
||||
|
||||
/**
|
||||
* Gets the attribute names that have a value associated with it. Each value can be passed into {@link org.springframework.session.Session#getAttribute(String)} to obtain the attribute value.
|
||||
* Gets the attribute names that have a value associated with it. Each value can be
|
||||
* passed into {@link org.springframework.session.Session#getAttribute(String)} to
|
||||
* obtain the attribute value.
|
||||
*
|
||||
* @return the attribute names that have a value associated with it.
|
||||
* @see #getAttribute(String)
|
||||
@@ -52,10 +56,13 @@ public interface Session {
|
||||
Set<String> getAttributeNames();
|
||||
|
||||
/**
|
||||
* Sets the attribute value for the provided attribute name. If the attributeValue is null, it has the same result as removing the attribute with {@link org.springframework.session.Session#removeAttribute(String)} .
|
||||
* Sets the attribute value for the provided attribute name. If the attributeValue is
|
||||
* null, it has the same result as removing the attribute with
|
||||
* {@link org.springframework.session.Session#removeAttribute(String)} .
|
||||
*
|
||||
* @param attributeName the attribute name to set
|
||||
* @param attributeValue the value of the attribute to set. If null, the attribute will be removed.
|
||||
* @param attributeValue the value of the attribute to set. If null, the attribute
|
||||
* will be removed.
|
||||
*/
|
||||
void setAttribute(String attributeName, Object attributeValue);
|
||||
|
||||
|
||||
@@ -26,22 +26,28 @@ package org.springframework.session;
|
||||
public interface SessionRepository<S extends Session> {
|
||||
|
||||
/**
|
||||
* Creates a new {@link Session} that is capable of being persisted by this {@link SessionRepository}.
|
||||
* Creates a new {@link Session} that is capable of being persisted by this
|
||||
* {@link SessionRepository}.
|
||||
*
|
||||
* <p>This allows optimizations and customizations in how the {@link Session} is persisted. For example, the
|
||||
* implementation returned might keep track of the changes ensuring that only the delta needs to be persisted on
|
||||
* a save.</p>
|
||||
* <p>
|
||||
* This allows optimizations and customizations in how the {@link Session} is
|
||||
* persisted. For example, the implementation returned might keep track of the changes
|
||||
* ensuring that only the delta needs to be persisted on a save.
|
||||
* </p>
|
||||
*
|
||||
* @return a new {@link Session} that is capable of being persisted by this {@link SessionRepository}
|
||||
* @return a new {@link Session} that is capable of being persisted by this
|
||||
* {@link SessionRepository}
|
||||
*/
|
||||
S createSession();
|
||||
|
||||
/**
|
||||
* Ensures the {@link Session} created by {@link org.springframework.session.SessionRepository#createSession()} is saved.
|
||||
* Ensures the {@link Session} created by
|
||||
* {@link org.springframework.session.SessionRepository#createSession()} is saved.
|
||||
*
|
||||
* <p>
|
||||
* Some implementations may choose to save as the {@link Session} is updated by returning a {@link Session} that
|
||||
* immediately persists any changes. In this case, this method may not actually do anything.
|
||||
* Some implementations may choose to save as the {@link Session} is updated by
|
||||
* returning a {@link Session} that immediately persists any changes. In this case,
|
||||
* this method may not actually do anything.
|
||||
* </p>
|
||||
*
|
||||
* @param session the {@link Session} to save
|
||||
@@ -49,15 +55,18 @@ public interface SessionRepository<S extends Session> {
|
||||
void save(S session);
|
||||
|
||||
/**
|
||||
* Gets the {@link Session} by the {@link Session#getId()} or null if no {@link Session} is found.
|
||||
* Gets the {@link Session} by the {@link Session#getId()} or null if no
|
||||
* {@link Session} is found.
|
||||
*
|
||||
* @param id the {@link org.springframework.session.Session#getId()} to lookup
|
||||
* @return the {@link Session} by the {@link Session#getId()} or null if no {@link Session} is found.
|
||||
* @return the {@link Session} by the {@link Session#getId()} or null if no
|
||||
* {@link Session} is found.
|
||||
*/
|
||||
S getSession(String id);
|
||||
|
||||
/**
|
||||
* Deletes the {@link Session} with the given {@link Session#getId()} or does nothing if the {@link Session} is not found.
|
||||
* Deletes the {@link Session} with the given {@link Session#getId()} or does nothing
|
||||
* if the {@link Session} is not found.
|
||||
* @param id the {@link org.springframework.session.Session#getId()} to delete
|
||||
*/
|
||||
void delete(String id);
|
||||
|
||||
@@ -28,10 +28,9 @@ import org.springframework.session.events.SessionDestroyedEvent;
|
||||
|
||||
/**
|
||||
* Add this annotation to an {@code @Configuration} class to expose the
|
||||
* SessionRepositoryFilter as a bean named "springSessionRepositoryFilter" and
|
||||
* backed by a user provided implementation of {@link SessionRepository}. In
|
||||
* order to leverage the annotation, a single {@link SessionRepository} bean
|
||||
* must be provided. For example:
|
||||
* SessionRepositoryFilter as a bean named "springSessionRepositoryFilter" and backed by a
|
||||
* user provided implementation of {@link SessionRepository}. In order to leverage the
|
||||
* annotation, a single {@link SessionRepository} bean must be provided. For example:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
@@ -45,15 +44,13 @@ import org.springframework.session.events.SessionDestroyedEvent;
|
||||
* }
|
||||
*
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
* </code> </pre>
|
||||
*
|
||||
* <p>
|
||||
* It is important to note that no infrastructure for session expirations is
|
||||
* configured for you out of the box. This is because things like session
|
||||
* expiration are highly implementation dependent. This means if you require
|
||||
* cleaning up expired sessions, you are responsible for cleaning up the expired
|
||||
* sessions.
|
||||
* It is important to note that no infrastructure for session expirations is configured
|
||||
* for you out of the box. This is because things like session expiration are highly
|
||||
* implementation dependent. This means if you require cleaning up expired sessions, you
|
||||
* are responsible for cleaning up the expired sessions.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
@@ -61,13 +58,12 @@ import org.springframework.session.events.SessionDestroyedEvent;
|
||||
* </p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>SessionRepositoryFilter - is responsible for wrapping the
|
||||
* HttpServletRequest with an implementation of HttpSession that is backed by a
|
||||
* SessionRepository</li>
|
||||
* <li>SessionEventHttpSessionListenerAdapter - is responsible for translating
|
||||
* Spring Session events into HttpSessionEvent. In order for it to work, the
|
||||
* implementation of SessionRepository you provide must support
|
||||
* {@link SessionCreatedEvent} and {@link SessionDestroyedEvent}.</li>
|
||||
* <li>SessionRepositoryFilter - is responsible for wrapping the HttpServletRequest with
|
||||
* an implementation of HttpSession that is backed by a SessionRepository</li>
|
||||
* <li>SessionEventHttpSessionListenerAdapter - is responsible for translating Spring
|
||||
* Session events into HttpSessionEvent. In order for it to work, the implementation of
|
||||
* SessionRepository you provide must support {@link SessionCreatedEvent} and
|
||||
* {@link SessionDestroyedEvent}.</li>
|
||||
* <li>
|
||||
* </ul>
|
||||
*
|
||||
|
||||
@@ -37,8 +37,8 @@ import org.springframework.session.web.http.SessionEventHttpSessionListenerAdapt
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
|
||||
/**
|
||||
* Configures the basics for setting up Spring Session in a web environment. In
|
||||
* order to use it, you must provide a {@link SessionRepository}. For example:
|
||||
* Configures the basics for setting up Spring Session in a web environment. In order to
|
||||
* use it, you must provide a {@link SessionRepository}. For example:
|
||||
*
|
||||
* <pre>
|
||||
* {@literal @Configuration}
|
||||
@@ -54,11 +54,10 @@ import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* It is important to note that no infrastructure for session expirations is
|
||||
* configured for you out of the box. This is because things like session
|
||||
* expiration are highly implementation dependent. This means if you require
|
||||
* cleaning up expired sessions, you are responsible for cleaning up the expired
|
||||
* sessions.
|
||||
* It is important to note that no infrastructure for session expirations is configured
|
||||
* for you out of the box. This is because things like session expiration are highly
|
||||
* implementation dependent. This means if you require cleaning up expired sessions, you
|
||||
* are responsible for cleaning up the expired sessions.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
@@ -66,13 +65,12 @@ import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
* </p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>SessionRepositoryFilter - is responsible for wrapping the
|
||||
* HttpServletRequest with an implementation of HttpSession that is backed by a
|
||||
* SessionRepository</li>
|
||||
* <li>SessionEventHttpSessionListenerAdapter - is responsible for translating
|
||||
* Spring Session events into HttpSessionEvent. In order for it to work, the
|
||||
* implementation of SessionRepository you provide must support
|
||||
* {@link SessionCreatedEvent} and {@link SessionDestroyedEvent}.</li>
|
||||
* <li>SessionRepositoryFilter - is responsible for wrapping the HttpServletRequest with
|
||||
* an implementation of HttpSession that is backed by a SessionRepository</li>
|
||||
* <li>SessionEventHttpSessionListenerAdapter - is responsible for translating Spring
|
||||
* Session events into HttpSessionEvent. In order for it to work, the implementation of
|
||||
* SessionRepository you provide must support {@link SessionCreatedEvent} and
|
||||
* {@link SessionDestroyedEvent}.</li>
|
||||
* <li>
|
||||
* </ul>
|
||||
*
|
||||
@@ -98,11 +96,14 @@ public class SpringHttpSessionConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(SessionRepository<S> sessionRepository) {
|
||||
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<S>(sessionRepository);
|
||||
public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(
|
||||
SessionRepository<S> sessionRepository) {
|
||||
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<S>(
|
||||
sessionRepository);
|
||||
sessionRepositoryFilter.setServletContext(this.servletContext);
|
||||
if (this.httpSessionStrategy instanceof MultiHttpSessionStrategy) {
|
||||
sessionRepositoryFilter.setHttpSessionStrategy((MultiHttpSessionStrategy) this.httpSessionStrategy);
|
||||
sessionRepositoryFilter.setHttpSessionStrategy(
|
||||
(MultiHttpSessionStrategy) this.httpSessionStrategy);
|
||||
}
|
||||
else {
|
||||
sessionRepositoryFilter.setHttpSessionStrategy(this.httpSessionStrategy);
|
||||
|
||||
@@ -64,8 +64,9 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* AbstractGemFireOperationsSessionRepository is an abstract base class encapsulating functionality common
|
||||
* to all implementations that support SessionRepository operations backed by GemFire.
|
||||
* AbstractGemFireOperationsSessionRepository is an abstract base class encapsulating
|
||||
* functionality common to all implementations that support SessionRepository operations
|
||||
* backed by GemFire.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
@@ -77,11 +78,13 @@ import org.springframework.util.StringUtils;
|
||||
* @see org.springframework.session.ExpiringSession
|
||||
* @see org.springframework.session.FindByIndexNameSessionRepository
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.
|
||||
* GemFireHttpSessionConfiguration
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
* @see com.gemstone.gemfire.cache.util.CacheListenerAdapter
|
||||
*/
|
||||
public abstract class AbstractGemFireOperationsSessionRepository extends CacheListenerAdapter<Object, ExpiringSession>
|
||||
public abstract class AbstractGemFireOperationsSessionRepository
|
||||
extends CacheListenerAdapter<Object, ExpiringSession>
|
||||
implements InitializingBean, FindByIndexNameSessionRepository<ExpiringSession>,
|
||||
ApplicationEventPublisherAware {
|
||||
|
||||
@@ -90,6 +93,7 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
private ApplicationEventPublisher applicationEventPublisher = new ApplicationEventPublisher() {
|
||||
public void publishEvent(ApplicationEvent event) {
|
||||
}
|
||||
|
||||
public void publishEvent(Object event) {
|
||||
}
|
||||
};
|
||||
@@ -101,8 +105,9 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
private String fullyQualifiedRegionName;
|
||||
|
||||
/**
|
||||
* Constructs an instance of AbstractGemFireOperationsSessionRepository with a required GemfireOperations instance
|
||||
* used to perform GemFire data access operations and interactions supporting the SessionRepository operations.
|
||||
* Constructs an instance of AbstractGemFireOperationsSessionRepository with a
|
||||
* required GemfireOperations instance used to perform GemFire data access operations
|
||||
* and interactions supporting the SessionRepository operations.
|
||||
*
|
||||
* @param template the GemfireOperations instance used to interact with GemFire.
|
||||
* @see org.springframework.data.gemfire.GemfireOperations
|
||||
@@ -123,18 +128,23 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ApplicationEventPublisher used to publish Session events corresponding to GemFire cache events.
|
||||
* Sets the ApplicationEventPublisher used to publish Session events corresponding to
|
||||
* GemFire cache events.
|
||||
*
|
||||
* @param applicationEventPublisher the Spring ApplicationEventPublisher used to publish Session-based events.
|
||||
* @param applicationEventPublisher the Spring ApplicationEventPublisher used to
|
||||
* publish Session-based events.
|
||||
* @see org.springframework.context.ApplicationEventPublisher
|
||||
*/
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
|
||||
Assert.notNull(applicationEventPublisher, "ApplicationEventPublisher must not be null");
|
||||
public void setApplicationEventPublisher(
|
||||
ApplicationEventPublisher applicationEventPublisher) {
|
||||
Assert.notNull(applicationEventPublisher,
|
||||
"ApplicationEventPublisher must not be null");
|
||||
this.applicationEventPublisher = applicationEventPublisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ApplicationEventPublisher used to publish Session events corresponding to GemFire cache events.
|
||||
* Gets the ApplicationEventPublisher used to publish Session events corresponding to
|
||||
* GemFire cache events.
|
||||
*
|
||||
* @return the Spring ApplicationEventPublisher used to publish Session-based events.
|
||||
* @see org.springframework.context.ApplicationEventPublisher
|
||||
@@ -144,38 +154,43 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fully-qualified name of the GemFire cache {@link Region} used to store and manage Session data.
|
||||
* Gets the fully-qualified name of the GemFire cache {@link Region} used to store and
|
||||
* manage Session data.
|
||||
*
|
||||
* @return a String indicating the fully qualified name of the GemFire cache {@link Region} used to store
|
||||
* and manage Session data.
|
||||
* @return a String indicating the fully qualified name of the GemFire cache
|
||||
* {@link Region} used to store and manage Session data.
|
||||
*/
|
||||
protected String getFullyQualifiedRegionName() {
|
||||
return this.fullyQualifiedRegionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum interval in seconds in which a Session can remain inactive before it is considered expired.
|
||||
* Sets the maximum interval in seconds in which a Session can remain inactive before
|
||||
* it is considered expired.
|
||||
*
|
||||
* @param maxInactiveIntervalInSeconds an integer value specifying the maximum interval in seconds that a Session
|
||||
* can remain inactive before it is considered expired.
|
||||
* @param maxInactiveIntervalInSeconds an integer value specifying the maximum
|
||||
* interval in seconds that a Session can remain inactive before it is considered
|
||||
* expired.
|
||||
*/
|
||||
public void setMaxInactiveIntervalInSeconds(int maxInactiveIntervalInSeconds) {
|
||||
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum interval in seconds in which a Session can remain inactive before it is considered expired.
|
||||
* Gets the maximum interval in seconds in which a Session can remain inactive before
|
||||
* it is considered expired.
|
||||
*
|
||||
* @return an integer value specifying the maximum interval in seconds that a Session can remain inactive
|
||||
* before it is considered expired.
|
||||
* @return an integer value specifying the maximum interval in seconds that a Session
|
||||
* can remain inactive before it is considered expired.
|
||||
*/
|
||||
public int getMaxInactiveIntervalInSeconds() {
|
||||
return this.maxInactiveIntervalInSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the GemfireOperations (template) used to perform data access operations
|
||||
* and other interactions on the GemFire cache {@link Region} backing this SessionRepository.
|
||||
* Gets a reference to the GemfireOperations (template) used to perform data access
|
||||
* operations and other interactions on the GemFire cache {@link Region} backing this
|
||||
* SessionRepository.
|
||||
*
|
||||
* @return a reference to the GemfireOperations used to interact with GemFire.
|
||||
* @see org.springframework.data.gemfire.GemfireOperations
|
||||
@@ -185,9 +200,10 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method during Spring bean initialization that will capture the fully-qualified name
|
||||
* of the GemFire cache {@link Region} used to manage Session state and register this SessionRepository
|
||||
* as a GemFire {@link com.gemstone.gemfire.cache.CacheListener}.
|
||||
* Callback method during Spring bean initialization that will capture the
|
||||
* fully-qualified name of the GemFire cache {@link Region} used to manage Session
|
||||
* state and register this SessionRepository as a GemFire
|
||||
* {@link com.gemstone.gemfire.cache.CacheListener}.
|
||||
*
|
||||
* @throws Exception if an error occurs during the initialization process.
|
||||
*/
|
||||
@@ -213,7 +229,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method triggered when an entry is created in the GemFire cache {@link Region}.
|
||||
* Callback method triggered when an entry is created in the GemFire cache
|
||||
* {@link Region}.
|
||||
*
|
||||
* @param event an EntryEvent containing the details of the cache operation.
|
||||
* @see com.gemstone.gemfire.cache.EntryEvent
|
||||
@@ -222,12 +239,14 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
@Override
|
||||
public void afterCreate(EntryEvent<Object, ExpiringSession> event) {
|
||||
if (isExpiringSessionOrNull(event.getNewValue())) {
|
||||
handleCreated(event.getKey().toString(), toExpiringSession(event.getNewValue()));
|
||||
handleCreated(event.getKey().toString(),
|
||||
toExpiringSession(event.getNewValue()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method triggered when an entry is destroyed in the GemFire cache {@link Region}.
|
||||
* Callback method triggered when an entry is destroyed in the GemFire cache
|
||||
* {@link Region}.
|
||||
*
|
||||
* @param event an EntryEvent containing the details of the cache operation.
|
||||
* @see com.gemstone.gemfire.cache.EntryEvent
|
||||
@@ -235,11 +254,13 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
*/
|
||||
@Override
|
||||
public void afterDestroy(EntryEvent<Object, ExpiringSession> event) {
|
||||
handleDestroyed(event.getKey().toString(), toExpiringSession(event.getOldValue()));
|
||||
handleDestroyed(event.getKey().toString(),
|
||||
toExpiringSession(event.getOldValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method triggered when an entry is invalidated in the GemFire cache {@link Region}.
|
||||
* Callback method triggered when an entry is invalidated in the GemFire cache
|
||||
* {@link Region}.
|
||||
*
|
||||
* @param event an EntryEvent containing the details of the cache operation.
|
||||
* @see com.gemstone.gemfire.cache.EntryEvent
|
||||
@@ -318,29 +339,34 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
getApplicationEventPublisher().publishEvent(event);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
this.logger.error(String.format("error occurred publishing event (%1$s)", event), t);
|
||||
this.logger.error(
|
||||
String.format("error occurred publishing event (%1$s)", event), t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GemFireSession is a GemFire representation model of a Spring {@link ExpiringSession} for storing and accessing
|
||||
* Session state information in GemFire. This class implements GemFire's {@link DataSerializable} interface
|
||||
* to better handle replication of Session information across the GemFire cluster.
|
||||
* GemFireSession is a GemFire representation model of a Spring
|
||||
* {@link ExpiringSession} for storing and accessing Session state information in
|
||||
* GemFire. This class implements GemFire's {@link DataSerializable} interface to
|
||||
* better handle replication of Session information across the GemFire cluster.
|
||||
*
|
||||
* @see java.lang.Comparable
|
||||
* @see org.springframework.session.ExpiringSession
|
||||
* @see org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes
|
||||
* @see org.springframework.session.data.gemfire.
|
||||
* AbstractGemFireOperationsSessionRepository.GemFireSessionAttributes
|
||||
* @see com.gemstone.gemfire.DataSerializable
|
||||
* @see com.gemstone.gemfire.DataSerializer
|
||||
* @see com.gemstone.gemfire.Delta
|
||||
* @see com.gemstone.gemfire.Instantiator
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class GemFireSession implements Comparable<ExpiringSession>, DataSerializable, Delta, ExpiringSession {
|
||||
public static class GemFireSession implements Comparable<ExpiringSession>,
|
||||
DataSerializable, Delta, ExpiringSession {
|
||||
|
||||
protected static final boolean DEFAULT_ALLOW_JAVA_SERIALIZATION = true;
|
||||
|
||||
protected static final DateFormat TO_STRING_DATE_FORMAT = new SimpleDateFormat("YYYY-MM-dd-HH-mm-ss");
|
||||
protected static final DateFormat TO_STRING_DATE_FORMAT = new SimpleDateFormat(
|
||||
"YYYY-MM-dd-HH-mm-ss");
|
||||
|
||||
protected static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
|
||||
|
||||
@@ -360,7 +386,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
private long creationTime;
|
||||
private long lastAccessedTime;
|
||||
|
||||
private transient final GemFireSessionAttributes sessionAttributes = new GemFireSessionAttributes(this);
|
||||
private transient final GemFireSessionAttributes sessionAttributes = new GemFireSessionAttributes(
|
||||
this);
|
||||
|
||||
private transient final SpelExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
@@ -460,7 +487,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private long idleTimeout(long maxInactiveIntervalInSeconds) {
|
||||
return (System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(maxInactiveIntervalInSeconds));
|
||||
return (System.currentTimeMillis()
|
||||
- TimeUnit.SECONDS.toMillis(maxInactiveIntervalInSeconds));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -475,7 +503,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public synchronized void setMaxInactiveIntervalInSeconds(final int maxInactiveIntervalInSeconds) {
|
||||
public synchronized void setMaxInactiveIntervalInSeconds(
|
||||
final int maxInactiveIntervalInSeconds) {
|
||||
this.delta |= (this.maxInactiveIntervalInSeconds != maxInactiveIntervalInSeconds);
|
||||
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
|
||||
}
|
||||
@@ -498,7 +527,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
Object authentication = getAttribute(SPRING_SECURITY_CONTEXT);
|
||||
|
||||
if (authentication != null) {
|
||||
Expression expression = this.parser.parseExpression("authentication?.name");
|
||||
Expression expression = this.parser
|
||||
.parseExpression("authentication?.name");
|
||||
principalName = expression.getValue(authentication, String.class);
|
||||
}
|
||||
}
|
||||
@@ -514,7 +544,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
out.writeInt(getMaxInactiveIntervalInSeconds());
|
||||
|
||||
String principalName = getPrincipalName();
|
||||
int length = (StringUtils.hasText(principalName) ? principalName.length() : 0);
|
||||
int length = (StringUtils.hasText(principalName) ? principalName.length()
|
||||
: 0);
|
||||
|
||||
out.writeInt(length);
|
||||
|
||||
@@ -533,7 +564,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public synchronized void fromData(DataInput in) throws ClassNotFoundException, IOException {
|
||||
public synchronized void fromData(DataInput in)
|
||||
throws ClassNotFoundException, IOException {
|
||||
this.id = in.readUTF();
|
||||
this.creationTime = in.readLong();
|
||||
setLastAccessedTime(in.readLong());
|
||||
@@ -609,9 +641,11 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public synchronized String toString() {
|
||||
return String.format("{ @type = %1$s, id = %2$s, creationTime = %3$s, lastAccessedTime = %4$s"
|
||||
+ ", maxInactiveIntervalInSeconds = %5$s, principalName = %6$s }", getClass().getName(), getId(),
|
||||
toString(getCreationTime()), toString(getLastAccessedTime()), getMaxInactiveIntervalInSeconds(),
|
||||
return String.format(
|
||||
"{ @type = %1$s, id = %2$s, creationTime = %3$s, lastAccessedTime = %4$s"
|
||||
+ ", maxInactiveIntervalInSeconds = %5$s, principalName = %6$s }",
|
||||
getClass().getName(), getId(), toString(getCreationTime()),
|
||||
toString(getLastAccessedTime()), getMaxInactiveIntervalInSeconds(),
|
||||
getPrincipalName());
|
||||
}
|
||||
|
||||
@@ -622,10 +656,11 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
}
|
||||
|
||||
/**
|
||||
* The GemFireSessionAttributes class is a container for Session attributes that implements both
|
||||
* the {@link DataSerializable} and {@link Delta} GemFire interfaces for efficient storage and distribution
|
||||
* (replication) in GemFire. Additionally, GemFireSessionAttributes extends {@link AbstractMap} providing
|
||||
* {@link Map}-like behavior since attributes of a Session are effectively a name to value mapping.
|
||||
* The GemFireSessionAttributes class is a container for Session attributes that
|
||||
* implements both the {@link DataSerializable} and {@link Delta} GemFire interfaces
|
||||
* for efficient storage and distribution (replication) in GemFire. Additionally,
|
||||
* GemFireSessionAttributes extends {@link AbstractMap} providing {@link Map}-like
|
||||
* behavior since attributes of a Session are effectively a name to value mapping.
|
||||
*
|
||||
* @see java.util.AbstractMap
|
||||
* @see com.gemstone.gemfire.DataSerializable
|
||||
@@ -640,7 +675,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
protected static final boolean DEFAULT_ALLOW_JAVA_SERIALIZATION = true;
|
||||
|
||||
static {
|
||||
Instantiator.register(new Instantiator(GemFireSessionAttributes.class, 800828008) {
|
||||
Instantiator.register(
|
||||
new Instantiator(GemFireSessionAttributes.class, 800828008) {
|
||||
@Override
|
||||
public DataSerializable newInstance() {
|
||||
return new GemFireSessionAttributes();
|
||||
@@ -667,7 +703,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
public void setAttribute(String attributeName, Object attributeValue) {
|
||||
synchronized (this.lock) {
|
||||
if (attributeValue != null) {
|
||||
if (!attributeValue.equals(this.sessionAttributes.put(attributeName, attributeValue))) {
|
||||
if (!attributeValue.equals(
|
||||
this.sessionAttributes.put(attributeName, attributeValue))) {
|
||||
this.sessionAttributeDeltas.put(attributeName, attributeValue);
|
||||
}
|
||||
}
|
||||
@@ -697,7 +734,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
/* (non-Javadoc) */
|
||||
public Set<String> getAttributeNames() {
|
||||
synchronized (this.lock) {
|
||||
return Collections.unmodifiableSet(new HashSet<String>(this.sessionAttributes.keySet()));
|
||||
return Collections.unmodifiableSet(
|
||||
new HashSet<String>(this.sessionAttributes.keySet()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -713,7 +751,10 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
return new AbstractSet<Entry<String, Object>>() {
|
||||
@Override
|
||||
public Iterator<Entry<String, Object>> iterator() {
|
||||
return Collections.unmodifiableMap(GemFireSessionAttributes.this.sessionAttributes).entrySet().iterator();
|
||||
return Collections
|
||||
.unmodifiableMap(
|
||||
GemFireSessionAttributes.this.sessionAttributes)
|
||||
.entrySet().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -736,7 +777,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
public void from(GemFireSessionAttributes sessionAttributes) {
|
||||
synchronized (this.lock) {
|
||||
for (String attributeName : sessionAttributes.getAttributeNames()) {
|
||||
setAttribute(attributeName, sessionAttributes.getAttribute(attributeName));
|
||||
setAttribute(attributeName,
|
||||
sessionAttributes.getAttribute(attributeName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -788,7 +830,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
synchronized (this.lock) {
|
||||
out.writeInt(this.sessionAttributeDeltas.size());
|
||||
|
||||
for (Map.Entry<String, Object> entry : this.sessionAttributeDeltas.entrySet()) {
|
||||
for (Map.Entry<String, Object> entry : this.sessionAttributeDeltas
|
||||
.entrySet()) {
|
||||
out.writeUTF(entry.getKey());
|
||||
writeObject(entry.getValue(), out);
|
||||
}
|
||||
|
||||
@@ -25,31 +25,33 @@ import org.springframework.data.gemfire.GemfireOperations;
|
||||
import org.springframework.session.ExpiringSession;
|
||||
|
||||
/**
|
||||
* The GemFireOperationsSessionRepository class is a Spring SessionRepository implementation that interfaces with
|
||||
* and uses GemFire to back and store Spring Sessions.
|
||||
* The GemFireOperationsSessionRepository class is a Spring SessionRepository
|
||||
* implementation that interfaces with and uses GemFire to back and store Spring Sessions.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
* @see org.springframework.data.gemfire.GemfireOperations
|
||||
* @see org.springframework.session.ExpiringSession
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository
|
||||
* @see org.springframework.session.data.gemfire.
|
||||
* AbstractGemFireOperationsSessionRepository
|
||||
*/
|
||||
public class GemFireOperationsSessionRepository extends AbstractGemFireOperationsSessionRepository {
|
||||
public class GemFireOperationsSessionRepository
|
||||
extends AbstractGemFireOperationsSessionRepository {
|
||||
|
||||
// GemFire OQL query used to lookup Sessions by arbitrary attributes.
|
||||
protected static final String FIND_SESSIONS_BY_INDEX_NAME_VALUE_QUERY =
|
||||
"SELECT s FROM %1$s s WHERE s.attributes['%2$s'] = $1";
|
||||
protected static final String FIND_SESSIONS_BY_INDEX_NAME_VALUE_QUERY = "SELECT s FROM %1$s s WHERE s.attributes['%2$s'] = $1";
|
||||
|
||||
// GemFire OQL query used to look up Sessions by principal name.
|
||||
protected static final String FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY =
|
||||
"SELECT s FROM %1$s s WHERE s.principalName = $1";
|
||||
protected static final String FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY = "SELECT s FROM %1$s s WHERE s.principalName = $1";
|
||||
|
||||
/**
|
||||
* Constructs an instance of GemFireOperationsSessionRepository initialized with the required GemfireOperations
|
||||
* object used to perform data access operations to manage Session state.
|
||||
* Constructs an instance of GemFireOperationsSessionRepository initialized with the
|
||||
* required GemfireOperations object used to perform data access operations to manage
|
||||
* Session state.
|
||||
*
|
||||
* @param template the GemfireOperations object used to access and manage Session state in GemFire.
|
||||
* @param template the GemfireOperations object used to access and manage Session
|
||||
* state in GemFire.
|
||||
* @see org.springframework.data.gemfire.GemfireOperations
|
||||
*/
|
||||
public GemFireOperationsSessionRepository(GemfireOperations template) {
|
||||
@@ -57,20 +59,26 @@ public class GemFireOperationsSessionRepository extends AbstractGemFireOperation
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up all available Sessions with the particular attribute indexed by name having the given value.
|
||||
* Looks up all available Sessions with the particular attribute indexed by name
|
||||
* having the given value.
|
||||
*
|
||||
* @param indexName name of the indexed Session attribute.
|
||||
* (e.g. {@link org.springframework.session.FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME}).
|
||||
* @param indexValue value of the indexed Session attribute to search on (e.g. username).
|
||||
* @param indexName name of the indexed Session attribute. (e.g.
|
||||
* {@link org.springframework.session.FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME}
|
||||
* ).
|
||||
* @param indexValue value of the indexed Session attribute to search on (e.g.
|
||||
* username).
|
||||
* @return a mapping of Session ID to Session instances.
|
||||
* @see org.springframework.session.ExpiringSession
|
||||
* @see java.util.Map
|
||||
* @see #prepareQuery(String)
|
||||
*/
|
||||
public Map<String, ExpiringSession> findByIndexNameAndIndexValue(String indexName, String indexValue) {
|
||||
SelectResults<ExpiringSession> results = getTemplate().find(prepareQuery(indexName), indexValue);
|
||||
public Map<String, ExpiringSession> findByIndexNameAndIndexValue(String indexName,
|
||||
String indexValue) {
|
||||
SelectResults<ExpiringSession> results = getTemplate()
|
||||
.find(prepareQuery(indexName), indexValue);
|
||||
|
||||
Map<String, ExpiringSession> sessions = new HashMap<String, ExpiringSession>(results.size());
|
||||
Map<String, ExpiringSession> sessions = new HashMap<String, ExpiringSession>(
|
||||
results.size());
|
||||
|
||||
for (ExpiringSession session : results.asList()) {
|
||||
sessions.put(session.getId(), session);
|
||||
@@ -80,22 +88,26 @@ public class GemFireOperationsSessionRepository extends AbstractGemFireOperation
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the appropriate GemFire OQL query based on the indexed Session attribute name.
|
||||
* Prepares the appropriate GemFire OQL query based on the indexed Session attribute
|
||||
* name.
|
||||
*
|
||||
* @param indexName a String indicating the name of the indexed Session attribute.
|
||||
* @return an appropriate GemFire OQL statement for querying on a particular indexed Session attribute.
|
||||
* @return an appropriate GemFire OQL statement for querying on a particular indexed
|
||||
* Session attribute.
|
||||
*/
|
||||
protected String prepareQuery(String indexName) {
|
||||
return (PRINCIPAL_NAME_INDEX_NAME.equals(indexName)
|
||||
? String.format(FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY, getFullyQualifiedRegionName())
|
||||
: String.format(FIND_SESSIONS_BY_INDEX_NAME_VALUE_QUERY, getFullyQualifiedRegionName(), indexName));
|
||||
? String.format(FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
|
||||
getFullyQualifiedRegionName())
|
||||
: String.format(FIND_SESSIONS_BY_INDEX_NAME_VALUE_QUERY,
|
||||
getFullyQualifiedRegionName(), indexName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ExpiringSession} instance backed by GemFire.
|
||||
*
|
||||
* @return an instance of {@link ExpiringSession} backed by GemFire.
|
||||
* @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository.GemFireSession#create(int)
|
||||
* @see GemFireSession#create(int)
|
||||
* @see org.springframework.session.ExpiringSession
|
||||
* @see #getMaxInactiveIntervalInSeconds()
|
||||
*/
|
||||
@@ -104,8 +116,8 @@ public class GemFireOperationsSessionRepository extends AbstractGemFireOperation
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a copy of an existing, non-expired {@link ExpiringSession} by ID. If the Session is expired,
|
||||
* then it is deleted.
|
||||
* Gets a copy of an existing, non-expired {@link ExpiringSession} by ID. If the
|
||||
* Session is expired, then it is deleted.
|
||||
*
|
||||
* @param sessionId a String indicating the ID of the Session to get.
|
||||
* @return an existing {@link ExpiringSession} by ID or null if not Session exists.
|
||||
@@ -140,15 +152,16 @@ public class GemFireOperationsSessionRepository extends AbstractGemFireOperation
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes (removes) any existing {@link ExpiringSession} from GemFire. This operation also results in
|
||||
* a SessionDeletedEvent.
|
||||
* Deletes (removes) any existing {@link ExpiringSession} from GemFire. This operation
|
||||
* also results in a SessionDeletedEvent.
|
||||
*
|
||||
* @param sessionId a String indicating the ID of the Session to remove from GemFire.
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#remove(Object)
|
||||
* @see #handleDeleted(String, ExpiringSession)
|
||||
*/
|
||||
public void delete(String sessionId) {
|
||||
handleDeleted(sessionId, getTemplate().<Object, ExpiringSession>remove(sessionId));
|
||||
handleDeleted(sessionId,
|
||||
getTemplate().<Object, ExpiringSession>remove(sessionId));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,11 +29,13 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Add this annotation to an {@code @Configuration} class to expose the SessionRepositoryFilter
|
||||
* as a bean named "springSessionRepositoryFilter" and backed by Pivotal GemFire or Apache Geode.
|
||||
* Add this annotation to an {@code @Configuration} class to expose the
|
||||
* SessionRepositoryFilter as a bean named "springSessionRepositoryFilter" and backed by
|
||||
* Pivotal GemFire or Apache Geode.
|
||||
*
|
||||
* In order to leverage the annotation, a single Pivotal GemFire/Apache Geode {@link com.gemstone.gemfire.cache.Cache}
|
||||
* or {@link com.gemstone.gemfire.cache.client.ClientCache} instance must be provided.
|
||||
* In order to leverage the annotation, a single Pivotal GemFire/Apache Geode
|
||||
* {@link com.gemstone.gemfire.cache.Cache} or
|
||||
* {@link com.gemstone.gemfire.cache.client.ClientCache} instance must be provided.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
@@ -61,12 +63,11 @@ import org.springframework.context.annotation.Import;
|
||||
* return clientCacheFactoryBean;
|
||||
* }
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
* </code> </pre>
|
||||
*
|
||||
* Alternatively, a Spring Session can be configured to use Pivotal GemFire (Apache Geode) as a client
|
||||
* using a dedicated GemFire Server cluster and a {@link com.gemstone.gemfire.cache.client.ClientCache}.
|
||||
* For example:
|
||||
* Alternatively, a Spring Session can be configured to use Pivotal GemFire (Apache Geode)
|
||||
* as a client using a dedicated GemFire Server cluster and a
|
||||
* {@link com.gemstone.gemfire.cache.client.ClientCache}. For example:
|
||||
*
|
||||
* <code>
|
||||
* {@literal @Configuration}
|
||||
@@ -92,12 +93,14 @@ import org.springframework.context.annotation.Import;
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* More advanced configurations can extend {@link GemFireHttpSessionConfiguration} instead.
|
||||
* More advanced configurations can extend {@link GemFireHttpSessionConfiguration}
|
||||
* instead.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.
|
||||
* GemFireHttpSessionConfiguration
|
||||
* @see org.springframework.session.config.annotation.web.http.EnableSpringHttpSession
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@@ -111,31 +114,35 @@ public @interface EnableGemFireHttpSession {
|
||||
/**
|
||||
* Defines the GemFire ClientCache Region DataPolicy.
|
||||
*
|
||||
* @return a ClientRegionShortcut used to specify and configure the ClientCache Region DataPolicy.
|
||||
* @return a ClientRegionShortcut used to specify and configure the ClientCache Region
|
||||
* DataPolicy.
|
||||
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
|
||||
*/
|
||||
ClientRegionShortcut clientRegionShortcut() default ClientRegionShortcut.PROXY;
|
||||
|
||||
/**
|
||||
* Identifies the Session attributes by name that should be indexed for query operations.
|
||||
* For instance, find all Sessions in GemFire having attribute A defined with value X.
|
||||
* Identifies the Session attributes by name that should be indexed for query
|
||||
* operations. For instance, find all Sessions in GemFire having attribute A defined
|
||||
* with value X.
|
||||
*
|
||||
* @return an array of Strings identifying the names of Session attributes to index.
|
||||
*/
|
||||
String[]indexableSessionAttributes() default {};
|
||||
|
||||
/**
|
||||
* Defines the maximum interval in seconds that a Session can remain inactive before it is considered expired.
|
||||
* Defaults to 1800 seconds, or 30 minutes.
|
||||
* Defines the maximum interval in seconds that a Session can remain inactive before
|
||||
* it is considered expired. Defaults to 1800 seconds, or 30 minutes.
|
||||
*
|
||||
* @return an integer value defining the maximum inactive interval in seconds for declaring a Session expired.
|
||||
* @return an integer value defining the maximum inactive interval in seconds for
|
||||
* declaring a Session expired.
|
||||
*/
|
||||
int maxInactiveIntervalInSeconds() default 1800;
|
||||
|
||||
/**
|
||||
* Defines the name of the GemFire (Client)Cache Region used to store Sessions.
|
||||
*
|
||||
* @return a String specifying the name of the GemFire (Client)Cache Region used to store Sessions.
|
||||
* @return a String specifying the name of the GemFire (Client)Cache Region used to
|
||||
* store Sessions.
|
||||
* @see com.gemstone.gemfire.cache.Region#getName()
|
||||
*/
|
||||
String regionName() default "ClusteredSpringSessions";
|
||||
@@ -143,7 +150,8 @@ public @interface EnableGemFireHttpSession {
|
||||
/**
|
||||
* Defines the GemFire, Peer Cache Region DataPolicy.
|
||||
*
|
||||
* @return a RegionShortcut used to specify and configure the Peer Cache Region DataPolicy.
|
||||
* @return a RegionShortcut used to specify and configure the Peer Cache Region
|
||||
* DataPolicy.
|
||||
* @see com.gemstone.gemfire.cache.RegionShortcut
|
||||
*/
|
||||
RegionShortcut serverRegionShortcut() default RegionShortcut.PARTITION;
|
||||
|
||||
@@ -49,8 +49,9 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The GemFireHttpSessionConfiguration class is a Spring @Configuration class used to configure and initialize
|
||||
* Pivotal GemFire (or Apache Geode) as a clustered, replicated HttpSession provider implementation in Spring Session.
|
||||
* The GemFireHttpSessionConfiguration class is a Spring @Configuration class used to
|
||||
* configure and initialize Pivotal GemFire (or Apache Geode) as a clustered, replicated
|
||||
* HttpSession provider implementation in Spring Session.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
@@ -63,9 +64,11 @@ import org.springframework.util.StringUtils;
|
||||
* @see org.springframework.data.gemfire.IndexFactoryBean
|
||||
* @see org.springframework.data.gemfire.RegionAttributesFactoryBean
|
||||
* @see org.springframework.session.ExpiringSession
|
||||
* @see org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration
|
||||
* @see org.springframework.session.config.annotation.web.http.
|
||||
* SpringHttpSessionConfiguration
|
||||
* @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.support.GemFireCacheTypeAwareRegionFactoryBean
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.support.
|
||||
* GemFireCacheTypeAwareRegionFactoryBean
|
||||
* @see com.gemstone.gemfire.cache.ExpirationAttributes
|
||||
* @see com.gemstone.gemfire.cache.GemFireCache
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
@@ -81,7 +84,8 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
* The default maximum interval in seconds in which a Session can remain inactive
|
||||
* before it is considered expired.
|
||||
*/
|
||||
public static final int DEFAULT_MAX_INACTIVE_INTERVAL_IN_SECONDS = (int) TimeUnit.MINUTES.toSeconds(30);
|
||||
public static final int DEFAULT_MAX_INACTIVE_INTERVAL_IN_SECONDS = (int) TimeUnit.MINUTES
|
||||
.toSeconds(30);
|
||||
|
||||
protected static final Class<Object> SPRING_SESSION_GEMFIRE_REGION_KEY_CONSTRAINT = Object.class;
|
||||
protected static final Class<GemFireSession> SPRING_SESSION_GEMFIRE_REGION_VALUE_CONSTRAINT = GemFireSession.class;
|
||||
@@ -121,9 +125,11 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
private String[] indexableSessionAttributes = DEFAULT_INDEXABLE_SESSION_ATTRIBUTES;
|
||||
|
||||
/**
|
||||
* Sets a reference to the {@link ClassLoader} used to load bean definition class types in a Spring context.
|
||||
* Sets a reference to the {@link ClassLoader} used to load bean definition class
|
||||
* types in a Spring context.
|
||||
*
|
||||
* @param beanClassLoader the ClassLoader used by the Spring container to load bean class types.
|
||||
* @param beanClassLoader the ClassLoader used by the Spring container to load bean
|
||||
* class types.
|
||||
* @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(ClassLoader)
|
||||
* @see java.lang.ClassLoader
|
||||
*/
|
||||
@@ -132,7 +138,8 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the {@link ClassLoader} used to load bean definition class types in a Spring context.
|
||||
* Gets a reference to the {@link ClassLoader} used to load bean definition class
|
||||
* types in a Spring context.
|
||||
*
|
||||
* @return the ClassLoader used by the Spring container to load bean class types.
|
||||
* @see java.lang.ClassLoader
|
||||
@@ -142,10 +149,11 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link ClientRegionShortcut} used to configure the GemFire ClientCache Region
|
||||
* that will store Spring Sessions.
|
||||
* Sets the {@link ClientRegionShortcut} used to configure the GemFire ClientCache
|
||||
* Region that will store Spring Sessions.
|
||||
*
|
||||
* @param shortcut the ClientRegionShortcut used to configure the GemFire ClientCache Region.
|
||||
* @param shortcut the ClientRegionShortcut used to configure the GemFire ClientCache
|
||||
* Region.
|
||||
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
|
||||
*/
|
||||
public void setClientRegionShortcut(ClientRegionShortcut shortcut) {
|
||||
@@ -153,22 +161,24 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link ClientRegionShortcut} used to configure the GemFire ClientCache Region
|
||||
* that will store Spring Sessions. Defaults to {@link ClientRegionShortcut#PROXY}.
|
||||
* Gets the {@link ClientRegionShortcut} used to configure the GemFire ClientCache
|
||||
* Region that will store Spring Sessions. Defaults to
|
||||
* {@link ClientRegionShortcut#PROXY}.
|
||||
*
|
||||
* @return the ClientRegionShortcut used to configure the GemFire ClientCache Region.
|
||||
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
|
||||
* @see EnableGemFireHttpSession#clientRegionShortcut()
|
||||
*/
|
||||
protected ClientRegionShortcut getClientRegionShortcut() {
|
||||
return (this.clientRegionShortcut != null ? this.clientRegionShortcut : DEFAULT_CLIENT_REGION_SHORTCUT);
|
||||
return (this.clientRegionShortcut != null ? this.clientRegionShortcut
|
||||
: DEFAULT_CLIENT_REGION_SHORTCUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the names of all Session attributes that should be indexed by GemFire.
|
||||
*
|
||||
* @param indexableSessionAttributes an array of Strings indicating the names of all Session attributes
|
||||
* for which an Index will be created by GemFire.
|
||||
* @param indexableSessionAttributes an array of Strings indicating the names of all
|
||||
* Session attributes for which an Index will be created by GemFire.
|
||||
*/
|
||||
public void setIndexableSessionAttributes(String[] indexableSessionAttributes) {
|
||||
this.indexableSessionAttributes = indexableSessionAttributes;
|
||||
@@ -177,21 +187,23 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
/**
|
||||
* Get the names of all Session attributes that should be indexed by GemFire.
|
||||
*
|
||||
* @return an array of Strings indicating the names of all Session attributes for which an Index
|
||||
* will be created by GemFire. Defaults to an empty String array if unspecified.
|
||||
* @return an array of Strings indicating the names of all Session attributes for
|
||||
* which an Index will be created by GemFire. Defaults to an empty String array if
|
||||
* unspecified.
|
||||
* @see EnableGemFireHttpSession#indexableSessionAttributes()
|
||||
*/
|
||||
protected String[] getIndexableSessionAttributes() {
|
||||
return (this.indexableSessionAttributes != null ? this.indexableSessionAttributes : DEFAULT_INDEXABLE_SESSION_ATTRIBUTES);
|
||||
return (this.indexableSessionAttributes != null ? this.indexableSessionAttributes
|
||||
: DEFAULT_INDEXABLE_SESSION_ATTRIBUTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of all Session attributes that will be indexed by GemFire as single String value constituting
|
||||
* the Index expression of the Index definition.
|
||||
* Gets the names of all Session attributes that will be indexed by GemFire as single
|
||||
* String value constituting the Index expression of the Index definition.
|
||||
*
|
||||
* @return a String composed of all the named Session attributes on which a GemFire Index will be created
|
||||
* as an Index definition expression. If the indexable Session attributes were not specified, then the
|
||||
* wildcard ("*") is returned.
|
||||
* @return a String composed of all the named Session attributes on which a GemFire
|
||||
* Index will be created as an Index definition expression. If the indexable Session
|
||||
* attributes were not specified, then the wildcard ("*") is returned.
|
||||
* @see com.gemstone.gemfire.cache.query.Index#getIndexedExpression()
|
||||
*/
|
||||
protected String getIndexableSessionAttributesAsGemFireIndexExpression() {
|
||||
@@ -208,20 +220,23 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum interval in seconds in which a Session can remain inactive before it is considered expired.
|
||||
* Sets the maximum interval in seconds in which a Session can remain inactive before
|
||||
* it is considered expired.
|
||||
*
|
||||
* @param maxInactiveIntervalInSeconds an integer value specifying the maximum interval in seconds that a Session
|
||||
* can remain inactive before it is considered expired.
|
||||
* @param maxInactiveIntervalInSeconds an integer value specifying the maximum
|
||||
* interval in seconds that a Session can remain inactive before it is considered
|
||||
* expired.
|
||||
*/
|
||||
public void setMaxInactiveIntervalInSeconds(int maxInactiveIntervalInSeconds) {
|
||||
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum interval in seconds in which a Session can remain inactive before it is considered expired.
|
||||
* Gets the maximum interval in seconds in which a Session can remain inactive before
|
||||
* it is considered expired.
|
||||
*
|
||||
* @return an integer value specifying the maximum interval in seconds that a Session can remain inactive
|
||||
* before it is considered expired.
|
||||
* @return an integer value specifying the maximum interval in seconds that a Session
|
||||
* can remain inactive before it is considered expired.
|
||||
* @see EnableGemFireHttpSession#maxInactiveIntervalInSeconds()
|
||||
*/
|
||||
protected int getMaxInactiveIntervalInSeconds() {
|
||||
@@ -229,7 +244,8 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link RegionShortcut} used to configure the GemFire Cache Region that will store Spring Sessions.
|
||||
* Sets the {@link RegionShortcut} used to configure the GemFire Cache Region that
|
||||
* will store Spring Sessions.
|
||||
*
|
||||
* @param shortcut the RegionShortcut used to configure the GemFire Cache Region.
|
||||
* @see com.gemstone.gemfire.cache.RegionShortcut
|
||||
@@ -239,111 +255,131 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link RegionShortcut} used to configure the GemFire Cache Region that will store Spring Sessions.
|
||||
* Defaults to {@link RegionShortcut#PARTITION}.
|
||||
* Gets the {@link RegionShortcut} used to configure the GemFire Cache Region that
|
||||
* will store Spring Sessions. Defaults to {@link RegionShortcut#PARTITION}.
|
||||
*
|
||||
* @return the RegionShortcut used to configure the GemFire Cache Region.
|
||||
* @see com.gemstone.gemfire.cache.RegionShortcut
|
||||
* @see EnableGemFireHttpSession#serverRegionShortcut()
|
||||
*/
|
||||
protected RegionShortcut getServerRegionShortcut() {
|
||||
return (this.serverRegionShortcut != null ? this.serverRegionShortcut : DEFAULT_SERVER_REGION_SHORTCUT);
|
||||
return (this.serverRegionShortcut != null ? this.serverRegionShortcut
|
||||
: DEFAULT_SERVER_REGION_SHORTCUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the Gemfire (Client)Cache Region used to store Sessions.
|
||||
*
|
||||
* @param springSessionGemFireRegionName a String specifying the name of the GemFire (Client)Cache Region
|
||||
* used to store the Session.
|
||||
* @param springSessionGemFireRegionName a String specifying the name of the GemFire
|
||||
* (Client)Cache Region used to store the Session.
|
||||
*/
|
||||
public void setSpringSessionGemFireRegionName(String springSessionGemFireRegionName) {
|
||||
this.springSessionGemFireRegionName = springSessionGemFireRegionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the Gemfire (Client)Cache Region used to store Sessions. Defaults to 'ClusteredSpringSessions'.
|
||||
* Gets the name of the Gemfire (Client)Cache Region used to store Sessions. Defaults
|
||||
* to 'ClusteredSpringSessions'.
|
||||
*
|
||||
* @return a String specifying the name of the GemFire (Client)Cache Region
|
||||
* used to store the Session.
|
||||
* @return a String specifying the name of the GemFire (Client)Cache Region used to
|
||||
* store the Session.
|
||||
* @see com.gemstone.gemfire.cache.Region#getName()
|
||||
* @see EnableGemFireHttpSession#regionName()
|
||||
*/
|
||||
protected String getSpringSessionGemFireRegionName() {
|
||||
return (StringUtils.hasText(this.springSessionGemFireRegionName) ? this.springSessionGemFireRegionName
|
||||
return (StringUtils.hasText(this.springSessionGemFireRegionName)
|
||||
? this.springSessionGemFireRegionName
|
||||
: DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback with the {@link AnnotationMetadata} of the class containing @Import annotation that imported
|
||||
* this @Configuration class.
|
||||
* Callback with the {@link AnnotationMetadata} of the class containing @Import
|
||||
* annotation that imported this @Configuration class.
|
||||
*
|
||||
* @param importMetadata the AnnotationMetadata of the class importing this @Configuration class.
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession
|
||||
* @param importMetadata the AnnotationMetadata of the class importing
|
||||
* this @Configuration class.
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.
|
||||
* EnableGemFireHttpSession
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
*/
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
AnnotationAttributes enableGemFireHttpSessionAnnotationAttributes = AnnotationAttributes.fromMap(
|
||||
importMetadata.getAnnotationAttributes(EnableGemFireHttpSession.class.getName()));
|
||||
AnnotationAttributes enableGemFireHttpSessionAnnotationAttributes = AnnotationAttributes
|
||||
.fromMap(importMetadata.getAnnotationAttributes(
|
||||
EnableGemFireHttpSession.class.getName()));
|
||||
|
||||
setClientRegionShortcut(ClientRegionShortcut.class.cast(enableGemFireHttpSessionAnnotationAttributes.getEnum(
|
||||
"clientRegionShortcut")));
|
||||
setClientRegionShortcut(ClientRegionShortcut.class
|
||||
.cast(enableGemFireHttpSessionAnnotationAttributes
|
||||
.getEnum("clientRegionShortcut")));
|
||||
|
||||
setIndexableSessionAttributes(enableGemFireHttpSessionAnnotationAttributes.getStringArray(
|
||||
"indexableSessionAttributes"));
|
||||
setIndexableSessionAttributes(enableGemFireHttpSessionAnnotationAttributes
|
||||
.getStringArray("indexableSessionAttributes"));
|
||||
|
||||
setMaxInactiveIntervalInSeconds(enableGemFireHttpSessionAnnotationAttributes.getNumber(
|
||||
"maxInactiveIntervalInSeconds").intValue());
|
||||
setMaxInactiveIntervalInSeconds(enableGemFireHttpSessionAnnotationAttributes
|
||||
.getNumber("maxInactiveIntervalInSeconds").intValue());
|
||||
|
||||
setServerRegionShortcut(RegionShortcut.class.cast(enableGemFireHttpSessionAnnotationAttributes.getEnum(
|
||||
"serverRegionShortcut")));
|
||||
setServerRegionShortcut(
|
||||
RegionShortcut.class.cast(enableGemFireHttpSessionAnnotationAttributes
|
||||
.getEnum("serverRegionShortcut")));
|
||||
|
||||
setSpringSessionGemFireRegionName(enableGemFireHttpSessionAnnotationAttributes.getString("regionName"));
|
||||
setSpringSessionGemFireRegionName(
|
||||
enableGemFireHttpSessionAnnotationAttributes.getString("regionName"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the Spring SessionRepository bean used to interact with GemFire as a Spring Session provider.
|
||||
* Defines the Spring SessionRepository bean used to interact with GemFire as a Spring
|
||||
* Session provider.
|
||||
*
|
||||
* @param gemfireOperations an instance of {@link GemfireOperations} used to manage Spring Sessions in GemFire.
|
||||
* @return a GemFireOperationsSessionRepository for managing (clustering/replicating) Sessions using GemFire.
|
||||
* @param gemfireOperations an instance of {@link GemfireOperations} used to manage
|
||||
* Spring Sessions in GemFire.
|
||||
* @return a GemFireOperationsSessionRepository for managing (clustering/replicating)
|
||||
* Sessions using GemFire.
|
||||
* @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository
|
||||
* @see org.springframework.data.gemfire.GemfireOperations
|
||||
*/
|
||||
@Bean
|
||||
public GemFireOperationsSessionRepository sessionRepository(@Qualifier("sessionRegionTemplate")
|
||||
GemfireOperations gemfireOperations) {
|
||||
public GemFireOperationsSessionRepository sessionRepository(
|
||||
@Qualifier("sessionRegionTemplate") GemfireOperations gemfireOperations) {
|
||||
|
||||
GemFireOperationsSessionRepository sessionRepository = new GemFireOperationsSessionRepository(gemfireOperations);
|
||||
GemFireOperationsSessionRepository sessionRepository = new GemFireOperationsSessionRepository(
|
||||
gemfireOperations);
|
||||
|
||||
sessionRepository.setMaxInactiveIntervalInSeconds(getMaxInactiveIntervalInSeconds());
|
||||
sessionRepository
|
||||
.setMaxInactiveIntervalInSeconds(getMaxInactiveIntervalInSeconds());
|
||||
|
||||
return sessionRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a Spring GemfireTemplate bean used to interact with GemFire's (Client)Cache {@link Region}
|
||||
* storing Sessions.
|
||||
* Defines a Spring GemfireTemplate bean used to interact with GemFire's (Client)Cache
|
||||
* {@link Region} storing Sessions.
|
||||
*
|
||||
* @param gemFireCache reference to the single GemFire cache instance used by the {@link GemfireTemplate}
|
||||
* to perform GemFire cache data access operations.
|
||||
* @return a {@link GemfireTemplate} used to interact with GemFire's (Client)Cache {@link Region} storing Sessions.
|
||||
* @param gemFireCache reference to the single GemFire cache instance used by the
|
||||
* {@link GemfireTemplate} to perform GemFire cache data access operations.
|
||||
* @return a {@link GemfireTemplate} used to interact with GemFire's (Client)Cache
|
||||
* {@link Region} storing Sessions.
|
||||
* @see org.springframework.data.gemfire.GemfireTemplate
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
*/
|
||||
@Bean
|
||||
@DependsOn(DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME)
|
||||
public GemfireTemplate sessionRegionTemplate(GemFireCache gemFireCache) {
|
||||
return new GemfireTemplate(gemFireCache.getRegion(getSpringSessionGemFireRegionName()));
|
||||
return new GemfireTemplate(
|
||||
gemFireCache.getRegion(getSpringSessionGemFireRegionName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a Spring GemFire {@link com.gemstone.gemfire.cache.Cache} {@link Region} bean used to store
|
||||
* and manage Sessions using either a client-server or peer-to-peer (p2p) topology.
|
||||
* Defines a Spring GemFire {@link com.gemstone.gemfire.cache.Cache} {@link Region}
|
||||
* bean used to store and manage Sessions using either a client-server or peer-to-peer
|
||||
* (p2p) topology.
|
||||
*
|
||||
* @param gemfireCache a reference to the GemFire {@link com.gemstone.gemfire.cache.Cache}.
|
||||
* @param sessionRegionAttributes the GemFire {@link RegionAttributes} used to configure the {@link Region}.
|
||||
* @return a {@link GemFireCacheTypeAwareRegionFactoryBean} used to configure and initialize a GemFire Cache
|
||||
* {@link Region} for storing and managing Sessions.
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.support.GemFireCacheTypeAwareRegionFactoryBean
|
||||
* @param gemfireCache a reference to the GemFire
|
||||
* {@link com.gemstone.gemfire.cache.Cache}.
|
||||
* @param sessionRegionAttributes the GemFire {@link RegionAttributes} used to
|
||||
* configure the {@link Region}.
|
||||
* @return a {@link GemFireCacheTypeAwareRegionFactoryBean} used to configure and
|
||||
* initialize a GemFire Cache {@link Region} for storing and managing Sessions.
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.support.
|
||||
* GemFireCacheTypeAwareRegionFactoryBean
|
||||
* @see com.gemstone.gemfire.cache.GemFireCache
|
||||
* @see com.gemstone.gemfire.cache.RegionAttributes
|
||||
* @see #getClientRegionShortcut()
|
||||
@@ -351,11 +387,11 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
* @see #getServerRegionShortcut()
|
||||
*/
|
||||
@Bean(name = DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME)
|
||||
public GemFireCacheTypeAwareRegionFactoryBean<Object, ExpiringSession> sessionRegion(GemFireCache gemfireCache,
|
||||
public GemFireCacheTypeAwareRegionFactoryBean<Object, ExpiringSession> sessionRegion(
|
||||
GemFireCache gemfireCache,
|
||||
RegionAttributes<Object, ExpiringSession> sessionRegionAttributes) {
|
||||
|
||||
GemFireCacheTypeAwareRegionFactoryBean<Object, ExpiringSession> serverRegion =
|
||||
new GemFireCacheTypeAwareRegionFactoryBean<Object, ExpiringSession>();
|
||||
GemFireCacheTypeAwareRegionFactoryBean<Object, ExpiringSession> serverRegion = new GemFireCacheTypeAwareRegionFactoryBean<Object, ExpiringSession>();
|
||||
|
||||
serverRegion.setGemfireCache(gemfireCache);
|
||||
serverRegion.setClientRegionShortcut(getClientRegionShortcut());
|
||||
@@ -367,13 +403,14 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a Spring GemFire {@link RegionAttributes} bean used to configure and initialize the GemFire cache
|
||||
* {@link Region} storing Sessions. Expiration is also configured for the {@link Region} on the basis that the
|
||||
* GemFire cache {@link Region} is a not a proxy, on either the client or server.
|
||||
* Defines a Spring GemFire {@link RegionAttributes} bean used to configure and
|
||||
* initialize the GemFire cache {@link Region} storing Sessions. Expiration is also
|
||||
* configured for the {@link Region} on the basis that the GemFire cache
|
||||
* {@link Region} is a not a proxy, on either the client or server.
|
||||
*
|
||||
* @param gemfireCache a reference to the GemFire cache.
|
||||
* @return an instance of {@link RegionAttributes} used to configure and initialize the GemFire cache {@link Region}
|
||||
* for storing and managing Sessions.
|
||||
* @return an instance of {@link RegionAttributes} used to configure and initialize
|
||||
* the GemFire cache {@link Region} for storing and managing Sessions.
|
||||
* @see org.springframework.data.gemfire.RegionAttributesFactoryBean
|
||||
* @see com.gemstone.gemfire.cache.GemFireCache
|
||||
* @see com.gemstone.gemfire.cache.PartitionAttributes
|
||||
@@ -381,44 +418,49 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
*/
|
||||
@Bean
|
||||
@SuppressWarnings({ "unchecked", "deprecation" })
|
||||
public RegionAttributesFactoryBean sessionRegionAttributes(GemFireCache gemfireCache) {
|
||||
public RegionAttributesFactoryBean sessionRegionAttributes(
|
||||
GemFireCache gemfireCache) {
|
||||
RegionAttributesFactoryBean regionAttributes = new RegionAttributesFactoryBean();
|
||||
|
||||
regionAttributes.setKeyConstraint(SPRING_SESSION_GEMFIRE_REGION_KEY_CONSTRAINT);
|
||||
regionAttributes.setValueConstraint(SPRING_SESSION_GEMFIRE_REGION_VALUE_CONSTRAINT);
|
||||
regionAttributes
|
||||
.setValueConstraint(SPRING_SESSION_GEMFIRE_REGION_VALUE_CONSTRAINT);
|
||||
|
||||
if (isExpirationAllowed(gemfireCache)) {
|
||||
regionAttributes.setStatisticsEnabled(true);
|
||||
regionAttributes.setEntryIdleTimeout(new ExpirationAttributes(
|
||||
Math.max(getMaxInactiveIntervalInSeconds(), 0), ExpirationAction.INVALIDATE));
|
||||
Math.max(getMaxInactiveIntervalInSeconds(), 0),
|
||||
ExpirationAction.INVALIDATE));
|
||||
}
|
||||
|
||||
return regionAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether expiration configuration is allowed to be set on the GemFire cache {@link Region}
|
||||
* used to store and manage Sessions.
|
||||
* Determines whether expiration configuration is allowed to be set on the GemFire
|
||||
* cache {@link Region} used to store and manage Sessions.
|
||||
*
|
||||
* @param gemfireCache a reference to the GemFire cache.
|
||||
* @return a boolean indicating if a {@link Region} can be configured for Region entry idle-timeout expiration.
|
||||
* @return a boolean indicating if a {@link Region} can be configured for Region entry
|
||||
* idle-timeout expiration.
|
||||
* @see GemFireUtils#isClient(GemFireCache)
|
||||
* @see GemFireUtils#isProxy(ClientRegionShortcut)
|
||||
* @see GemFireUtils#isProxy(RegionShortcut)
|
||||
*/
|
||||
boolean isExpirationAllowed(GemFireCache gemfireCache) {
|
||||
return !(GemFireUtils.isClient(gemfireCache) ? GemFireUtils.isProxy(getClientRegionShortcut())
|
||||
return !(GemFireUtils.isClient(gemfireCache)
|
||||
? GemFireUtils.isProxy(getClientRegionShortcut())
|
||||
: GemFireUtils.isProxy(getServerRegionShortcut()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a Spring GemFire Index bean on the GemFire cache {@link Region} storing and managing Sessions,
|
||||
* specifically on the 'principalName' property for quick lookup and queries. This index will only be created
|
||||
* on a server @{link Region}.
|
||||
* Defines a Spring GemFire Index bean on the GemFire cache {@link Region} storing and
|
||||
* managing Sessions, specifically on the 'principalName' property for quick lookup
|
||||
* and queries. This index will only be created on a server @{link Region}.
|
||||
*
|
||||
* @param gemfireCache a reference to the GemFire cache.
|
||||
* @return a IndexFactoryBean creating an GemFire Index on the 'principalName' property of Sessions stored
|
||||
* in the GemFire cache {@link Region}.
|
||||
* @return a IndexFactoryBean creating an GemFire Index on the 'principalName'
|
||||
* property of Sessions stored in the GemFire cache {@link Region}.
|
||||
* @see org.springframework.data.gemfire.IndexFactoryBean
|
||||
* @see com.gemstone.gemfire.cache.GemFireCache
|
||||
*/
|
||||
@@ -445,12 +487,14 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a Spring GemFire Index bean on the GemFire cache {@link Region} storing and managing Sessions,
|
||||
* specifically on Session attributes for quick lookup and queries on Session attribute names with a given value.
|
||||
* This index will only be created on a server @{link Region}.
|
||||
* Defines a Spring GemFire Index bean on the GemFire cache {@link Region} storing and
|
||||
* managing Sessions, specifically on Session attributes for quick lookup and queries
|
||||
* on Session attribute names with a given value. This index will only be created on a
|
||||
* server @{link Region}.
|
||||
*
|
||||
* @param gemfireCache a reference to the GemFire cache.
|
||||
* @return a IndexFactoryBean creating an GemFire Index on attributes of Sessions stored in the GemFire cache {@link Region}.
|
||||
* @return a IndexFactoryBean creating an GemFire Index on attributes of Sessions
|
||||
* stored in the GemFire cache {@link Region}.
|
||||
* @see org.springframework.data.gemfire.IndexFactoryBean
|
||||
* @see com.gemstone.gemfire.cache.GemFireCache
|
||||
*/
|
||||
@@ -460,7 +504,8 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
IndexFactoryBean index = new IndexFactoryBean() {
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (GemFireUtils.isPeer(gemfireCache) && !ObjectUtils.isEmpty(getIndexableSessionAttributes())) {
|
||||
if (GemFireUtils.isPeer(gemfireCache)
|
||||
&& !ObjectUtils.isEmpty(getIndexableSessionAttributes())) {
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
}
|
||||
@@ -468,8 +513,10 @@ public class GemFireHttpSessionConfiguration extends SpringHttpSessionConfigurat
|
||||
|
||||
index.setCache(gemfireCache);
|
||||
index.setName("sessionAttributesIndex");
|
||||
index.setExpression(String.format("s.attributes[%1$s]", getIndexableSessionAttributesAsGemFireIndexExpression()));
|
||||
index.setFrom(String.format("%1$s s", GemFireUtils.toRegionPath(getSpringSessionGemFireRegionName())));
|
||||
index.setExpression(String.format("s.attributes[%1$s]",
|
||||
getIndexableSessionAttributesAsGemFireIndexExpression()));
|
||||
index.setFrom(String.format("%1$s s",
|
||||
GemFireUtils.toRegionPath(getSpringSessionGemFireRegionName())));
|
||||
index.setOverride(true);
|
||||
|
||||
return index;
|
||||
|
||||
@@ -34,8 +34,9 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The GemFireCacheTypeAwareRegionFactoryBean class is a Spring {@link FactoryBean} used to construct, configure
|
||||
* and initialize the GemFire cache {@link Region} used to store and manage Session state.
|
||||
* The GemFireCacheTypeAwareRegionFactoryBean class is a Spring {@link FactoryBean} used
|
||||
* to construct, configure and initialize the GemFire cache {@link Region} used to store
|
||||
* and manage Session state.
|
||||
*
|
||||
* @param <K> the type of keys
|
||||
* @param <V> the type of values
|
||||
@@ -45,7 +46,8 @@ import org.springframework.util.StringUtils;
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.data.gemfire.GenericRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.
|
||||
* GemFireHttpSessionConfiguration
|
||||
* @see com.gemstone.gemfire.cache.GemFireCache
|
||||
* @see com.gemstone.gemfire.cache.InterestResultPolicy
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
@@ -53,16 +55,14 @@ import org.springframework.util.StringUtils;
|
||||
* @see com.gemstone.gemfire.cache.RegionShortcut
|
||||
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
|
||||
*/
|
||||
public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean<Region<K, V>>, InitializingBean {
|
||||
public class GemFireCacheTypeAwareRegionFactoryBean<K, V>
|
||||
implements FactoryBean<Region<K, V>>, InitializingBean {
|
||||
|
||||
protected static final ClientRegionShortcut DEFAULT_CLIENT_REGION_SHORTCUT =
|
||||
GemFireHttpSessionConfiguration.DEFAULT_CLIENT_REGION_SHORTCUT;
|
||||
protected static final ClientRegionShortcut DEFAULT_CLIENT_REGION_SHORTCUT = GemFireHttpSessionConfiguration.DEFAULT_CLIENT_REGION_SHORTCUT;
|
||||
|
||||
protected static final RegionShortcut DEFAULT_SERVER_REGION_SHORTCUT =
|
||||
GemFireHttpSessionConfiguration.DEFAULT_SERVER_REGION_SHORTCUT;
|
||||
protected static final RegionShortcut DEFAULT_SERVER_REGION_SHORTCUT = GemFireHttpSessionConfiguration.DEFAULT_SERVER_REGION_SHORTCUT;
|
||||
|
||||
protected static final String DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME =
|
||||
GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME;
|
||||
protected static final String DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME = GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME;
|
||||
|
||||
private ClientRegionShortcut clientRegionShortcut;
|
||||
|
||||
@@ -77,9 +77,10 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
private String regionName;
|
||||
|
||||
/**
|
||||
* Post-construction initialization callback to create, configure and initialize the GemFire cache {@link Region}
|
||||
* used to store, replicate (distribute) and manage Session state. This method intelligently handles
|
||||
* both client-server and peer-to-peer (p2p) GemFire supported distributed system topologies.
|
||||
* Post-construction initialization callback to create, configure and initialize the
|
||||
* GemFire cache {@link Region} used to store, replicate (distribute) and manage
|
||||
* Session state. This method intelligently handles both client-server and
|
||||
* peer-to-peer (p2p) GemFire supported distributed system topologies.
|
||||
*
|
||||
* @throws Exception if the initialization of the GemFire cache {@link Region} fails.
|
||||
* @see org.springframework.session.data.gemfire.support.GemFireUtils#isClient(GemFireCache)
|
||||
@@ -95,13 +96,16 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a GemFire cache {@link Region} using a peer-to-peer (p2p) GemFire topology to store
|
||||
* and manage Session state in a GemFire server cluster accessible from a GemFire cache client.
|
||||
* Constructs a GemFire cache {@link Region} using a peer-to-peer (p2p) GemFire
|
||||
* topology to store and manage Session state in a GemFire server cluster accessible
|
||||
* from a GemFire cache client.
|
||||
*
|
||||
* @param gemfireCache a reference to the GemFire {@link com.gemstone.gemfire.cache.Cache}.
|
||||
* @return a peer-to-peer-based GemFire cache {@link Region} to store and manage Session state.
|
||||
* @throws Exception if the instantiation, configuration and initialization
|
||||
* of the GemFire cache {@link Region} fails.
|
||||
* @param gemfireCache a reference to the GemFire
|
||||
* {@link com.gemstone.gemfire.cache.Cache}.
|
||||
* @return a peer-to-peer-based GemFire cache {@link Region} to store and manage
|
||||
* Session state.
|
||||
* @throws Exception if the instantiation, configuration and initialization of the
|
||||
* GemFire cache {@link Region} fails.
|
||||
* @see org.springframework.data.gemfire.GenericRegionFactoryBean
|
||||
* @see com.gemstone.gemfire.cache.GemFireCache
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
@@ -122,13 +126,16 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a GemFire cache {@link Region} using the client-server GemFire topology to store
|
||||
* and manage Session state in a GemFire server cluster accessible from a GemFire cache client.
|
||||
* Constructs a GemFire cache {@link Region} using the client-server GemFire topology
|
||||
* to store and manage Session state in a GemFire server cluster accessible from a
|
||||
* GemFire cache client.
|
||||
*
|
||||
* @param gemfireCache a reference to the GemFire {@link com.gemstone.gemfire.cache.Cache}.
|
||||
* @return a client-server-based GemFire cache {@link Region} to store and manage Session state.
|
||||
* @throws Exception if the instantiation, configuration and initialization
|
||||
* of the GemFire cache {@link Region} fails.
|
||||
* @param gemfireCache a reference to the GemFire
|
||||
* {@link com.gemstone.gemfire.cache.Cache}.
|
||||
* @return a client-server-based GemFire cache {@link Region} to store and manage
|
||||
* Session state.
|
||||
* @throws Exception if the instantiation, configuration and initialization of the
|
||||
* GemFire cache {@link Region} fails.
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see com.gemstone.gemfire.cache.GemFireCache
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
@@ -155,12 +162,14 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
/**
|
||||
* Registers interests in all keys when the client {@link Region} is non-local.
|
||||
*
|
||||
* @return an array of Interests specifying the server notifications of interests to the client.
|
||||
* @return an array of Interests specifying the server notifications of interests to
|
||||
* the client.
|
||||
* @see org.springframework.data.gemfire.client.Interest
|
||||
*/
|
||||
/**
|
||||
* Decides whether interests will be registered for all keys. Interests is only registered on a client
|
||||
* and typically only when the client is a (CACHING) PROXY to the server (i.e. non-LOCAL only).
|
||||
* Decides whether interests will be registered for all keys. Interests is only
|
||||
* registered on a client and typically only when the client is a (CACHING) PROXY to
|
||||
* the server (i.e. non-LOCAL only).
|
||||
*
|
||||
* @param register a boolean value indicating whether interests should be registered.
|
||||
* @return an array of Interests KEY/VALUE registrations.
|
||||
@@ -168,13 +177,14 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Interest<K>[] registerInterests(boolean register) {
|
||||
return (!register ? new Interest[0] : new Interest[] {
|
||||
new Interest<String>("ALL_KEYS", InterestResultPolicy.KEYS)
|
||||
});
|
||||
return (!register ? new Interest[0]
|
||||
: new Interest[] {
|
||||
new Interest<String>("ALL_KEYS", InterestResultPolicy.KEYS) });
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the constructed GemFire cache {@link Region} used to store and manage Session state.
|
||||
* Returns a reference to the constructed GemFire cache {@link Region} used to store
|
||||
* and manage Session state.
|
||||
*
|
||||
* @return the {@link Region} used to store and manage Session state.
|
||||
* @throws Exception if the {@link Region} reference cannot be obtained.
|
||||
@@ -185,8 +195,8 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the specific type of GemFire cache {@link Region} this factory creates when initialized
|
||||
* or Region.class when uninitialized.
|
||||
* Returns the specific type of GemFire cache {@link Region} this factory creates when
|
||||
* initialized or Region.class when uninitialized.
|
||||
*
|
||||
* @return the GemFire cache {@link Region} class type constructed by this factory.
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
@@ -197,19 +207,22 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true indicating the GemFire cache {@link Region} created by this factory is the sole instance.
|
||||
* Returns true indicating the GemFire cache {@link Region} created by this factory is
|
||||
* the sole instance.
|
||||
*
|
||||
* @return true to indicate the GemFire cache {@link Region} storing and managing Sessions is a Singleton.
|
||||
* @return true to indicate the GemFire cache {@link Region} storing and managing
|
||||
* Sessions is a Singleton.
|
||||
*/
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Region} data policy used by the GemFire cache client to manage Session state.
|
||||
* Sets the {@link Region} data policy used by the GemFire cache client to manage
|
||||
* Session state.
|
||||
*
|
||||
* @param clientRegionShortcut a {@link ClientRegionShortcut} to specify the client {@link Region}
|
||||
* data management policy.
|
||||
* @param clientRegionShortcut a {@link ClientRegionShortcut} to specify the client
|
||||
* {@link Region} data management policy.
|
||||
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
|
||||
*/
|
||||
public void setClientRegionShortcut(ClientRegionShortcut clientRegionShortcut) {
|
||||
@@ -217,19 +230,22 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Region} data policy used by the GemFire cache client to manage Session state. Defaults to
|
||||
* {@link ClientRegionShortcut#PROXY}.
|
||||
* Returns the {@link Region} data policy used by the GemFire cache client to manage
|
||||
* Session state. Defaults to {@link ClientRegionShortcut#PROXY}.
|
||||
*
|
||||
* @return a {@link ClientRegionShortcut} specifying the client {@link Region} data management policy.
|
||||
* @return a {@link ClientRegionShortcut} specifying the client {@link Region} data
|
||||
* management policy.
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration#DEFAULT_CLIENT_REGION_SHORTCUT
|
||||
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
|
||||
*/
|
||||
protected ClientRegionShortcut getClientRegionShortcut() {
|
||||
return (this.clientRegionShortcut != null ? this.clientRegionShortcut : DEFAULT_CLIENT_REGION_SHORTCUT);
|
||||
return (this.clientRegionShortcut != null ? this.clientRegionShortcut
|
||||
: DEFAULT_CLIENT_REGION_SHORTCUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the GemFire cache used to construct the appropriate {@link Region}.
|
||||
* Sets a reference to the GemFire cache used to construct the appropriate
|
||||
* {@link Region}.
|
||||
*
|
||||
* @param gemfireCache a reference to the GemFire cache.
|
||||
* @throws IllegalArgumentException if the {@link GemFireCache} reference is null.
|
||||
@@ -240,21 +256,24 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the GemFire cache used to construct the appropriate {@link Region}.
|
||||
* Returns a reference to the GemFire cache used to construct the appropriate
|
||||
* {@link Region}.
|
||||
*
|
||||
* @return a reference to the GemFire cache.
|
||||
* @throws IllegalStateException if the {@link GemFireCache} reference is null.
|
||||
*/
|
||||
protected GemFireCache getGemfireCache() {
|
||||
Assert.state(this.gemfireCache != null, "A reference to a GemFireCache was not properly configured");
|
||||
Assert.state(this.gemfireCache != null,
|
||||
"A reference to a GemFireCache was not properly configured");
|
||||
return this.gemfireCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the GemFire {@link RegionAttributes} used to configure the GemFire cache {@link Region} used to
|
||||
* store and manage Session state.
|
||||
* Sets the GemFire {@link RegionAttributes} used to configure the GemFire cache
|
||||
* {@link Region} used to store and manage Session state.
|
||||
*
|
||||
* @param regionAttributes the GemFire {@link RegionAttributes} used to configure the GemFire cache {@link Region}.
|
||||
* @param regionAttributes the GemFire {@link RegionAttributes} used to configure the
|
||||
* GemFire cache {@link Region}.
|
||||
* @see com.gemstone.gemfire.cache.RegionAttributes
|
||||
*/
|
||||
public void setRegionAttributes(RegionAttributes<K, V> regionAttributes) {
|
||||
@@ -262,10 +281,11 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GemFire {@link RegionAttributes} used to configure the GemFire cache {@link Region} used to
|
||||
* store and manage Session state.
|
||||
* Returns the GemFire {@link RegionAttributes} used to configure the GemFire cache
|
||||
* {@link Region} used to store and manage Session state.
|
||||
*
|
||||
* @return the GemFire {@link RegionAttributes} used to configure the GemFire cache {@link Region}.
|
||||
* @return the GemFire {@link RegionAttributes} used to configure the GemFire cache
|
||||
* {@link Region}.
|
||||
* @see com.gemstone.gemfire.cache.RegionAttributes
|
||||
*/
|
||||
protected RegionAttributes<K, V> getRegionAttributes() {
|
||||
@@ -273,7 +293,8 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the GemFire cache {@link Region} use to store and manage Session state.
|
||||
* Sets the name of the GemFire cache {@link Region} use to store and manage Session
|
||||
* state.
|
||||
*
|
||||
* @param regionName a String specifying the name of the GemFire cache {@link Region}.
|
||||
*/
|
||||
@@ -282,20 +303,23 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured name of the GemFire cache {@link Region} use to store and manage Session state.
|
||||
* Defaults to "ClusteredSpringSessions"
|
||||
* Returns the configured name of the GemFire cache {@link Region} use to store and
|
||||
* manage Session state. Defaults to "ClusteredSpringSessions"
|
||||
*
|
||||
* @return a String specifying the name of the GemFire cache {@link Region}.
|
||||
* @see com.gemstone.gemfire.cache.Region#getName()
|
||||
*/
|
||||
protected String getRegionName() {
|
||||
return (StringUtils.hasText(this.regionName) ? this.regionName : DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME);
|
||||
return (StringUtils.hasText(this.regionName) ? this.regionName
|
||||
: DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Region} data policy used by the GemFire peer cache to manage Session state.
|
||||
* Sets the {@link Region} data policy used by the GemFire peer cache to manage
|
||||
* Session state.
|
||||
*
|
||||
* @param serverRegionShortcut a {@link RegionShortcut} to specify the peer {@link Region} data management policy.
|
||||
* @param serverRegionShortcut a {@link RegionShortcut} to specify the peer
|
||||
* {@link Region} data management policy.
|
||||
* @see com.gemstone.gemfire.cache.RegionShortcut
|
||||
*/
|
||||
public void setServerRegionShortcut(RegionShortcut serverRegionShortcut) {
|
||||
@@ -303,14 +327,16 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> implements FactoryBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Region} data policy used by the GemFire peer cache to manage Session state. Defaults to
|
||||
* {@link RegionShortcut#PARTITION}.
|
||||
* Returns the {@link Region} data policy used by the GemFire peer cache to manage
|
||||
* Session state. Defaults to {@link RegionShortcut#PARTITION}.
|
||||
*
|
||||
* @return a {@link RegionShortcut} specifying the peer {@link Region} data management policy.
|
||||
* @return a {@link RegionShortcut} specifying the peer {@link Region} data management
|
||||
* policy.
|
||||
* @see com.gemstone.gemfire.cache.RegionShortcut
|
||||
*/
|
||||
protected RegionShortcut getServerRegionShortcut() {
|
||||
return (this.serverRegionShortcut != null ? this.serverRegionShortcut : DEFAULT_SERVER_REGION_SHORTCUT);
|
||||
return (this.serverRegionShortcut != null ? this.serverRegionShortcut
|
||||
: DEFAULT_SERVER_REGION_SHORTCUT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
|
||||
import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
|
||||
|
||||
/**
|
||||
* GemFireUtils is an abstract, extensible utility class for working with GemFire types and functionality
|
||||
* and is used by Spring Session's GemFire adapter support classes.
|
||||
* GemFireUtils is an abstract, extensible utility class for working with GemFire types
|
||||
* and functionality and is used by Spring Session's GemFire adapter support classes.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
@@ -40,8 +40,8 @@ public abstract class GemFireUtils {
|
||||
* Null-safe method to close the given {@link Closeable} object.
|
||||
*
|
||||
* @param obj the {@link Closeable} object to close.
|
||||
* @return true if the {@link Closeable} object is not null and was successfully closed,
|
||||
* otherwise return false.
|
||||
* @return true if the {@link Closeable} object is not null and was successfully
|
||||
* closed, otherwise return false.
|
||||
* @see java.io.Closeable
|
||||
*/
|
||||
public static boolean close(Closeable obj) {
|
||||
@@ -67,7 +67,8 @@ public abstract class GemFireUtils {
|
||||
*/
|
||||
public static boolean isClient(GemFireCache gemFireCache) {
|
||||
boolean client = (gemFireCache instanceof ClientCache);
|
||||
client &= (!(gemFireCache instanceof GemFireCacheImpl) || ((GemFireCacheImpl) gemFireCache).isClient());
|
||||
client &= (!(gemFireCache instanceof GemFireCacheImpl)
|
||||
|| ((GemFireCacheImpl) gemFireCache).isClient());
|
||||
return client;
|
||||
}
|
||||
|
||||
@@ -87,7 +88,8 @@ public abstract class GemFireUtils {
|
||||
* Determines whether the given {@link ClientRegionShortcut} is local only.
|
||||
*
|
||||
* @param shortcut the ClientRegionShortcut to evaluate.
|
||||
* @return a boolean value indicating if the {@link ClientRegionShortcut} is local or not.
|
||||
* @return a boolean value indicating if the {@link ClientRegionShortcut} is local or
|
||||
* not.
|
||||
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
|
||||
*/
|
||||
public static boolean isLocal(ClientRegionShortcut shortcut) {
|
||||
@@ -104,12 +106,12 @@ public abstract class GemFireUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the client {@link ClientRegionShortcut} is a proxy-based shortcut.
|
||||
* NOTE: "proxy"-based Regions keep no local state.
|
||||
* Determines whether the client {@link ClientRegionShortcut} is a proxy-based
|
||||
* shortcut. NOTE: "proxy"-based Regions keep no local state.
|
||||
*
|
||||
* @param shortcut the client {@link ClientRegionShortcut} to evaluate.
|
||||
* @return a boolean value indicating whether the client {@link ClientRegionShortcut} refers to
|
||||
* a proxy-based shortcut.
|
||||
* @return a boolean value indicating whether the client {@link ClientRegionShortcut}
|
||||
* refers to a proxy-based shortcut.
|
||||
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
|
||||
*/
|
||||
public static boolean isProxy(ClientRegionShortcut shortcut) {
|
||||
@@ -122,11 +124,12 @@ public abstract class GemFireUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the peer {@link RegionShortcut} is a proxy-based shortcut. NOTE: "proxy"-based Regions
|
||||
* keep no local state.
|
||||
* Determines whether the peer {@link RegionShortcut} is a proxy-based shortcut. NOTE:
|
||||
* "proxy"-based Regions keep no local state.
|
||||
*
|
||||
* @param shortcut the peer {@link RegionShortcut} to evaluate.
|
||||
* @return a boolean value indicating whether the peer {@link RegionShortcut} refers to a proxy-based shortcut.
|
||||
* @return a boolean value indicating whether the peer {@link RegionShortcut} refers
|
||||
* to a proxy-based shortcut.
|
||||
* @see com.gemstone.gemfire.cache.RegionShortcut
|
||||
*/
|
||||
public static boolean isProxy(RegionShortcut shortcut) {
|
||||
|
||||
@@ -1,7 +1,25 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.session.data.mongo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mongodb.core.IndexOperations;
|
||||
@@ -9,12 +27,10 @@ import org.springframework.data.mongodb.core.index.Index;
|
||||
import org.springframework.data.mongodb.core.index.IndexInfo;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Base class for serializing and deserializing session objects.
|
||||
* To create custom serializer you have to implement this interface
|
||||
* and simply register your class as a bean.
|
||||
* Base class for serializing and deserializing session objects. To create custom
|
||||
* serializer you have to implement this interface and simply register your class as a
|
||||
* bean.
|
||||
*
|
||||
* @author Jakub Kubrynski
|
||||
* @since 1.2
|
||||
@@ -26,7 +42,7 @@ public abstract class AbstractMongoSessionConverter implements GenericConverter
|
||||
protected static final String EXPIRE_AT_FIELD_NAME = "expireAt";
|
||||
|
||||
/**
|
||||
* Returns query to be executed to return sessions based on a particular index
|
||||
* Returns query to be executed to return sessions based on a particular index.
|
||||
* @param indexName name of the index
|
||||
* @param indexValue value to query against
|
||||
* @return built query or null if indexName is not supported
|
||||
@@ -34,23 +50,26 @@ public abstract class AbstractMongoSessionConverter implements GenericConverter
|
||||
protected abstract Query getQueryForIndex(String indexName, Object indexValue);
|
||||
|
||||
/**
|
||||
* Method ensures that there is a TTL index on {@literal expireAt} field.
|
||||
* It's has {@literal expireAfterSeconds} set to zero seconds, so the expiration
|
||||
* time is controlled by the application.
|
||||
* Method ensures that there is a TTL index on {@literal expireAt} field. It's has
|
||||
* {@literal expireAfterSeconds} set to zero seconds, so the expiration time is
|
||||
* controlled by the application.
|
||||
*
|
||||
* It can be extended in custom converters when there is a need for creating
|
||||
* additional custom indexes.
|
||||
* @param sessionCollectionIndexes {@link IndexOperations} to use
|
||||
*/
|
||||
protected void ensureIndexes(IndexOperations sessionCollectionIndexes) {
|
||||
List<IndexInfo> indexInfo = sessionCollectionIndexes.getIndexInfo();
|
||||
for (IndexInfo info : indexInfo) {
|
||||
if (EXPIRE_AT_FIELD_NAME.equals(info.getName())) {
|
||||
LOG.debug("TTL index on field " + EXPIRE_AT_FIELD_NAME + " already exists");
|
||||
LOG.debug(
|
||||
"TTL index on field " + EXPIRE_AT_FIELD_NAME + " already exists");
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG.info("Creating TTL index on field " + EXPIRE_AT_FIELD_NAME);
|
||||
sessionCollectionIndexes
|
||||
.ensureIndex(new Index(EXPIRE_AT_FIELD_NAME, Sort.Direction.ASC).named(EXPIRE_AT_FIELD_NAME).expire(0));
|
||||
.ensureIndex(new Index(EXPIRE_AT_FIELD_NAME, Sort.Direction.ASC)
|
||||
.named(EXPIRE_AT_FIELD_NAME).expire(0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,36 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.session.data.mongo;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
|
||||
/**
|
||||
* Utility class to extract principal name from {@code Authentication} object
|
||||
* Utility class to extract principal name from {@code Authentication} object.
|
||||
*
|
||||
* @author Jakub Kubrynski
|
||||
*/
|
||||
class AuthenticationParser {
|
||||
final class AuthenticationParser {
|
||||
|
||||
private static final String NAME_EXPRESSION = "authentication?.name";
|
||||
|
||||
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
|
||||
/**
|
||||
* Extracts principal name from authentication
|
||||
* Extracts principal name from authentication.
|
||||
*
|
||||
* @param authentication Authentication object
|
||||
* @return principal name
|
||||
@@ -27,4 +42,7 @@ class AuthenticationParser {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private AuthenticationParser() {
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,15 +15,6 @@
|
||||
*/
|
||||
package org.springframework.session.data.mongo;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.session.Session;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -35,11 +26,20 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.session.FindByIndexNameSessionRepository;
|
||||
import org.springframework.session.Session;
|
||||
|
||||
/**
|
||||
* {@code AbstractMongoSessionConverter} implementation transforming {@code MongoExpiringSession} to/from a BSON object
|
||||
* using standard Java serialization
|
||||
* {@code AbstractMongoSessionConverter} implementation transforming.
|
||||
* {@code MongoExpiringSession} to/from a BSON object using standard Java serialization
|
||||
*
|
||||
* @author Jakub Kubrynski
|
||||
* @since 1.2
|
||||
@@ -57,25 +57,30 @@ class JdkMongoSessionConverter extends AbstractMongoSessionConverter {
|
||||
private static final String PRINCIPAL_FIELD_NAME = "principal";
|
||||
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
|
||||
|
||||
@Override
|
||||
public Query getQueryForIndex(String indexName, Object indexValue) {
|
||||
if (PRINCIPAL_NAME_INDEX_NAME.equals(indexName)) {
|
||||
if (FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME
|
||||
.equals(indexName)) {
|
||||
return Query.query(Criteria.where(PRINCIPAL_FIELD_NAME).is(indexValue));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
return Collections.singleton(new ConvertiblePair(DBObject.class, MongoExpiringSession.class));
|
||||
return Collections.singleton(
|
||||
new ConvertiblePair(DBObject.class, MongoExpiringSession.class));
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
public Object convert(Object source, TypeDescriptor sourceType,
|
||||
TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (DBObject.class.isAssignableFrom(sourceType.getType())) {
|
||||
return convert((DBObject) source);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return convert((MongoExpiringSession) source);
|
||||
}
|
||||
}
|
||||
@@ -103,24 +108,29 @@ class JdkMongoSessionConverter extends AbstractMongoSessionConverter {
|
||||
outputStream.writeObject(attributes);
|
||||
outputStream.flush();
|
||||
return out.toByteArray();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error("Exception during session serialization", e);
|
||||
throw new IllegalStateException("Cannot serialize session", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String extractPrincipal(Session expiringSession) {
|
||||
String resolvedPrincipal = AuthenticationParser.extractName(expiringSession.getAttribute(SPRING_SECURITY_CONTEXT));
|
||||
String resolvedPrincipal = AuthenticationParser
|
||||
.extractName(expiringSession.getAttribute(SPRING_SECURITY_CONTEXT));
|
||||
if (resolvedPrincipal != null) {
|
||||
return resolvedPrincipal;
|
||||
} else {
|
||||
return expiringSession.getAttribute(PRINCIPAL_NAME_INDEX_NAME);
|
||||
}
|
||||
else {
|
||||
return expiringSession.getAttribute(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
private MongoExpiringSession convert(DBObject sessionWrapper) {
|
||||
MongoExpiringSession session =
|
||||
new MongoExpiringSession((String) sessionWrapper.get(ID), (Integer) sessionWrapper.get(MAX_INTERVAL));
|
||||
MongoExpiringSession session = new MongoExpiringSession(
|
||||
(String) sessionWrapper.get(ID),
|
||||
(Integer) sessionWrapper.get(MAX_INTERVAL));
|
||||
session.setCreationTime((Long) sessionWrapper.get(CREATION_TIME));
|
||||
session.setLastAccessedTime((Long) sessionWrapper.get(LAST_ACCESSED_TIME));
|
||||
session.setExpireAt((Date) sessionWrapper.get(EXPIRE_AT_FIELD_NAME));
|
||||
@@ -131,17 +141,21 @@ class JdkMongoSessionConverter extends AbstractMongoSessionConverter {
|
||||
@SuppressWarnings("unchecked")
|
||||
private void deserializeAttributes(DBObject sessionWrapper, Session session) {
|
||||
try {
|
||||
ByteArrayInputStream in = new ByteArrayInputStream((byte[]) sessionWrapper.get(ATTRIBUTES));
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(
|
||||
(byte[]) sessionWrapper.get(ATTRIBUTES));
|
||||
ObjectInputStream objectInputStream = new ObjectInputStream(in);
|
||||
Map<String, Object> attributes = (Map<String, Object>) objectInputStream.readObject();
|
||||
Map<String, Object> attributes = (Map<String, Object>) objectInputStream
|
||||
.readObject();
|
||||
for (Map.Entry<String, Object> entry : attributes.entrySet()) {
|
||||
session.setAttribute(entry.getKey(), entry.getValue());
|
||||
}
|
||||
objectInputStream.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error("Exception during session deserialization", e);
|
||||
throw new IllegalStateException("Cannot deserialize session", e);
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
LOG.error("Exception during session deserialization", e);
|
||||
throw new IllegalStateException("Cannot deserialize session", e);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user