@@ -26,13 +26,12 @@ import org.springframework.jdbc.datasource.init.DataSourceInitializer;
|
||||
import org.springframework.jdbc.datasource.init.DatabasePopulator;
|
||||
|
||||
/**
|
||||
* Abstract base class for Testcontainers based {@link JdbcOperationsSessionRepository}
|
||||
* integration tests.
|
||||
* Base class for Testcontainers based {@link JdbcIndexedSessionRepository} integration
|
||||
* tests.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
abstract class AbstractContainerJdbcOperationsSessionRepositoryITests
|
||||
extends AbstractJdbcOperationsSessionRepositoryITests {
|
||||
abstract class AbstractContainerJdbcIndexedSessionRepositoryITests extends AbstractJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
static class BaseContainerConfig extends BaseConfig {
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.session.FindByIndexNameSessionRepository;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository.JdbcSession;
|
||||
import org.springframework.session.jdbc.config.annotation.web.http.EnableJdbcHttpSession;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
@@ -46,18 +47,18 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link JdbcOperationsSessionRepository} integration tests.
|
||||
* Base class for {@link JdbcIndexedSessionRepository} integration tests.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
abstract class AbstractJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
|
||||
|
||||
private static final String INDEX_NAME = FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME;
|
||||
|
||||
@Autowired
|
||||
private JdbcOperationsSessionRepository repository;
|
||||
private JdbcIndexedSessionRepository repository;
|
||||
|
||||
private SecurityContext context;
|
||||
|
||||
@@ -76,10 +77,10 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
void saveWhenNoAttributesThenCanBeFound() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
|
||||
this.repository.save(toSave);
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.findById(toSave.getId());
|
||||
JdbcSession session = this.repository.findById(toSave.getId());
|
||||
|
||||
assertThat(session).isNotNull();
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
@@ -90,7 +91,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
void saves() {
|
||||
String username = "saves-" + System.currentTimeMillis();
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
String expectedAttributeName = "a";
|
||||
String expectedAttributeValue = "b";
|
||||
toSave.setAttribute(expectedAttributeName, expectedAttributeValue);
|
||||
@@ -103,7 +104,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.findById(toSave.getId());
|
||||
JdbcSession session = this.repository.findById(toSave.getId());
|
||||
|
||||
assertThat(session.getId()).isEqualTo(toSave.getId());
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
@@ -120,14 +121,14 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
@Test
|
||||
@Transactional(readOnly = true)
|
||||
void savesInReadOnlyTransaction() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
|
||||
this.repository.save(toSave);
|
||||
}
|
||||
|
||||
@Test
|
||||
void putAllOnSingleAttrDoesNotRemoveOld() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute("a", "b");
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -138,7 +139,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
this.repository.save(toSave);
|
||||
toSave = this.repository.findById(toSave.getId());
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.findById(toSave.getId());
|
||||
JdbcSession session = this.repository.findById(toSave.getId());
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
assertThat(session.getAttributeNames().size()).isEqualTo(2);
|
||||
@@ -150,7 +151,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
void updateLastAccessedTime() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setLastAccessedTime(Instant.now().minusSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS + 1));
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -159,7 +160,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
toSave.setLastAccessedTime(lastAccessedTime);
|
||||
this.repository.save(toSave);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.findById(toSave.getId());
|
||||
JdbcSession session = this.repository.findById(toSave.getId());
|
||||
|
||||
assertThat(session).isNotNull();
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
@@ -172,13 +173,13 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
@Test
|
||||
void findByPrincipalName() {
|
||||
String principalName = "findByPrincipalName" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
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, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -194,15 +195,15 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
@Test
|
||||
void findByPrincipalNameExpireRemovesIndex() {
|
||||
String principalName = "findByPrincipalNameExpireRemovesIndex" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
toSave.setLastAccessedTime(Instant.now().minusSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS + 1));
|
||||
|
||||
this.repository.save(toSave);
|
||||
this.repository.cleanUpExpiredSessions();
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(0);
|
||||
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
|
||||
@@ -211,7 +212,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
@Test
|
||||
void findByPrincipalNameNoPrincipalNameChange() {
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChange" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -219,8 +220,8 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute("other", "value");
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -233,7 +234,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
@Test
|
||||
void findByPrincipalNameNoPrincipalNameChangeReload() {
|
||||
String principalName = "findByPrincipalNameNoPrincipalNameChangeReload" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -243,8 +244,8 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute("other", "value");
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -257,7 +258,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
@Test
|
||||
void findByDeletedPrincipalName() {
|
||||
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -265,8 +266,8 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute(INDEX_NAME, null);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
@@ -275,7 +276,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
void findByChangedPrincipalName() {
|
||||
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -283,8 +284,8 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute(INDEX_NAME, principalNameChanged);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
|
||||
@@ -300,17 +301,17 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
@Test
|
||||
void findByDeletedPrincipalNameReload() {
|
||||
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession getSession = this.repository.findById(toSave.getId());
|
||||
JdbcSession getSession = this.repository.findById(toSave.getId());
|
||||
getSession.setAttribute(INDEX_NAME, null);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
@@ -319,18 +320,18 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
void findByChangedPrincipalNameReload() {
|
||||
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(INDEX_NAME, principalName);
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession getSession = this.repository.findById(toSave.getId());
|
||||
JdbcSession getSession = this.repository.findById(toSave.getId());
|
||||
|
||||
getSession.setAttribute(INDEX_NAME, principalNameChanged);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
principalName);
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
|
||||
@@ -345,13 +346,13 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
void findBySecurityPrincipalName() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
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, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -366,15 +367,15 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
void findBySecurityPrincipalNameExpireRemovesIndex() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
toSave.setLastAccessedTime(Instant.now().minusSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS + 1));
|
||||
|
||||
this.repository.save(toSave);
|
||||
this.repository.cleanUpExpiredSessions();
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(0);
|
||||
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
|
||||
@@ -382,7 +383,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
void findByPrincipalNameNoSecurityPrincipalNameChange() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -390,8 +391,8 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute("other", "value");
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -403,7 +404,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
void findByPrincipalNameNoSecurityPrincipalNameChangeReload() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -413,8 +414,8 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute("other", "value");
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
@@ -426,7 +427,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
void findByDeletedSecurityPrincipalName() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -434,15 +435,15 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, null);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByChangedSecurityPrincipalName() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
@@ -450,8 +451,8 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
@@ -466,35 +467,35 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
void findByDeletedSecurityPrincipalNameReload() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession getSession = this.repository.findById(toSave.getId());
|
||||
JdbcSession getSession = this.repository.findById(toSave.getId());
|
||||
getSession.setAttribute(INDEX_NAME, null);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getChangedSecurityName());
|
||||
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByChangedSecurityPrincipalNameReload() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession getSession = this.repository.findById(toSave.getId());
|
||||
JdbcSession getSession = this.repository.findById(toSave.getId());
|
||||
|
||||
getSession.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
|
||||
this.repository.save(getSession);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> findByPrincipalName = this.repository
|
||||
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
|
||||
Map<String, JdbcSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
|
||||
getSecurityName());
|
||||
assertThat(findByPrincipalName).isEmpty();
|
||||
|
||||
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
|
||||
@@ -509,7 +510,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
void cleanupInactiveSessionsUsingRepositoryDefinedInterval() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
@@ -537,7 +538,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
// gh-580
|
||||
@Test
|
||||
void cleanupInactiveSessionsUsingSessionDefinedInterval() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
session.setMaxInactiveInterval(Duration.ofMinutes(45));
|
||||
|
||||
this.repository.save(session);
|
||||
@@ -567,12 +568,12 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
void changeSessionIdWhenOnlyChangeId() {
|
||||
String attrName = "changeSessionId";
|
||||
String attrValue = "changeSessionId-value";
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
toSave.setAttribute(attrName, attrValue);
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession findById = this.repository.findById(toSave.getId());
|
||||
JdbcSession findById = this.repository.findById(toSave.getId());
|
||||
|
||||
assertThat(findById.<String>getAttribute(attrName)).isEqualTo(attrValue);
|
||||
|
||||
@@ -583,7 +584,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
assertThat(this.repository.findById(originalFindById)).isNull();
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession findByChangeSessionId = this.repository.findById(changeSessionId);
|
||||
JdbcSession findByChangeSessionId = this.repository.findById(changeSessionId);
|
||||
|
||||
assertThat(findByChangeSessionId.isChanged()).isFalse();
|
||||
assertThat(findByChangeSessionId.getDelta()).isEmpty();
|
||||
@@ -592,7 +593,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
void changeSessionIdWhenChangeTwice() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
@@ -612,11 +613,11 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
String attrName = "changeSessionId";
|
||||
String attrValue = "changeSessionId-value";
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession findById = this.repository.findById(toSave.getId());
|
||||
JdbcSession findById = this.repository.findById(toSave.getId());
|
||||
|
||||
findById.setAttribute(attrName, attrValue);
|
||||
|
||||
@@ -627,7 +628,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
assertThat(this.repository.findById(originalFindById)).isNull();
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession findByChangeSessionId = this.repository.findById(changeSessionId);
|
||||
JdbcSession findByChangeSessionId = this.repository.findById(changeSessionId);
|
||||
|
||||
assertThat(findByChangeSessionId.isChanged()).isFalse();
|
||||
assertThat(findByChangeSessionId.getDelta()).isEmpty();
|
||||
@@ -636,7 +637,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test
|
||||
void changeSessionIdWhenHasNotSaved() {
|
||||
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
|
||||
JdbcSession toSave = this.repository.createSession();
|
||||
String originalId = toSave.getId();
|
||||
toSave.changeSessionId();
|
||||
|
||||
@@ -648,7 +649,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test // gh-1070
|
||||
void saveUpdatedAddAndModifyAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
session.setAttribute("testName", "testValue1");
|
||||
@@ -661,7 +662,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test // gh-1070
|
||||
void saveUpdatedAddAndRemoveAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
session.setAttribute("testName", "testValue");
|
||||
@@ -674,7 +675,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test // gh-1070
|
||||
void saveUpdatedModifyAndRemoveAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
session.setAttribute("testName", "testValue1");
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
@@ -688,7 +689,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test // gh-1070
|
||||
void saveUpdatedRemoveAndAddAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
session.setAttribute("testName", "testValue1");
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
@@ -702,7 +703,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test // gh-1031
|
||||
void saveDeleted() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
this.repository.deleteById(session.getId());
|
||||
@@ -714,7 +715,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test // gh-1031
|
||||
void saveDeletedAddAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
this.repository.deleteById(session.getId());
|
||||
@@ -727,7 +728,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
@Test // gh-1133
|
||||
void sessionFromStoreResolvesAttributesLazily() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
session.setAttribute("attribute1", "value1");
|
||||
session.setAttribute("attribute2", "value2");
|
||||
this.repository.save(session);
|
||||
@@ -749,7 +750,7 @@ abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
String attributeName = "largeAttribute";
|
||||
int arraySize = 4000;
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
session.setAttribute(attributeName, new byte[arraySize]);
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
@@ -27,15 +27,14 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using IBM DB2 11.x
|
||||
* database.
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using IBM DB2 11.x database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class Db211JdbcOperationsSessionRepositoryITests extends AbstractContainerJdbcOperationsSessionRepositoryITests {
|
||||
class Db211JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseContainerConfig {
|
||||
@@ -28,14 +28,14 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using Derby database.
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using Derby database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class DerbyJdbcOperationsSessionRepositoryITests extends AbstractJdbcOperationsSessionRepositoryITests {
|
||||
class DerbyJdbcIndexedSessionRepositoryITests extends AbstractJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseConfig {
|
||||
@@ -28,14 +28,14 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using H2 database.
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using H2 database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class H2JdbcOperationsSessionRepositoryITests extends AbstractJdbcOperationsSessionRepositoryITests {
|
||||
class H2JdbcIndexedSessionRepositoryITests extends AbstractJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseConfig {
|
||||
@@ -28,14 +28,14 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using HSQLDB database.
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using HSQLDB database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class HsqldbJdbcOperationsSessionRepositoryITests extends AbstractJdbcOperationsSessionRepositoryITests {
|
||||
class HsqldbJdbcIndexedSessionRepositoryITests extends AbstractJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseConfig {
|
||||
@@ -27,15 +27,14 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using MariaDB 10.x
|
||||
* database.
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using MariaDB 10.x database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class MariaDb10JdbcOperationsSessionRepositoryITests extends AbstractContainerJdbcOperationsSessionRepositoryITests {
|
||||
class MariaDb10JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseContainerConfig {
|
||||
@@ -27,15 +27,14 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using MariaDB 5.x
|
||||
* database.
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using MariaDB 5.x database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class MariaDb5JdbcOperationsSessionRepositoryITests extends AbstractContainerJdbcOperationsSessionRepositoryITests {
|
||||
class MariaDb5JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseContainerConfig {
|
||||
@@ -27,14 +27,14 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using MySQL 5.x database.
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using MySQL 5.x database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class MySql5JdbcOperationsSessionRepositoryITests extends AbstractContainerJdbcOperationsSessionRepositoryITests {
|
||||
class MySql5JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseContainerConfig {
|
||||
@@ -27,14 +27,14 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using MySQL 8.x database.
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using MySQL 8.x database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class MySql8JdbcOperationsSessionRepositoryITests extends AbstractContainerJdbcOperationsSessionRepositoryITests {
|
||||
class MySql8JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseContainerConfig {
|
||||
@@ -31,7 +31,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using Oracle database.
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using Oracle database.
|
||||
* <p>
|
||||
* This test is conditional on presence of Oracle JDBC driver on the classpath and
|
||||
* Testcontainers property {@code oracle.container.image} being set.
|
||||
@@ -41,7 +41,7 @@ import org.springframework.util.ClassUtils;
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class OracleJdbcOperationsSessionRepositoryITests extends AbstractContainerJdbcOperationsSessionRepositoryITests {
|
||||
class OracleJdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@BeforeAll
|
||||
static void setUpClass() {
|
||||
@@ -27,7 +27,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using PostgreSQL 10.x
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using PostgreSQL 10.x
|
||||
* database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
@@ -35,7 +35,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class PostgreSql10JdbcOperationsSessionRepositoryITests extends AbstractContainerJdbcOperationsSessionRepositoryITests {
|
||||
class PostgreSql10JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseContainerConfig {
|
||||
@@ -27,7 +27,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using PostgreSQL 11.x
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using PostgreSQL 11.x
|
||||
* database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
@@ -35,7 +35,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class PostgreSql11JdbcOperationsSessionRepositoryITests extends AbstractContainerJdbcOperationsSessionRepositoryITests {
|
||||
class PostgreSql11JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseContainerConfig {
|
||||
@@ -27,7 +27,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using PostgreSQL 9.x
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using PostgreSQL 9.x
|
||||
* database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
@@ -35,7 +35,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class PostgreSql9JdbcOperationsSessionRepositoryITests extends AbstractContainerJdbcOperationsSessionRepositoryITests {
|
||||
class PostgreSql9JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseContainerConfig {
|
||||
@@ -27,15 +27,15 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using Microsoft SQL
|
||||
* Server 2017 database.
|
||||
* Integration tests for {@link JdbcIndexedSessionRepository} using Microsoft SQL Server
|
||||
* 2017 database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
class SqlServerJdbcOperationsSessionRepositoryITests extends AbstractContainerJdbcOperationsSessionRepositoryITests {
|
||||
class SqlServerJdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseContainerConfig {
|
||||
@@ -0,0 +1,867 @@
|
||||
/*
|
||||
* Copyright 2014-2019 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
|
||||
*
|
||||
* https://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.jdbc;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.core.serializer.support.DeserializingConverter;
|
||||
import org.springframework.core.serializer.support.SerializingConverter;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
import org.springframework.jdbc.support.lob.DefaultLobHandler;
|
||||
import org.springframework.jdbc.support.lob.LobHandler;
|
||||
import org.springframework.session.DelegatingIndexResolver;
|
||||
import org.springframework.session.FindByIndexNameSessionRepository;
|
||||
import org.springframework.session.FlushMode;
|
||||
import org.springframework.session.IndexResolver;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.PrincipalNameIndexResolver;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.transaction.support.TransactionOperations;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.session.SessionRepository} implementation that uses
|
||||
* Spring's {@link JdbcOperations} to store sessions in a relational database. This
|
||||
* implementation does not support publishing of session events.
|
||||
* <p>
|
||||
* An example of how to create a new instance can be seen below:
|
||||
*
|
||||
* <pre class="code">
|
||||
* JdbcTemplate jdbcTemplate = new JdbcTemplate();
|
||||
*
|
||||
* // ... configure jdbcTemplate ...
|
||||
*
|
||||
* TransactionTemplate transactionTemplate = new TransactionTemplate();
|
||||
*
|
||||
* // ... configure transactionTemplate ...
|
||||
*
|
||||
* JdbcIndexedSessionRepository sessionRepository =
|
||||
* new JdbcIndexedSessionRepository(jdbcTemplate, transactionTemplate);
|
||||
* </pre>
|
||||
*
|
||||
* For additional information on how to create and configure {@code JdbcTemplate} and
|
||||
* {@code TransactionTemplate}, refer to the <a href=
|
||||
* "https://docs.spring.io/spring/docs/current/spring-framework-reference/html/spring-data-tier.html">
|
||||
* Spring Framework Reference Documentation</a>.
|
||||
* <p>
|
||||
* By default, this implementation uses <code>SPRING_SESSION</code> and
|
||||
* <code>SPRING_SESSION_ATTRIBUTES</code> tables to store sessions. Note that the table
|
||||
* name can be customized using the {@link #setTableName(String)} method. In that case the
|
||||
* table used to store attributes will be named using the provided table name, suffixed
|
||||
* with <code>_ATTRIBUTES</code>.
|
||||
*
|
||||
* Depending on your database, the table definition can be described as below:
|
||||
*
|
||||
* <pre class="code">
|
||||
* CREATE TABLE SPRING_SESSION (
|
||||
* PRIMARY_ID CHAR(36) NOT NULL,
|
||||
* SESSION_ID CHAR(36) NOT NULL,
|
||||
* CREATION_TIME BIGINT NOT NULL,
|
||||
* LAST_ACCESS_TIME BIGINT NOT NULL,
|
||||
* MAX_INACTIVE_INTERVAL INT NOT NULL,
|
||||
* EXPIRY_TIME BIGINT NOT NULL,
|
||||
* PRINCIPAL_NAME VARCHAR(100),
|
||||
* CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
|
||||
* );
|
||||
*
|
||||
* CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
|
||||
* CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (EXPIRY_TIME);
|
||||
* CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
*
|
||||
* CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
* SESSION_PRIMARY_ID CHAR(36) NOT NULL,
|
||||
* ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
|
||||
* ATTRIBUTE_BYTES BYTEA NOT NULL,
|
||||
* CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
|
||||
* CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
|
||||
* );
|
||||
*
|
||||
* CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
|
||||
* </pre>
|
||||
*
|
||||
* Due to the differences between the various database vendors, especially when it comes
|
||||
* to storing binary data, make sure to use SQL script specific to your database. Scripts
|
||||
* for most major database vendors are packaged as
|
||||
* <code>org/springframework/session/jdbc/schema-*.sql</code>, where <code>*</code> is the
|
||||
* target database type.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @author Craig Andrews
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public class JdbcIndexedSessionRepository
|
||||
implements FindByIndexNameSessionRepository<JdbcIndexedSessionRepository.JdbcSession> {
|
||||
|
||||
/**
|
||||
* The default name of database table used by Spring Session to store sessions.
|
||||
*/
|
||||
public static final String DEFAULT_TABLE_NAME = "SPRING_SESSION";
|
||||
|
||||
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
|
||||
|
||||
// @formatter:off
|
||||
private static final String CREATE_SESSION_QUERY = "INSERT INTO %TABLE_NAME%(PRIMARY_ID, SESSION_ID, CREATION_TIME, LAST_ACCESS_TIME, MAX_INACTIVE_INTERVAL, EXPIRY_TIME, PRINCIPAL_NAME) "
|
||||
+ "VALUES (?, ?, ?, ?, ?, ?, ?)";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = "INSERT INTO %TABLE_NAME%_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
|
||||
+ "SELECT PRIMARY_ID, ?, ? "
|
||||
+ "FROM %TABLE_NAME% "
|
||||
+ "WHERE SESSION_ID = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String GET_SESSION_QUERY = "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES "
|
||||
+ "FROM %TABLE_NAME% S "
|
||||
+ "LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID "
|
||||
+ "WHERE S.SESSION_ID = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String UPDATE_SESSION_QUERY = "UPDATE %TABLE_NAME% SET SESSION_ID = ?, LAST_ACCESS_TIME = ?, MAX_INACTIVE_INTERVAL = ?, EXPIRY_TIME = ?, PRINCIPAL_NAME = ? "
|
||||
+ "WHERE PRIMARY_ID = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = "UPDATE %TABLE_NAME%_ATTRIBUTES SET ATTRIBUTE_BYTES = ? "
|
||||
+ "WHERE SESSION_PRIMARY_ID = ? "
|
||||
+ "AND ATTRIBUTE_NAME = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String DELETE_SESSION_ATTRIBUTE_QUERY = "DELETE FROM %TABLE_NAME%_ATTRIBUTES "
|
||||
+ "WHERE SESSION_PRIMARY_ID = ? "
|
||||
+ "AND ATTRIBUTE_NAME = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String DELETE_SESSION_QUERY = "DELETE FROM %TABLE_NAME% "
|
||||
+ "WHERE SESSION_ID = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String LIST_SESSIONS_BY_PRINCIPAL_NAME_QUERY = "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES "
|
||||
+ "FROM %TABLE_NAME% S "
|
||||
+ "LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID "
|
||||
+ "WHERE S.PRINCIPAL_NAME = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY = "DELETE FROM %TABLE_NAME% "
|
||||
+ "WHERE EXPIRY_TIME < ?";
|
||||
// @formatter:on
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JdbcIndexedSessionRepository.class);
|
||||
|
||||
private final JdbcOperations jdbcOperations;
|
||||
|
||||
private final TransactionOperations transactionOperations;
|
||||
|
||||
private final ResultSetExtractor<List<JdbcSession>> extractor = new SessionResultSetExtractor();
|
||||
|
||||
private final IndexResolver<JdbcSession> indexResolver;
|
||||
|
||||
/**
|
||||
* The name of database table used by Spring Session to store sessions.
|
||||
*/
|
||||
private String tableName = DEFAULT_TABLE_NAME;
|
||||
|
||||
private String createSessionQuery;
|
||||
|
||||
private String createSessionAttributeQuery;
|
||||
|
||||
private String getSessionQuery;
|
||||
|
||||
private String updateSessionQuery;
|
||||
|
||||
private String updateSessionAttributeQuery;
|
||||
|
||||
private String deleteSessionAttributeQuery;
|
||||
|
||||
private String deleteSessionQuery;
|
||||
|
||||
private String listSessionsByPrincipalNameQuery;
|
||||
|
||||
private String deleteSessionsByExpiryTimeQuery;
|
||||
|
||||
/**
|
||||
* If non-null, this value is used to override the default value for
|
||||
* {@link JdbcSession#setMaxInactiveInterval(Duration)}.
|
||||
*/
|
||||
private Integer defaultMaxInactiveInterval;
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private LobHandler lobHandler;
|
||||
|
||||
private FlushMode flushMode = FlushMode.ON_SAVE;
|
||||
|
||||
private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE;
|
||||
|
||||
/**
|
||||
* Create a new {@link JdbcIndexedSessionRepository} instance which uses the provided
|
||||
* {@link JdbcOperations} and {@link TransactionOperations} to manage sessions.
|
||||
* @param jdbcOperations the {@link JdbcOperations} to use
|
||||
* @param transactionOperations the {@link TransactionOperations} to use
|
||||
*/
|
||||
public JdbcIndexedSessionRepository(JdbcOperations jdbcOperations, TransactionOperations transactionOperations) {
|
||||
Assert.notNull(jdbcOperations, "jdbcOperations must not be null");
|
||||
Assert.notNull(transactionOperations, "transactionOperations must not be null");
|
||||
this.jdbcOperations = jdbcOperations;
|
||||
this.transactionOperations = transactionOperations;
|
||||
this.indexResolver = new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>());
|
||||
this.conversionService = createDefaultConversionService();
|
||||
this.lobHandler = new DefaultLobHandler();
|
||||
prepareQueries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of database table used to store sessions.
|
||||
* @param tableName the database table name
|
||||
*/
|
||||
public void setTableName(String tableName) {
|
||||
Assert.hasText(tableName, "Table name must not be empty");
|
||||
this.tableName = tableName.trim();
|
||||
prepareQueries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to create the session.
|
||||
* @param createSessionQuery the SQL query string
|
||||
*/
|
||||
public void setCreateSessionQuery(String createSessionQuery) {
|
||||
Assert.hasText(createSessionQuery, "Query must not be empty");
|
||||
this.createSessionQuery = createSessionQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to create the session attribute.
|
||||
* @param createSessionAttributeQuery the SQL query string
|
||||
*/
|
||||
public void setCreateSessionAttributeQuery(String createSessionAttributeQuery) {
|
||||
Assert.hasText(createSessionAttributeQuery, "Query must not be empty");
|
||||
this.createSessionAttributeQuery = createSessionAttributeQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to retrieve the session.
|
||||
* @param getSessionQuery the SQL query string
|
||||
*/
|
||||
public void setGetSessionQuery(String getSessionQuery) {
|
||||
Assert.hasText(getSessionQuery, "Query must not be empty");
|
||||
this.getSessionQuery = getSessionQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to update the session.
|
||||
* @param updateSessionQuery the SQL query string
|
||||
*/
|
||||
public void setUpdateSessionQuery(String updateSessionQuery) {
|
||||
Assert.hasText(updateSessionQuery, "Query must not be empty");
|
||||
this.updateSessionQuery = updateSessionQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to update the session attribute.
|
||||
* @param updateSessionAttributeQuery the SQL query string
|
||||
*/
|
||||
public void setUpdateSessionAttributeQuery(String updateSessionAttributeQuery) {
|
||||
Assert.hasText(updateSessionAttributeQuery, "Query must not be empty");
|
||||
this.updateSessionAttributeQuery = updateSessionAttributeQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to delete the session attribute.
|
||||
* @param deleteSessionAttributeQuery the SQL query string
|
||||
*/
|
||||
public void setDeleteSessionAttributeQuery(String deleteSessionAttributeQuery) {
|
||||
Assert.hasText(deleteSessionAttributeQuery, "Query must not be empty");
|
||||
this.deleteSessionAttributeQuery = deleteSessionAttributeQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to delete the session.
|
||||
* @param deleteSessionQuery the SQL query string
|
||||
*/
|
||||
public void setDeleteSessionQuery(String deleteSessionQuery) {
|
||||
Assert.hasText(deleteSessionQuery, "Query must not be empty");
|
||||
this.deleteSessionQuery = deleteSessionQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to retrieve the sessions by principal name.
|
||||
* @param listSessionsByPrincipalNameQuery the SQL query string
|
||||
*/
|
||||
public void setListSessionsByPrincipalNameQuery(String listSessionsByPrincipalNameQuery) {
|
||||
Assert.hasText(listSessionsByPrincipalNameQuery, "Query must not be empty");
|
||||
this.listSessionsByPrincipalNameQuery = listSessionsByPrincipalNameQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to delete the sessions by last access time.
|
||||
* @param deleteSessionsByExpiryTimeQuery the SQL query string
|
||||
*/
|
||||
public void setDeleteSessionsByExpiryTimeQuery(String deleteSessionsByExpiryTimeQuery) {
|
||||
Assert.hasText(deleteSessionsByExpiryTimeQuery, "Query must not be empty");
|
||||
this.deleteSessionsByExpiryTimeQuery = deleteSessionsByExpiryTimeQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum inactive interval in seconds between requests before newly created
|
||||
* sessions will be invalidated. A negative time indicates that the session will never
|
||||
* timeout. The default is 1800 (30 minutes).
|
||||
* @param defaultMaxInactiveInterval the maximum inactive interval in seconds
|
||||
*/
|
||||
public void setDefaultMaxInactiveInterval(Integer defaultMaxInactiveInterval) {
|
||||
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
|
||||
}
|
||||
|
||||
public void setLobHandler(LobHandler lobHandler) {
|
||||
Assert.notNull(lobHandler, "LobHandler must not be null");
|
||||
this.lobHandler = lobHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link ConversionService} to use.
|
||||
* @param conversionService the converter to set
|
||||
*/
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
Assert.notNull(conversionService, "conversionService must not be null");
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the flush mode. Default is {@link FlushMode#ON_SAVE}.
|
||||
* @param flushMode the flush mode
|
||||
*/
|
||||
public void setFlushMode(FlushMode flushMode) {
|
||||
Assert.notNull(flushMode, "flushMode must not be null");
|
||||
this.flushMode = flushMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the save mode.
|
||||
* @param saveMode the save mode
|
||||
*/
|
||||
public void setSaveMode(SaveMode saveMode) {
|
||||
Assert.notNull(saveMode, "saveMode must not be null");
|
||||
this.saveMode = saveMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcSession createSession() {
|
||||
MapSession delegate = new MapSession();
|
||||
if (this.defaultMaxInactiveInterval != null) {
|
||||
delegate.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
|
||||
}
|
||||
JdbcSession session = new JdbcSession(delegate, UUID.randomUUID().toString(), true);
|
||||
session.flushIfRequired();
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final JdbcSession session) {
|
||||
session.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcSession findById(final String id) {
|
||||
final JdbcSession session = this.transactionOperations.execute((status) -> {
|
||||
List<JdbcSession> sessions = JdbcIndexedSessionRepository.this.jdbcOperations.query(
|
||||
JdbcIndexedSessionRepository.this.getSessionQuery, (ps) -> ps.setString(1, id),
|
||||
JdbcIndexedSessionRepository.this.extractor);
|
||||
if (sessions.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return sessions.get(0);
|
||||
});
|
||||
|
||||
if (session != null) {
|
||||
if (session.isExpired()) {
|
||||
deleteById(id);
|
||||
}
|
||||
else {
|
||||
return session;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteById(final String id) {
|
||||
this.transactionOperations.execute(() -> JdbcIndexedSessionRepository.this.jdbcOperations
|
||||
.update(JdbcIndexedSessionRepository.this.deleteSessionQuery, id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, JdbcSession> findByIndexNameAndIndexValue(String indexName, final String indexValue) {
|
||||
if (!PRINCIPAL_NAME_INDEX_NAME.equals(indexName)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
List<JdbcSession> sessions = this.transactionOperations
|
||||
.execute((status) -> JdbcIndexedSessionRepository.this.jdbcOperations.query(
|
||||
JdbcIndexedSessionRepository.this.listSessionsByPrincipalNameQuery,
|
||||
(ps) -> ps.setString(1, indexValue), JdbcIndexedSessionRepository.this.extractor));
|
||||
|
||||
Map<String, JdbcSession> sessionMap = new HashMap<>(sessions.size());
|
||||
|
||||
for (JdbcSession session : sessions) {
|
||||
sessionMap.put(session.getId(), session);
|
||||
}
|
||||
|
||||
return sessionMap;
|
||||
}
|
||||
|
||||
private void insertSessionAttributes(JdbcSession session, List<String> attributeNames) {
|
||||
Assert.notEmpty(attributeNames, "attributeNames must not be null or empty");
|
||||
if (attributeNames.size() > 1) {
|
||||
this.jdbcOperations.batchUpdate(this.createSessionAttributeQuery, new BatchPreparedStatementSetter() {
|
||||
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
String attributeName = attributeNames.get(i);
|
||||
ps.setString(1, attributeName);
|
||||
getLobHandler().getLobCreator().setBlobAsBytes(ps, 2,
|
||||
serialize(session.getAttribute(attributeName)));
|
||||
ps.setString(3, session.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return attributeNames.size();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.jdbcOperations.update(this.createSessionAttributeQuery, (ps) -> {
|
||||
String attributeName = attributeNames.get(0);
|
||||
ps.setString(1, attributeName);
|
||||
getLobHandler().getLobCreator().setBlobAsBytes(ps, 2, serialize(session.getAttribute(attributeName)));
|
||||
ps.setString(3, session.getId());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSessionAttributes(JdbcSession session, List<String> attributeNames) {
|
||||
Assert.notEmpty(attributeNames, "attributeNames must not be null or empty");
|
||||
if (attributeNames.size() > 1) {
|
||||
this.jdbcOperations.batchUpdate(this.updateSessionAttributeQuery, new BatchPreparedStatementSetter() {
|
||||
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
String attributeName = attributeNames.get(i);
|
||||
getLobHandler().getLobCreator().setBlobAsBytes(ps, 1,
|
||||
serialize(session.getAttribute(attributeName)));
|
||||
ps.setString(2, session.primaryKey);
|
||||
ps.setString(3, attributeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return attributeNames.size();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.jdbcOperations.update(this.updateSessionAttributeQuery, (ps) -> {
|
||||
String attributeName = attributeNames.get(0);
|
||||
getLobHandler().getLobCreator().setBlobAsBytes(ps, 1, serialize(session.getAttribute(attributeName)));
|
||||
ps.setString(2, session.primaryKey);
|
||||
ps.setString(3, attributeName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteSessionAttributes(JdbcSession session, List<String> attributeNames) {
|
||||
Assert.notEmpty(attributeNames, "attributeNames must not be null or empty");
|
||||
if (attributeNames.size() > 1) {
|
||||
this.jdbcOperations.batchUpdate(this.deleteSessionAttributeQuery, new BatchPreparedStatementSetter() {
|
||||
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
String attributeName = attributeNames.get(i);
|
||||
ps.setString(1, session.primaryKey);
|
||||
ps.setString(2, attributeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return attributeNames.size();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.jdbcOperations.update(this.deleteSessionAttributeQuery, (ps) -> {
|
||||
String attributeName = attributeNames.get(0);
|
||||
ps.setString(1, session.primaryKey);
|
||||
ps.setString(2, attributeName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanUpExpiredSessions() {
|
||||
Integer deletedCount = this.transactionOperations
|
||||
.execute((status) -> JdbcIndexedSessionRepository.this.jdbcOperations.update(
|
||||
JdbcIndexedSessionRepository.this.deleteSessionsByExpiryTimeQuery, System.currentTimeMillis()));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cleaned up " + deletedCount + " expired sessions");
|
||||
}
|
||||
}
|
||||
|
||||
private static GenericConversionService createDefaultConversionService() {
|
||||
GenericConversionService converter = new GenericConversionService();
|
||||
converter.addConverter(Object.class, byte[].class, new SerializingConverter());
|
||||
converter.addConverter(byte[].class, Object.class, new DeserializingConverter());
|
||||
return converter;
|
||||
}
|
||||
|
||||
private String getQuery(String base) {
|
||||
return StringUtils.replace(base, "%TABLE_NAME%", this.tableName);
|
||||
}
|
||||
|
||||
private void prepareQueries() {
|
||||
this.createSessionQuery = getQuery(CREATE_SESSION_QUERY);
|
||||
this.createSessionAttributeQuery = getQuery(CREATE_SESSION_ATTRIBUTE_QUERY);
|
||||
this.getSessionQuery = getQuery(GET_SESSION_QUERY);
|
||||
this.updateSessionQuery = getQuery(UPDATE_SESSION_QUERY);
|
||||
this.updateSessionAttributeQuery = getQuery(UPDATE_SESSION_ATTRIBUTE_QUERY);
|
||||
this.deleteSessionAttributeQuery = getQuery(DELETE_SESSION_ATTRIBUTE_QUERY);
|
||||
this.deleteSessionQuery = getQuery(DELETE_SESSION_QUERY);
|
||||
this.listSessionsByPrincipalNameQuery = getQuery(LIST_SESSIONS_BY_PRINCIPAL_NAME_QUERY);
|
||||
this.deleteSessionsByExpiryTimeQuery = getQuery(DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY);
|
||||
}
|
||||
|
||||
private LobHandler getLobHandler() {
|
||||
return this.lobHandler;
|
||||
}
|
||||
|
||||
private byte[] serialize(Object object) {
|
||||
return (byte[]) this.conversionService.convert(object, TypeDescriptor.valueOf(Object.class),
|
||||
TypeDescriptor.valueOf(byte[].class));
|
||||
}
|
||||
|
||||
private Object deserialize(byte[] bytes) {
|
||||
return this.conversionService.convert(bytes, TypeDescriptor.valueOf(byte[].class),
|
||||
TypeDescriptor.valueOf(Object.class));
|
||||
}
|
||||
|
||||
private enum DeltaValue {
|
||||
|
||||
ADDED, UPDATED, REMOVED
|
||||
|
||||
}
|
||||
|
||||
private static <T> Supplier<T> value(T value) {
|
||||
return (value != null) ? () -> value : null;
|
||||
}
|
||||
|
||||
private static <T> Supplier<T> lazily(Supplier<T> supplier) {
|
||||
Supplier<T> lazySupplier = new Supplier<T>() {
|
||||
|
||||
private T value;
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
if (this.value == null) {
|
||||
this.value = supplier.get();
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return (supplier != null) ? lazySupplier : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link Session} to use for {@link JdbcIndexedSessionRepository}.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
final class JdbcSession implements Session {
|
||||
|
||||
private final Session delegate;
|
||||
|
||||
private final String primaryKey;
|
||||
|
||||
private boolean isNew;
|
||||
|
||||
private boolean changed;
|
||||
|
||||
private Map<String, DeltaValue> delta = new HashMap<>();
|
||||
|
||||
JdbcSession(MapSession delegate, String primaryKey, boolean isNew) {
|
||||
this.delegate = delegate;
|
||||
this.primaryKey = primaryKey;
|
||||
this.isNew = isNew;
|
||||
if (this.isNew || (JdbcIndexedSessionRepository.this.saveMode == SaveMode.ALWAYS)) {
|
||||
getAttributeNames().forEach((attributeName) -> this.delta.put(attributeName, DeltaValue.UPDATED));
|
||||
}
|
||||
}
|
||||
|
||||
boolean isNew() {
|
||||
return this.isNew;
|
||||
}
|
||||
|
||||
boolean isChanged() {
|
||||
return this.changed;
|
||||
}
|
||||
|
||||
Map<String, DeltaValue> getDelta() {
|
||||
return this.delta;
|
||||
}
|
||||
|
||||
void clearChangeFlags() {
|
||||
this.isNew = false;
|
||||
this.changed = false;
|
||||
this.delta.clear();
|
||||
}
|
||||
|
||||
Instant getExpiryTime() {
|
||||
return getLastAccessedTime().plus(getMaxInactiveInterval());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.delegate.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String changeSessionId() {
|
||||
this.changed = true;
|
||||
return this.delegate.changeSessionId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getAttribute(String attributeName) {
|
||||
Supplier<T> supplier = this.delegate.getAttribute(attributeName);
|
||||
if (supplier == null) {
|
||||
return null;
|
||||
}
|
||||
T attributeValue = supplier.get();
|
||||
if (attributeValue != null
|
||||
&& JdbcIndexedSessionRepository.this.saveMode.equals(SaveMode.ON_GET_ATTRIBUTE)) {
|
||||
this.delta.put(attributeName, DeltaValue.UPDATED);
|
||||
}
|
||||
return attributeValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAttributeNames() {
|
||||
return this.delegate.getAttributeNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String attributeName, Object attributeValue) {
|
||||
boolean attributeExists = (this.delegate.getAttribute(attributeName) != null);
|
||||
boolean attributeRemoved = (attributeValue == null);
|
||||
if (!attributeExists && attributeRemoved) {
|
||||
return;
|
||||
}
|
||||
if (attributeExists) {
|
||||
if (attributeRemoved) {
|
||||
this.delta.merge(attributeName, DeltaValue.REMOVED,
|
||||
(oldDeltaValue, deltaValue) -> (oldDeltaValue == DeltaValue.ADDED) ? null : deltaValue);
|
||||
}
|
||||
else {
|
||||
this.delta.merge(attributeName, DeltaValue.UPDATED, (oldDeltaValue,
|
||||
deltaValue) -> (oldDeltaValue == DeltaValue.ADDED) ? oldDeltaValue : deltaValue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.delta.merge(attributeName, DeltaValue.ADDED, (oldDeltaValue,
|
||||
deltaValue) -> (oldDeltaValue == DeltaValue.ADDED) ? oldDeltaValue : DeltaValue.UPDATED);
|
||||
}
|
||||
this.delegate.setAttribute(attributeName, value(attributeValue));
|
||||
if (PRINCIPAL_NAME_INDEX_NAME.equals(attributeName) || SPRING_SECURITY_CONTEXT.equals(attributeName)) {
|
||||
this.changed = true;
|
||||
}
|
||||
flushIfRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String attributeName) {
|
||||
setAttribute(attributeName, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getCreationTime() {
|
||||
return this.delegate.getCreationTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastAccessedTime(Instant lastAccessedTime) {
|
||||
this.delegate.setLastAccessedTime(lastAccessedTime);
|
||||
this.changed = true;
|
||||
flushIfRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getLastAccessedTime() {
|
||||
return this.delegate.getLastAccessedTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxInactiveInterval(Duration interval) {
|
||||
this.delegate.setMaxInactiveInterval(interval);
|
||||
this.changed = true;
|
||||
flushIfRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration getMaxInactiveInterval() {
|
||||
return this.delegate.getMaxInactiveInterval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpired() {
|
||||
return this.delegate.isExpired();
|
||||
}
|
||||
|
||||
private void flushIfRequired() {
|
||||
if (JdbcIndexedSessionRepository.this.flushMode == FlushMode.IMMEDIATE) {
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
private void save() {
|
||||
if (this.isNew) {
|
||||
JdbcIndexedSessionRepository.this.transactionOperations.execute(() -> {
|
||||
Map<String, String> indexes = JdbcIndexedSessionRepository.this.indexResolver
|
||||
.resolveIndexesFor(JdbcSession.this);
|
||||
JdbcIndexedSessionRepository.this.jdbcOperations
|
||||
.update(JdbcIndexedSessionRepository.this.createSessionQuery, (ps) -> {
|
||||
ps.setString(1, JdbcSession.this.primaryKey);
|
||||
ps.setString(2, getId());
|
||||
ps.setLong(3, getCreationTime().toEpochMilli());
|
||||
ps.setLong(4, getLastAccessedTime().toEpochMilli());
|
||||
ps.setInt(5, (int) getMaxInactiveInterval().getSeconds());
|
||||
ps.setLong(6, getExpiryTime().toEpochMilli());
|
||||
ps.setString(7, indexes.get(PRINCIPAL_NAME_INDEX_NAME));
|
||||
});
|
||||
Set<String> attributeNames = getAttributeNames();
|
||||
if (!attributeNames.isEmpty()) {
|
||||
insertSessionAttributes(JdbcSession.this, new ArrayList<>(attributeNames));
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
JdbcIndexedSessionRepository.this.transactionOperations.execute(() -> {
|
||||
if (JdbcSession.this.changed) {
|
||||
Map<String, String> indexes = JdbcIndexedSessionRepository.this.indexResolver
|
||||
.resolveIndexesFor(JdbcSession.this);
|
||||
JdbcIndexedSessionRepository.this.jdbcOperations
|
||||
.update(JdbcIndexedSessionRepository.this.updateSessionQuery, (ps) -> {
|
||||
ps.setString(1, getId());
|
||||
ps.setLong(2, getLastAccessedTime().toEpochMilli());
|
||||
ps.setInt(3, (int) getMaxInactiveInterval().getSeconds());
|
||||
ps.setLong(4, getExpiryTime().toEpochMilli());
|
||||
ps.setString(5, indexes.get(PRINCIPAL_NAME_INDEX_NAME));
|
||||
ps.setString(6, JdbcSession.this.primaryKey);
|
||||
});
|
||||
}
|
||||
List<String> addedAttributeNames = JdbcSession.this.delta.entrySet().stream()
|
||||
.filter((entry) -> entry.getValue() == DeltaValue.ADDED).map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
if (!addedAttributeNames.isEmpty()) {
|
||||
insertSessionAttributes(JdbcSession.this, addedAttributeNames);
|
||||
}
|
||||
List<String> updatedAttributeNames = JdbcSession.this.delta.entrySet().stream()
|
||||
.filter((entry) -> entry.getValue() == DeltaValue.UPDATED).map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
if (!updatedAttributeNames.isEmpty()) {
|
||||
updateSessionAttributes(JdbcSession.this, updatedAttributeNames);
|
||||
}
|
||||
List<String> removedAttributeNames = JdbcSession.this.delta.entrySet().stream()
|
||||
.filter((entry) -> entry.getValue() == DeltaValue.REMOVED).map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
if (!removedAttributeNames.isEmpty()) {
|
||||
deleteSessionAttributes(JdbcSession.this, removedAttributeNames);
|
||||
}
|
||||
});
|
||||
}
|
||||
clearChangeFlags();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class SessionResultSetExtractor implements ResultSetExtractor<List<JdbcSession>> {
|
||||
|
||||
@Override
|
||||
public List<JdbcSession> extractData(ResultSet rs) throws SQLException, DataAccessException {
|
||||
List<JdbcSession> sessions = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
String id = rs.getString("SESSION_ID");
|
||||
JdbcSession session;
|
||||
if (sessions.size() > 0 && getLast(sessions).getId().equals(id)) {
|
||||
session = getLast(sessions);
|
||||
}
|
||||
else {
|
||||
MapSession delegate = new MapSession(id);
|
||||
String primaryKey = rs.getString("PRIMARY_ID");
|
||||
delegate.setCreationTime(Instant.ofEpochMilli(rs.getLong("CREATION_TIME")));
|
||||
delegate.setLastAccessedTime(Instant.ofEpochMilli(rs.getLong("LAST_ACCESS_TIME")));
|
||||
delegate.setMaxInactiveInterval(Duration.ofSeconds(rs.getInt("MAX_INACTIVE_INTERVAL")));
|
||||
session = new JdbcSession(delegate, primaryKey, false);
|
||||
}
|
||||
String attributeName = rs.getString("ATTRIBUTE_NAME");
|
||||
if (attributeName != null) {
|
||||
byte[] bytes = getLobHandler().getBlobAsBytes(rs, "ATTRIBUTE_BYTES");
|
||||
session.delegate.setAttribute(attributeName, lazily(() -> deserialize(bytes)));
|
||||
}
|
||||
sessions.add(session);
|
||||
}
|
||||
return sessions;
|
||||
}
|
||||
|
||||
private JdbcSession getLast(List<JdbcSession> sessions) {
|
||||
return sessions.get(sessions.size() - 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,229 +16,25 @@
|
||||
|
||||
package org.springframework.session.jdbc;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.core.serializer.support.DeserializingConverter;
|
||||
import org.springframework.core.serializer.support.SerializingConverter;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
import org.springframework.jdbc.support.lob.DefaultLobHandler;
|
||||
import org.springframework.jdbc.support.lob.LobHandler;
|
||||
import org.springframework.session.DelegatingIndexResolver;
|
||||
import org.springframework.session.FindByIndexNameSessionRepository;
|
||||
import org.springframework.session.FlushMode;
|
||||
import org.springframework.session.IndexResolver;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.PrincipalNameIndexResolver;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionOperations;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.session.SessionRepository} implementation that uses
|
||||
* Spring's {@link JdbcOperations} to store sessions in a relational database. This
|
||||
* implementation does not support publishing of session events.
|
||||
* <p>
|
||||
* An example of how to create a new instance can be seen below:
|
||||
*
|
||||
* <pre class="code">
|
||||
* JdbcTemplate jdbcTemplate = new JdbcTemplate();
|
||||
*
|
||||
* // ... configure jdbcTemplate ...
|
||||
*
|
||||
* TransactionTemplate transactionTemplate = new TransactionTemplate();
|
||||
*
|
||||
* // ... configure transactionTemplate ...
|
||||
*
|
||||
* JdbcOperationsSessionRepository sessionRepository =
|
||||
* new JdbcOperationsSessionRepository(jdbcTemplate, transactionTemplate);
|
||||
* </pre>
|
||||
*
|
||||
* For additional information on how to create and configure {@code JdbcTemplate} and
|
||||
* {@code TransactionTemplate}, refer to the <a href=
|
||||
* "https://docs.spring.io/spring/docs/current/spring-framework-reference/html/spring-data-tier.html">
|
||||
* Spring Framework Reference Documentation</a>.
|
||||
* <p>
|
||||
* By default, this implementation uses <code>SPRING_SESSION</code> and
|
||||
* <code>SPRING_SESSION_ATTRIBUTES</code> tables to store sessions. Note that the table
|
||||
* name can be customized using the {@link #setTableName(String)} method. In that case the
|
||||
* table used to store attributes will be named using the provided table name, suffixed
|
||||
* with <code>_ATTRIBUTES</code>.
|
||||
*
|
||||
* Depending on your database, the table definition can be described as below:
|
||||
*
|
||||
* <pre class="code">
|
||||
* CREATE TABLE SPRING_SESSION (
|
||||
* PRIMARY_ID CHAR(36) NOT NULL,
|
||||
* SESSION_ID CHAR(36) NOT NULL,
|
||||
* CREATION_TIME BIGINT NOT NULL,
|
||||
* LAST_ACCESS_TIME BIGINT NOT NULL,
|
||||
* MAX_INACTIVE_INTERVAL INT NOT NULL,
|
||||
* EXPIRY_TIME BIGINT NOT NULL,
|
||||
* PRINCIPAL_NAME VARCHAR(100),
|
||||
* CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
|
||||
* );
|
||||
*
|
||||
* CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
|
||||
* CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (EXPIRY_TIME);
|
||||
* CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
*
|
||||
* CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
* SESSION_PRIMARY_ID CHAR(36) NOT NULL,
|
||||
* ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
|
||||
* ATTRIBUTE_BYTES BYTEA NOT NULL,
|
||||
* CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
|
||||
* CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
|
||||
* );
|
||||
*
|
||||
* CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
|
||||
* </pre>
|
||||
*
|
||||
* Due to the differences between the various database vendors, especially when it comes
|
||||
* to storing binary data, make sure to use SQL script specific to your database. Scripts
|
||||
* for most major database vendors are packaged as
|
||||
* <code>org/springframework/session/jdbc/schema-*.sql</code>, where <code>*</code> is the
|
||||
* target database type.
|
||||
* This {@link SessionRepository} implementation is kept in order to support migration to
|
||||
* {@link JdbcIndexedSessionRepository} in a backwards compatible manner.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @author Craig Andrews
|
||||
* @since 1.2.0
|
||||
* @deprecated since 2.2.0 in favor of {@link JdbcIndexedSessionRepository}
|
||||
*/
|
||||
public class JdbcOperationsSessionRepository
|
||||
implements FindByIndexNameSessionRepository<JdbcOperationsSessionRepository.JdbcSession> {
|
||||
|
||||
/**
|
||||
* The default name of database table used by Spring Session to store sessions.
|
||||
*/
|
||||
public static final String DEFAULT_TABLE_NAME = "SPRING_SESSION";
|
||||
|
||||
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
|
||||
|
||||
// @formatter:off
|
||||
private static final String CREATE_SESSION_QUERY = "INSERT INTO %TABLE_NAME%(PRIMARY_ID, SESSION_ID, CREATION_TIME, LAST_ACCESS_TIME, MAX_INACTIVE_INTERVAL, EXPIRY_TIME, PRINCIPAL_NAME) "
|
||||
+ "VALUES (?, ?, ?, ?, ?, ?, ?)";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = "INSERT INTO %TABLE_NAME%_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
|
||||
+ "SELECT PRIMARY_ID, ?, ? "
|
||||
+ "FROM %TABLE_NAME% "
|
||||
+ "WHERE SESSION_ID = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String GET_SESSION_QUERY = "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES "
|
||||
+ "FROM %TABLE_NAME% S "
|
||||
+ "LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID "
|
||||
+ "WHERE S.SESSION_ID = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String UPDATE_SESSION_QUERY = "UPDATE %TABLE_NAME% SET SESSION_ID = ?, LAST_ACCESS_TIME = ?, MAX_INACTIVE_INTERVAL = ?, EXPIRY_TIME = ?, PRINCIPAL_NAME = ? "
|
||||
+ "WHERE PRIMARY_ID = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = "UPDATE %TABLE_NAME%_ATTRIBUTES SET ATTRIBUTE_BYTES = ? "
|
||||
+ "WHERE SESSION_PRIMARY_ID = ? "
|
||||
+ "AND ATTRIBUTE_NAME = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String DELETE_SESSION_ATTRIBUTE_QUERY = "DELETE FROM %TABLE_NAME%_ATTRIBUTES "
|
||||
+ "WHERE SESSION_PRIMARY_ID = ? "
|
||||
+ "AND ATTRIBUTE_NAME = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String DELETE_SESSION_QUERY = "DELETE FROM %TABLE_NAME% "
|
||||
+ "WHERE SESSION_ID = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String LIST_SESSIONS_BY_PRINCIPAL_NAME_QUERY = "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES "
|
||||
+ "FROM %TABLE_NAME% S "
|
||||
+ "LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID "
|
||||
+ "WHERE S.PRINCIPAL_NAME = ?";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY = "DELETE FROM %TABLE_NAME% "
|
||||
+ "WHERE EXPIRY_TIME < ?";
|
||||
// @formatter:on
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JdbcOperationsSessionRepository.class);
|
||||
|
||||
private final JdbcOperations jdbcOperations;
|
||||
|
||||
private final TransactionOperations transactionOperations;
|
||||
|
||||
private final ResultSetExtractor<List<JdbcSession>> extractor = new SessionResultSetExtractor();
|
||||
|
||||
private final IndexResolver<JdbcSession> indexResolver;
|
||||
|
||||
/**
|
||||
* The name of database table used by Spring Session to store sessions.
|
||||
*/
|
||||
private String tableName = DEFAULT_TABLE_NAME;
|
||||
|
||||
private String createSessionQuery;
|
||||
|
||||
private String createSessionAttributeQuery;
|
||||
|
||||
private String getSessionQuery;
|
||||
|
||||
private String updateSessionQuery;
|
||||
|
||||
private String updateSessionAttributeQuery;
|
||||
|
||||
private String deleteSessionAttributeQuery;
|
||||
|
||||
private String deleteSessionQuery;
|
||||
|
||||
private String listSessionsByPrincipalNameQuery;
|
||||
|
||||
private String deleteSessionsByExpiryTimeQuery;
|
||||
|
||||
/**
|
||||
* If non-null, this value is used to override the default value for
|
||||
* {@link JdbcSession#setMaxInactiveInterval(Duration)}.
|
||||
*/
|
||||
private Integer defaultMaxInactiveInterval;
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private LobHandler lobHandler;
|
||||
|
||||
private FlushMode flushMode = FlushMode.ON_SAVE;
|
||||
|
||||
private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE;
|
||||
@Deprecated
|
||||
public class JdbcOperationsSessionRepository extends JdbcIndexedSessionRepository {
|
||||
|
||||
/**
|
||||
* Create a new {@link JdbcOperationsSessionRepository} instance which uses the
|
||||
@@ -246,346 +42,42 @@ public class JdbcOperationsSessionRepository
|
||||
* sessions.
|
||||
* @param jdbcOperations the {@link JdbcOperations} to use
|
||||
* @param transactionOperations the {@link TransactionOperations} to use
|
||||
* @see JdbcIndexedSessionRepository#JdbcIndexedSessionRepository(JdbcOperations,
|
||||
* TransactionOperations)
|
||||
*/
|
||||
public JdbcOperationsSessionRepository(JdbcOperations jdbcOperations, TransactionOperations transactionOperations) {
|
||||
Assert.notNull(jdbcOperations, "jdbcOperations must not be null");
|
||||
Assert.notNull(transactionOperations, "transactionOperations must not be null");
|
||||
this.jdbcOperations = jdbcOperations;
|
||||
this.transactionOperations = transactionOperations;
|
||||
this.indexResolver = new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>());
|
||||
this.conversionService = createDefaultConversionService();
|
||||
this.lobHandler = new DefaultLobHandler();
|
||||
prepareQueries();
|
||||
super(jdbcOperations, transactionOperations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link JdbcOperationsSessionRepository} instance which uses the
|
||||
* provided {@link JdbcOperations} to manage sessions.
|
||||
* Create a new {@link JdbcIndexedSessionRepository} instance which uses the provided
|
||||
* {@link JdbcOperations} to manage sessions.
|
||||
* <p>
|
||||
* The created instance will execute all data access operations in a transaction with
|
||||
* propagation level of {@link TransactionDefinition#PROPAGATION_REQUIRES_NEW}.
|
||||
* @param jdbcOperations the {@link JdbcOperations} to use
|
||||
* @param transactionManager the {@link PlatformTransactionManager} to use
|
||||
* @deprecated since 2.2.0 in favor of
|
||||
* {@link #JdbcOperationsSessionRepository(JdbcOperations, TransactionOperations)}
|
||||
* {@link JdbcIndexedSessionRepository#JdbcIndexedSessionRepository(JdbcOperations, TransactionOperations)}
|
||||
*/
|
||||
@Deprecated
|
||||
public JdbcOperationsSessionRepository(JdbcOperations jdbcOperations,
|
||||
PlatformTransactionManager transactionManager) {
|
||||
this(jdbcOperations, createTransactionTemplate(transactionManager));
|
||||
super(jdbcOperations, createTransactionTemplate(transactionManager));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link JdbcOperationsSessionRepository} instance which uses the
|
||||
* provided {@link JdbcOperations} to manage sessions.
|
||||
* Create a new {@link JdbcIndexedSessionRepository} instance which uses the provided
|
||||
* {@link JdbcOperations} to manage sessions.
|
||||
* <p>
|
||||
* The created instance will not execute data access operations in a transaction.
|
||||
* @param jdbcOperations the {@link JdbcOperations} to use
|
||||
* @deprecated since 2.2.0 in favor of
|
||||
* {@link #JdbcOperationsSessionRepository(JdbcOperations, TransactionOperations)}
|
||||
* {@link JdbcIndexedSessionRepository#JdbcIndexedSessionRepository(JdbcOperations, TransactionOperations)}
|
||||
*/
|
||||
@Deprecated
|
||||
public JdbcOperationsSessionRepository(JdbcOperations jdbcOperations) {
|
||||
this(jdbcOperations, TransactionOperations.withoutTransaction());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of database table used to store sessions.
|
||||
* @param tableName the database table name
|
||||
*/
|
||||
public void setTableName(String tableName) {
|
||||
Assert.hasText(tableName, "Table name must not be empty");
|
||||
this.tableName = tableName.trim();
|
||||
prepareQueries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to create the session.
|
||||
* @param createSessionQuery the SQL query string
|
||||
*/
|
||||
public void setCreateSessionQuery(String createSessionQuery) {
|
||||
Assert.hasText(createSessionQuery, "Query must not be empty");
|
||||
this.createSessionQuery = createSessionQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to create the session attribute.
|
||||
* @param createSessionAttributeQuery the SQL query string
|
||||
*/
|
||||
public void setCreateSessionAttributeQuery(String createSessionAttributeQuery) {
|
||||
Assert.hasText(createSessionAttributeQuery, "Query must not be empty");
|
||||
this.createSessionAttributeQuery = createSessionAttributeQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to retrieve the session.
|
||||
* @param getSessionQuery the SQL query string
|
||||
*/
|
||||
public void setGetSessionQuery(String getSessionQuery) {
|
||||
Assert.hasText(getSessionQuery, "Query must not be empty");
|
||||
this.getSessionQuery = getSessionQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to update the session.
|
||||
* @param updateSessionQuery the SQL query string
|
||||
*/
|
||||
public void setUpdateSessionQuery(String updateSessionQuery) {
|
||||
Assert.hasText(updateSessionQuery, "Query must not be empty");
|
||||
this.updateSessionQuery = updateSessionQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to update the session attribute.
|
||||
* @param updateSessionAttributeQuery the SQL query string
|
||||
*/
|
||||
public void setUpdateSessionAttributeQuery(String updateSessionAttributeQuery) {
|
||||
Assert.hasText(updateSessionAttributeQuery, "Query must not be empty");
|
||||
this.updateSessionAttributeQuery = updateSessionAttributeQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to delete the session attribute.
|
||||
* @param deleteSessionAttributeQuery the SQL query string
|
||||
*/
|
||||
public void setDeleteSessionAttributeQuery(String deleteSessionAttributeQuery) {
|
||||
Assert.hasText(deleteSessionAttributeQuery, "Query must not be empty");
|
||||
this.deleteSessionAttributeQuery = deleteSessionAttributeQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to delete the session.
|
||||
* @param deleteSessionQuery the SQL query string
|
||||
*/
|
||||
public void setDeleteSessionQuery(String deleteSessionQuery) {
|
||||
Assert.hasText(deleteSessionQuery, "Query must not be empty");
|
||||
this.deleteSessionQuery = deleteSessionQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to retrieve the sessions by principal name.
|
||||
* @param listSessionsByPrincipalNameQuery the SQL query string
|
||||
*/
|
||||
public void setListSessionsByPrincipalNameQuery(String listSessionsByPrincipalNameQuery) {
|
||||
Assert.hasText(listSessionsByPrincipalNameQuery, "Query must not be empty");
|
||||
this.listSessionsByPrincipalNameQuery = listSessionsByPrincipalNameQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom SQL query used to delete the sessions by last access time.
|
||||
* @param deleteSessionsByExpiryTimeQuery the SQL query string
|
||||
*/
|
||||
public void setDeleteSessionsByExpiryTimeQuery(String deleteSessionsByExpiryTimeQuery) {
|
||||
Assert.hasText(deleteSessionsByExpiryTimeQuery, "Query must not be empty");
|
||||
this.deleteSessionsByExpiryTimeQuery = deleteSessionsByExpiryTimeQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum inactive interval in seconds between requests before newly created
|
||||
* sessions will be invalidated. A negative time indicates that the session will never
|
||||
* timeout. The default is 1800 (30 minutes).
|
||||
* @param defaultMaxInactiveInterval the maximum inactive interval in seconds
|
||||
*/
|
||||
public void setDefaultMaxInactiveInterval(Integer defaultMaxInactiveInterval) {
|
||||
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
|
||||
}
|
||||
|
||||
public void setLobHandler(LobHandler lobHandler) {
|
||||
Assert.notNull(lobHandler, "LobHandler must not be null");
|
||||
this.lobHandler = lobHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link ConversionService} to use.
|
||||
* @param conversionService the converter to set
|
||||
*/
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
Assert.notNull(conversionService, "conversionService must not be null");
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the flush mode. Default is {@link FlushMode#ON_SAVE}.
|
||||
* @param flushMode the flush mode
|
||||
*/
|
||||
public void setFlushMode(FlushMode flushMode) {
|
||||
Assert.notNull(flushMode, "flushMode must not be null");
|
||||
this.flushMode = flushMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the save mode.
|
||||
* @param saveMode the save mode
|
||||
*/
|
||||
public void setSaveMode(SaveMode saveMode) {
|
||||
Assert.notNull(saveMode, "saveMode must not be null");
|
||||
this.saveMode = saveMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcSession createSession() {
|
||||
MapSession delegate = new MapSession();
|
||||
if (this.defaultMaxInactiveInterval != null) {
|
||||
delegate.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
|
||||
}
|
||||
JdbcSession session = new JdbcSession(delegate, UUID.randomUUID().toString(), true);
|
||||
session.flushIfRequired();
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final JdbcSession session) {
|
||||
session.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcSession findById(final String id) {
|
||||
final JdbcSession session = this.transactionOperations.execute((status) -> {
|
||||
List<JdbcSession> sessions = JdbcOperationsSessionRepository.this.jdbcOperations.query(
|
||||
JdbcOperationsSessionRepository.this.getSessionQuery, (ps) -> ps.setString(1, id),
|
||||
JdbcOperationsSessionRepository.this.extractor);
|
||||
if (sessions.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return sessions.get(0);
|
||||
});
|
||||
|
||||
if (session != null) {
|
||||
if (session.isExpired()) {
|
||||
deleteById(id);
|
||||
}
|
||||
else {
|
||||
return session;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteById(final String id) {
|
||||
this.transactionOperations.execute(() -> JdbcOperationsSessionRepository.this.jdbcOperations
|
||||
.update(JdbcOperationsSessionRepository.this.deleteSessionQuery, id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, JdbcSession> findByIndexNameAndIndexValue(String indexName, final String indexValue) {
|
||||
if (!PRINCIPAL_NAME_INDEX_NAME.equals(indexName)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
List<JdbcSession> sessions = this.transactionOperations
|
||||
.execute((status) -> JdbcOperationsSessionRepository.this.jdbcOperations.query(
|
||||
JdbcOperationsSessionRepository.this.listSessionsByPrincipalNameQuery,
|
||||
(ps) -> ps.setString(1, indexValue), JdbcOperationsSessionRepository.this.extractor));
|
||||
|
||||
Map<String, JdbcSession> sessionMap = new HashMap<>(sessions.size());
|
||||
|
||||
for (JdbcSession session : sessions) {
|
||||
sessionMap.put(session.getId(), session);
|
||||
}
|
||||
|
||||
return sessionMap;
|
||||
}
|
||||
|
||||
private void insertSessionAttributes(JdbcSession session, List<String> attributeNames) {
|
||||
Assert.notEmpty(attributeNames, "attributeNames must not be null or empty");
|
||||
if (attributeNames.size() > 1) {
|
||||
this.jdbcOperations.batchUpdate(this.createSessionAttributeQuery, new BatchPreparedStatementSetter() {
|
||||
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
String attributeName = attributeNames.get(i);
|
||||
ps.setString(1, attributeName);
|
||||
getLobHandler().getLobCreator().setBlobAsBytes(ps, 2,
|
||||
serialize(session.getAttribute(attributeName)));
|
||||
ps.setString(3, session.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return attributeNames.size();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.jdbcOperations.update(this.createSessionAttributeQuery, (ps) -> {
|
||||
String attributeName = attributeNames.get(0);
|
||||
ps.setString(1, attributeName);
|
||||
getLobHandler().getLobCreator().setBlobAsBytes(ps, 2, serialize(session.getAttribute(attributeName)));
|
||||
ps.setString(3, session.getId());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSessionAttributes(JdbcSession session, List<String> attributeNames) {
|
||||
Assert.notEmpty(attributeNames, "attributeNames must not be null or empty");
|
||||
if (attributeNames.size() > 1) {
|
||||
this.jdbcOperations.batchUpdate(this.updateSessionAttributeQuery, new BatchPreparedStatementSetter() {
|
||||
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
String attributeName = attributeNames.get(i);
|
||||
getLobHandler().getLobCreator().setBlobAsBytes(ps, 1,
|
||||
serialize(session.getAttribute(attributeName)));
|
||||
ps.setString(2, session.primaryKey);
|
||||
ps.setString(3, attributeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return attributeNames.size();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.jdbcOperations.update(this.updateSessionAttributeQuery, (ps) -> {
|
||||
String attributeName = attributeNames.get(0);
|
||||
getLobHandler().getLobCreator().setBlobAsBytes(ps, 1, serialize(session.getAttribute(attributeName)));
|
||||
ps.setString(2, session.primaryKey);
|
||||
ps.setString(3, attributeName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteSessionAttributes(JdbcSession session, List<String> attributeNames) {
|
||||
Assert.notEmpty(attributeNames, "attributeNames must not be null or empty");
|
||||
if (attributeNames.size() > 1) {
|
||||
this.jdbcOperations.batchUpdate(this.deleteSessionAttributeQuery, new BatchPreparedStatementSetter() {
|
||||
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
String attributeName = attributeNames.get(i);
|
||||
ps.setString(1, session.primaryKey);
|
||||
ps.setString(2, attributeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return attributeNames.size();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.jdbcOperations.update(this.deleteSessionAttributeQuery, (ps) -> {
|
||||
String attributeName = attributeNames.get(0);
|
||||
ps.setString(1, session.primaryKey);
|
||||
ps.setString(2, attributeName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanUpExpiredSessions() {
|
||||
Integer deletedCount = this.transactionOperations
|
||||
.execute((status) -> JdbcOperationsSessionRepository.this.jdbcOperations.update(
|
||||
JdbcOperationsSessionRepository.this.deleteSessionsByExpiryTimeQuery,
|
||||
System.currentTimeMillis()));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cleaned up " + deletedCount + " expired sessions");
|
||||
}
|
||||
super(jdbcOperations, TransactionOperations.withoutTransaction());
|
||||
}
|
||||
|
||||
private static TransactionTemplate createTransactionTemplate(PlatformTransactionManager transactionManager) {
|
||||
@@ -596,316 +88,4 @@ public class JdbcOperationsSessionRepository
|
||||
return transactionTemplate;
|
||||
}
|
||||
|
||||
private static GenericConversionService createDefaultConversionService() {
|
||||
GenericConversionService converter = new GenericConversionService();
|
||||
converter.addConverter(Object.class, byte[].class, new SerializingConverter());
|
||||
converter.addConverter(byte[].class, Object.class, new DeserializingConverter());
|
||||
return converter;
|
||||
}
|
||||
|
||||
private String getQuery(String base) {
|
||||
return StringUtils.replace(base, "%TABLE_NAME%", this.tableName);
|
||||
}
|
||||
|
||||
private void prepareQueries() {
|
||||
this.createSessionQuery = getQuery(CREATE_SESSION_QUERY);
|
||||
this.createSessionAttributeQuery = getQuery(CREATE_SESSION_ATTRIBUTE_QUERY);
|
||||
this.getSessionQuery = getQuery(GET_SESSION_QUERY);
|
||||
this.updateSessionQuery = getQuery(UPDATE_SESSION_QUERY);
|
||||
this.updateSessionAttributeQuery = getQuery(UPDATE_SESSION_ATTRIBUTE_QUERY);
|
||||
this.deleteSessionAttributeQuery = getQuery(DELETE_SESSION_ATTRIBUTE_QUERY);
|
||||
this.deleteSessionQuery = getQuery(DELETE_SESSION_QUERY);
|
||||
this.listSessionsByPrincipalNameQuery = getQuery(LIST_SESSIONS_BY_PRINCIPAL_NAME_QUERY);
|
||||
this.deleteSessionsByExpiryTimeQuery = getQuery(DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY);
|
||||
}
|
||||
|
||||
private LobHandler getLobHandler() {
|
||||
return this.lobHandler;
|
||||
}
|
||||
|
||||
private byte[] serialize(Object object) {
|
||||
return (byte[]) this.conversionService.convert(object, TypeDescriptor.valueOf(Object.class),
|
||||
TypeDescriptor.valueOf(byte[].class));
|
||||
}
|
||||
|
||||
private Object deserialize(byte[] bytes) {
|
||||
return this.conversionService.convert(bytes, TypeDescriptor.valueOf(byte[].class),
|
||||
TypeDescriptor.valueOf(Object.class));
|
||||
}
|
||||
|
||||
private enum DeltaValue {
|
||||
|
||||
ADDED, UPDATED, REMOVED
|
||||
|
||||
}
|
||||
|
||||
private static <T> Supplier<T> value(T value) {
|
||||
return (value != null) ? () -> value : null;
|
||||
}
|
||||
|
||||
private static <T> Supplier<T> lazily(Supplier<T> supplier) {
|
||||
Supplier<T> lazySupplier = new Supplier<T>() {
|
||||
|
||||
private T value;
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
if (this.value == null) {
|
||||
this.value = supplier.get();
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return (supplier != null) ? lazySupplier : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link Session} to use for {@link JdbcOperationsSessionRepository}.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
final class JdbcSession implements Session {
|
||||
|
||||
private final Session delegate;
|
||||
|
||||
private final String primaryKey;
|
||||
|
||||
private boolean isNew;
|
||||
|
||||
private boolean changed;
|
||||
|
||||
private Map<String, DeltaValue> delta = new HashMap<>();
|
||||
|
||||
JdbcSession(MapSession delegate, String primaryKey, boolean isNew) {
|
||||
this.delegate = delegate;
|
||||
this.primaryKey = primaryKey;
|
||||
this.isNew = isNew;
|
||||
if (this.isNew || (JdbcOperationsSessionRepository.this.saveMode == SaveMode.ALWAYS)) {
|
||||
getAttributeNames().forEach((attributeName) -> this.delta.put(attributeName, DeltaValue.UPDATED));
|
||||
}
|
||||
}
|
||||
|
||||
boolean isNew() {
|
||||
return this.isNew;
|
||||
}
|
||||
|
||||
boolean isChanged() {
|
||||
return this.changed;
|
||||
}
|
||||
|
||||
Map<String, DeltaValue> getDelta() {
|
||||
return this.delta;
|
||||
}
|
||||
|
||||
void clearChangeFlags() {
|
||||
this.isNew = false;
|
||||
this.changed = false;
|
||||
this.delta.clear();
|
||||
}
|
||||
|
||||
Instant getExpiryTime() {
|
||||
return getLastAccessedTime().plus(getMaxInactiveInterval());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.delegate.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String changeSessionId() {
|
||||
this.changed = true;
|
||||
return this.delegate.changeSessionId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getAttribute(String attributeName) {
|
||||
Supplier<T> supplier = this.delegate.getAttribute(attributeName);
|
||||
if (supplier == null) {
|
||||
return null;
|
||||
}
|
||||
T attributeValue = supplier.get();
|
||||
if (attributeValue != null
|
||||
&& JdbcOperationsSessionRepository.this.saveMode.equals(SaveMode.ON_GET_ATTRIBUTE)) {
|
||||
this.delta.put(attributeName, DeltaValue.UPDATED);
|
||||
}
|
||||
return attributeValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAttributeNames() {
|
||||
return this.delegate.getAttributeNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String attributeName, Object attributeValue) {
|
||||
boolean attributeExists = (this.delegate.getAttribute(attributeName) != null);
|
||||
boolean attributeRemoved = (attributeValue == null);
|
||||
if (!attributeExists && attributeRemoved) {
|
||||
return;
|
||||
}
|
||||
if (attributeExists) {
|
||||
if (attributeRemoved) {
|
||||
this.delta.merge(attributeName, DeltaValue.REMOVED,
|
||||
(oldDeltaValue, deltaValue) -> (oldDeltaValue == DeltaValue.ADDED) ? null : deltaValue);
|
||||
}
|
||||
else {
|
||||
this.delta.merge(attributeName, DeltaValue.UPDATED, (oldDeltaValue,
|
||||
deltaValue) -> (oldDeltaValue == DeltaValue.ADDED) ? oldDeltaValue : deltaValue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.delta.merge(attributeName, DeltaValue.ADDED, (oldDeltaValue,
|
||||
deltaValue) -> (oldDeltaValue == DeltaValue.ADDED) ? oldDeltaValue : DeltaValue.UPDATED);
|
||||
}
|
||||
this.delegate.setAttribute(attributeName, value(attributeValue));
|
||||
if (PRINCIPAL_NAME_INDEX_NAME.equals(attributeName) || SPRING_SECURITY_CONTEXT.equals(attributeName)) {
|
||||
this.changed = true;
|
||||
}
|
||||
flushIfRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String attributeName) {
|
||||
setAttribute(attributeName, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getCreationTime() {
|
||||
return this.delegate.getCreationTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastAccessedTime(Instant lastAccessedTime) {
|
||||
this.delegate.setLastAccessedTime(lastAccessedTime);
|
||||
this.changed = true;
|
||||
flushIfRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getLastAccessedTime() {
|
||||
return this.delegate.getLastAccessedTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxInactiveInterval(Duration interval) {
|
||||
this.delegate.setMaxInactiveInterval(interval);
|
||||
this.changed = true;
|
||||
flushIfRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration getMaxInactiveInterval() {
|
||||
return this.delegate.getMaxInactiveInterval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpired() {
|
||||
return this.delegate.isExpired();
|
||||
}
|
||||
|
||||
private void flushIfRequired() {
|
||||
if (JdbcOperationsSessionRepository.this.flushMode == FlushMode.IMMEDIATE) {
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
private void save() {
|
||||
if (this.isNew) {
|
||||
JdbcOperationsSessionRepository.this.transactionOperations.execute(() -> {
|
||||
Map<String, String> indexes = JdbcOperationsSessionRepository.this.indexResolver
|
||||
.resolveIndexesFor(JdbcSession.this);
|
||||
JdbcOperationsSessionRepository.this.jdbcOperations
|
||||
.update(JdbcOperationsSessionRepository.this.createSessionQuery, (ps) -> {
|
||||
ps.setString(1, JdbcSession.this.primaryKey);
|
||||
ps.setString(2, getId());
|
||||
ps.setLong(3, getCreationTime().toEpochMilli());
|
||||
ps.setLong(4, getLastAccessedTime().toEpochMilli());
|
||||
ps.setInt(5, (int) getMaxInactiveInterval().getSeconds());
|
||||
ps.setLong(6, getExpiryTime().toEpochMilli());
|
||||
ps.setString(7, indexes.get(PRINCIPAL_NAME_INDEX_NAME));
|
||||
});
|
||||
Set<String> attributeNames = getAttributeNames();
|
||||
if (!attributeNames.isEmpty()) {
|
||||
insertSessionAttributes(JdbcSession.this, new ArrayList<>(attributeNames));
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
JdbcOperationsSessionRepository.this.transactionOperations.execute(() -> {
|
||||
if (JdbcSession.this.changed) {
|
||||
Map<String, String> indexes = JdbcOperationsSessionRepository.this.indexResolver
|
||||
.resolveIndexesFor(JdbcSession.this);
|
||||
JdbcOperationsSessionRepository.this.jdbcOperations
|
||||
.update(JdbcOperationsSessionRepository.this.updateSessionQuery, (ps) -> {
|
||||
ps.setString(1, getId());
|
||||
ps.setLong(2, getLastAccessedTime().toEpochMilli());
|
||||
ps.setInt(3, (int) getMaxInactiveInterval().getSeconds());
|
||||
ps.setLong(4, getExpiryTime().toEpochMilli());
|
||||
ps.setString(5, indexes.get(PRINCIPAL_NAME_INDEX_NAME));
|
||||
ps.setString(6, JdbcSession.this.primaryKey);
|
||||
});
|
||||
}
|
||||
List<String> addedAttributeNames = JdbcSession.this.delta.entrySet().stream()
|
||||
.filter((entry) -> entry.getValue() == DeltaValue.ADDED).map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
if (!addedAttributeNames.isEmpty()) {
|
||||
insertSessionAttributes(JdbcSession.this, addedAttributeNames);
|
||||
}
|
||||
List<String> updatedAttributeNames = JdbcSession.this.delta.entrySet().stream()
|
||||
.filter((entry) -> entry.getValue() == DeltaValue.UPDATED).map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
if (!updatedAttributeNames.isEmpty()) {
|
||||
updateSessionAttributes(JdbcSession.this, updatedAttributeNames);
|
||||
}
|
||||
List<String> removedAttributeNames = JdbcSession.this.delta.entrySet().stream()
|
||||
.filter((entry) -> entry.getValue() == DeltaValue.REMOVED).map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
if (!removedAttributeNames.isEmpty()) {
|
||||
deleteSessionAttributes(JdbcSession.this, removedAttributeNames);
|
||||
}
|
||||
});
|
||||
}
|
||||
clearChangeFlags();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class SessionResultSetExtractor implements ResultSetExtractor<List<JdbcSession>> {
|
||||
|
||||
@Override
|
||||
public List<JdbcSession> extractData(ResultSet rs) throws SQLException, DataAccessException {
|
||||
List<JdbcSession> sessions = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
String id = rs.getString("SESSION_ID");
|
||||
JdbcSession session;
|
||||
if (sessions.size() > 0 && getLast(sessions).getId().equals(id)) {
|
||||
session = getLast(sessions);
|
||||
}
|
||||
else {
|
||||
MapSession delegate = new MapSession(id);
|
||||
String primaryKey = rs.getString("PRIMARY_ID");
|
||||
delegate.setCreationTime(Instant.ofEpochMilli(rs.getLong("CREATION_TIME")));
|
||||
delegate.setLastAccessedTime(Instant.ofEpochMilli(rs.getLong("LAST_ACCESS_TIME")));
|
||||
delegate.setMaxInactiveInterval(Duration.ofSeconds(rs.getInt("MAX_INACTIVE_INTERVAL")));
|
||||
session = new JdbcSession(delegate, primaryKey, false);
|
||||
}
|
||||
String attributeName = rs.getString("ATTRIBUTE_NAME");
|
||||
if (attributeName != null) {
|
||||
byte[] bytes = getLobHandler().getBlobAsBytes(rs, "ATTRIBUTE_BYTES");
|
||||
session.delegate.setAttribute(attributeName, lazily(() -> deserialize(bytes)));
|
||||
}
|
||||
sessions.add(session);
|
||||
}
|
||||
return sessions;
|
||||
}
|
||||
|
||||
private JdbcSession getLast(List<JdbcSession> sessions) {
|
||||
return sessions.get(sessions.size() - 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@ import java.lang.annotation.Target;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.session.jdbc.JdbcOperationsSessionRepository;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
|
||||
|
||||
/**
|
||||
* Qualifier annotation for a {@link DataSource} to be injected in
|
||||
* {@link JdbcOperationsSessionRepository}.
|
||||
* {@link JdbcIndexedSessionRepository}.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @since 2.0.0
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
|
||||
import org.springframework.session.jdbc.JdbcOperationsSessionRepository;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
|
||||
/**
|
||||
@@ -91,7 +91,7 @@ public @interface EnableJdbcHttpSession {
|
||||
* The name of database table used by Spring Session to store sessions.
|
||||
* @return the database table name
|
||||
*/
|
||||
String tableName() default JdbcOperationsSessionRepository.DEFAULT_TABLE_NAME;
|
||||
String tableName() default JdbcIndexedSessionRepository.DEFAULT_TABLE_NAME;
|
||||
|
||||
/**
|
||||
* The cron expression for expired session cleanup job. By default runs every minute.
|
||||
|
||||
@@ -49,7 +49,7 @@ import org.springframework.session.MapSession;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.config.SessionRepositoryCustomizer;
|
||||
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
|
||||
import org.springframework.session.jdbc.JdbcOperationsSessionRepository;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
|
||||
import org.springframework.session.jdbc.config.annotation.SpringSessionDataSource;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
@@ -81,7 +81,7 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration
|
||||
|
||||
private Integer maxInactiveIntervalInSeconds = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
|
||||
|
||||
private String tableName = JdbcOperationsSessionRepository.DEFAULT_TABLE_NAME;
|
||||
private String tableName = JdbcIndexedSessionRepository.DEFAULT_TABLE_NAME;
|
||||
|
||||
private String cleanupCron = DEFAULT_CLEANUP_CRON;
|
||||
|
||||
@@ -101,19 +101,19 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private List<SessionRepositoryCustomizer<JdbcOperationsSessionRepository>> sessionRepositoryCustomizers;
|
||||
private List<SessionRepositoryCustomizer<JdbcIndexedSessionRepository>> sessionRepositoryCustomizers;
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
@Bean
|
||||
public JdbcOperationsSessionRepository sessionRepository() {
|
||||
public JdbcIndexedSessionRepository sessionRepository() {
|
||||
JdbcTemplate jdbcTemplate = createJdbcTemplate(this.dataSource);
|
||||
if (this.transactionOperations == null) {
|
||||
this.transactionOperations = createTransactionTemplate(this.transactionManager);
|
||||
}
|
||||
JdbcOperationsSessionRepository sessionRepository = new JdbcOperationsSessionRepository(jdbcTemplate,
|
||||
JdbcIndexedSessionRepository sessionRepository = new JdbcIndexedSessionRepository(jdbcTemplate,
|
||||
this.transactionOperations);
|
||||
if (StringUtils.hasText(this.tableName)) {
|
||||
sessionRepository.setTableName(this.tableName);
|
||||
@@ -214,7 +214,7 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setSessionRepositoryCustomizer(
|
||||
ObjectProvider<SessionRepositoryCustomizer<JdbcOperationsSessionRepository>> sessionRepositoryCustomizers) {
|
||||
ObjectProvider<SessionRepositoryCustomizer<JdbcIndexedSessionRepository>> sessionRepositoryCustomizers) {
|
||||
this.sessionRepositoryCustomizers = sessionRepositoryCustomizers.orderedStream().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,7 @@ import org.springframework.session.FlushMode;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.jdbc.JdbcOperationsSessionRepository.JdbcSession;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository.JdbcSession;
|
||||
import org.springframework.transaction.support.TransactionOperations;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -59,51 +58,41 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
/**
|
||||
* Tests for {@link JdbcOperationsSessionRepository}.
|
||||
* Tests for {@link JdbcIndexedSessionRepository}.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @author Craig Andrews
|
||||
* @since 1.2.0
|
||||
*/
|
||||
class JdbcOperationsSessionRepositoryTests {
|
||||
class JdbcIndexedSessionRepositoryTests {
|
||||
|
||||
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
|
||||
|
||||
@Mock
|
||||
private JdbcOperations jdbcOperations;
|
||||
|
||||
private JdbcOperationsSessionRepository repository;
|
||||
private JdbcIndexedSessionRepository repository;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
this.repository = new JdbcOperationsSessionRepository(this.jdbcOperations,
|
||||
this.repository = new JdbcIndexedSessionRepository(this.jdbcOperations,
|
||||
TransactionOperations.withoutTransaction());
|
||||
}
|
||||
|
||||
@Test
|
||||
void constructorNullJdbcOperations() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new JdbcOperationsSessionRepository(null, TransactionOperations.withoutTransaction()))
|
||||
.isThrownBy(() -> new JdbcIndexedSessionRepository(null, TransactionOperations.withoutTransaction()))
|
||||
.withMessage("jdbcOperations must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void constructorNullTransactionOperations() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(
|
||||
() -> new JdbcOperationsSessionRepository(this.jdbcOperations, (TransactionOperations) null))
|
||||
.isThrownBy(() -> new JdbcIndexedSessionRepository(this.jdbcOperations, null))
|
||||
.withMessage("transactionOperations must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
void constructorNullTransactionManager() {
|
||||
assertThatIllegalArgumentException().isThrownBy(
|
||||
() -> new JdbcOperationsSessionRepository(this.jdbcOperations, (PlatformTransactionManager) null))
|
||||
.withMessage("transactionManager must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void setTableNameNull() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setTableName(null))
|
||||
@@ -250,7 +239,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void createSessionDefaultMaxInactiveInterval() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
|
||||
assertThat(session.isNew()).isTrue();
|
||||
assertThat(session.getMaxInactiveInterval()).isEqualTo(new MapSession().getMaxInactiveInterval());
|
||||
@@ -262,7 +251,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
int interval = 1;
|
||||
this.repository.setDefaultMaxInactiveInterval(interval);
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
|
||||
assertThat(session.isNew()).isTrue();
|
||||
assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(interval));
|
||||
@@ -280,7 +269,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void saveNewWithoutAttributes() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
@@ -291,7 +280,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void saveNewWithSingleAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
session.setAttribute("testName", "testValue");
|
||||
|
||||
this.repository.save(session);
|
||||
@@ -306,7 +295,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void saveNewWithMultipleAttributes() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
session.setAttribute("testName1", "testValue1");
|
||||
session.setAttribute("testName2", "testValue2");
|
||||
|
||||
@@ -322,8 +311,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void saveUpdatedAddSingleAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
session.setAttribute("testName", "testValue");
|
||||
|
||||
this.repository.save(session);
|
||||
@@ -336,8 +324,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void saveUpdatedAddMultipleAttributes() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
session.setAttribute("testName1", "testValue1");
|
||||
session.setAttribute("testName2", "testValue2");
|
||||
|
||||
@@ -351,8 +338,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void saveUpdatedModifySingleAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
session.setAttribute("testName", "testValue");
|
||||
session.clearChangeFlags();
|
||||
session.setAttribute("testName", "testValue");
|
||||
@@ -367,8 +353,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void saveUpdatedModifyMultipleAttributes() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
session.setAttribute("testName1", "testValue1");
|
||||
session.setAttribute("testName2", "testValue2");
|
||||
session.clearChangeFlags();
|
||||
@@ -385,8 +370,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void saveUpdatedRemoveSingleAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
session.setAttribute("testName", "testValue");
|
||||
session.clearChangeFlags();
|
||||
session.removeAttribute("testName");
|
||||
@@ -401,8 +385,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void saveUpdatedRemoveNonExistingAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
session.removeAttribute("testName");
|
||||
|
||||
this.repository.save(session);
|
||||
@@ -413,8 +396,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void saveUpdatedRemoveMultipleAttributes() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
session.setAttribute("testName1", "testValue1");
|
||||
session.setAttribute("testName2", "testValue2");
|
||||
session.clearChangeFlags();
|
||||
@@ -431,8 +413,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test // gh-1070
|
||||
void saveUpdatedAddAndModifyAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
session.setAttribute("testName", "testValue1");
|
||||
session.setAttribute("testName", "testValue2");
|
||||
|
||||
@@ -446,8 +427,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test // gh-1070
|
||||
void saveUpdatedAddAndRemoveAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
session.setAttribute("testName", "testValue");
|
||||
session.removeAttribute("testName");
|
||||
|
||||
@@ -459,8 +439,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test // gh-1070
|
||||
void saveUpdatedModifyAndRemoveAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
session.setAttribute("testName", "testValue1");
|
||||
session.clearChangeFlags();
|
||||
session.setAttribute("testName", "testValue2");
|
||||
@@ -476,8 +455,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test // gh-1070
|
||||
void saveUpdatedRemoveAndAddAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
session.setAttribute("testName", "testValue1");
|
||||
session.clearChangeFlags();
|
||||
session.removeAttribute("testName");
|
||||
@@ -493,8 +471,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void saveUpdatedLastAccessedTime() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
session.setLastAccessedTime(Instant.now());
|
||||
|
||||
this.repository.save(session);
|
||||
@@ -507,8 +484,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
void saveUnchanged() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(new MapSession(),
|
||||
"primaryKey", false);
|
||||
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
@@ -523,7 +499,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
given(this.jdbcOperations.query(isA(String.class), isA(PreparedStatementSetter.class),
|
||||
isA(ResultSetExtractor.class))).willReturn(Collections.emptyList());
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.findById(sessionId);
|
||||
JdbcSession session = this.repository.findById(sessionId);
|
||||
|
||||
assertThat(session).isNull();
|
||||
verify(this.jdbcOperations, times(1)).query(isA(String.class), isA(PreparedStatementSetter.class),
|
||||
@@ -538,7 +514,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
given(this.jdbcOperations.query(isA(String.class), isA(PreparedStatementSetter.class),
|
||||
isA(ResultSetExtractor.class))).willReturn(Collections.singletonList(expired));
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.findById(expired.getId());
|
||||
JdbcSession session = this.repository.findById(expired.getId());
|
||||
|
||||
assertThat(session).isNull();
|
||||
verify(this.jdbcOperations, times(1)).query(isA(String.class), isA(PreparedStatementSetter.class),
|
||||
@@ -554,7 +530,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
given(this.jdbcOperations.query(isA(String.class), isA(PreparedStatementSetter.class),
|
||||
isA(ResultSetExtractor.class))).willReturn(Collections.singletonList(saved));
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.findById(saved.getId());
|
||||
JdbcSession session = this.repository.findById(saved.getId());
|
||||
|
||||
assertThat(session.getId()).isEqualTo(saved.getId());
|
||||
assertThat(session.isNew()).isFalse();
|
||||
@@ -576,8 +552,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
void findByIndexNameAndIndexValueUnknownIndexName() {
|
||||
String indexValue = "testIndexValue";
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> sessions = this.repository
|
||||
.findByIndexNameAndIndexValue("testIndexName", indexValue);
|
||||
Map<String, JdbcSession> sessions = this.repository.findByIndexNameAndIndexValue("testIndexName", indexValue);
|
||||
|
||||
assertThat(sessions).isEmpty();
|
||||
verifyNoMoreInteractions(this.jdbcOperations);
|
||||
@@ -590,7 +565,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
given(this.jdbcOperations.query(isA(String.class), isA(PreparedStatementSetter.class),
|
||||
isA(ResultSetExtractor.class))).willReturn(Collections.emptyList());
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> sessions = this.repository
|
||||
Map<String, JdbcSession> sessions = this.repository
|
||||
.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principal);
|
||||
|
||||
assertThat(sessions).isEmpty();
|
||||
@@ -614,7 +589,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
given(this.jdbcOperations.query(isA(String.class), isA(PreparedStatementSetter.class),
|
||||
isA(ResultSetExtractor.class))).willReturn(saved);
|
||||
|
||||
Map<String, JdbcOperationsSessionRepository.JdbcSession> sessions = this.repository
|
||||
Map<String, JdbcSession> sessions = this.repository
|
||||
.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principal);
|
||||
|
||||
assertThat(sessions).hasSize(2);
|
||||
@@ -631,7 +606,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
@Test // gh-1120
|
||||
void getAttributeNamesAndRemove() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
JdbcSession session = this.repository.createSession();
|
||||
session.setAttribute("attribute1", "value1");
|
||||
session.setAttribute("attribute2", "value2");
|
||||
|
||||
@@ -649,8 +624,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
delegate.setAttribute("attribute1", (Supplier<String>) () -> "value1");
|
||||
delegate.setAttribute("attribute2", (Supplier<String>) () -> "value2");
|
||||
delegate.setAttribute("attribute3", (Supplier<String>) () -> "value3");
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(delegate,
|
||||
UUID.randomUUID().toString(), false);
|
||||
JdbcSession session = this.repository.new JdbcSession(delegate, UUID.randomUUID().toString(), false);
|
||||
session.getAttribute("attribute2");
|
||||
session.setAttribute("attribute3", "value4");
|
||||
this.repository.save(session);
|
||||
@@ -666,8 +640,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
delegate.setAttribute("attribute1", (Supplier<String>) () -> "value1");
|
||||
delegate.setAttribute("attribute2", (Supplier<String>) () -> "value2");
|
||||
delegate.setAttribute("attribute3", (Supplier<String>) () -> "value3");
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(delegate,
|
||||
UUID.randomUUID().toString(), false);
|
||||
JdbcSession session = this.repository.new JdbcSession(delegate, UUID.randomUUID().toString(), false);
|
||||
session.getAttribute("attribute2");
|
||||
session.setAttribute("attribute3", "value4");
|
||||
this.repository.save(session);
|
||||
@@ -685,8 +658,7 @@ class JdbcOperationsSessionRepositoryTests {
|
||||
delegate.setAttribute("attribute1", (Supplier<String>) () -> "value1");
|
||||
delegate.setAttribute("attribute2", (Supplier<String>) () -> "value2");
|
||||
delegate.setAttribute("attribute3", (Supplier<String>) () -> "value3");
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(delegate,
|
||||
UUID.randomUUID().toString(), false);
|
||||
JdbcSession session = this.repository.new JdbcSession(delegate, UUID.randomUUID().toString(), false);
|
||||
session.getAttribute("attribute2");
|
||||
session.setAttribute("attribute3", "value4");
|
||||
this.repository.save(session);
|
||||
@@ -35,7 +35,7 @@ import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.session.FlushMode;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.config.SessionRepositoryCustomizer;
|
||||
import org.springframework.session.jdbc.JdbcOperationsSessionRepository;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
|
||||
import org.springframework.session.jdbc.config.annotation.SpringSessionDataSource;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
@@ -51,7 +51,6 @@ import static org.mockito.Mockito.mock;
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @author Eddú Meléndez
|
||||
* @since 1.2.0
|
||||
*/
|
||||
class JdbcHttpSessionConfigurationTests {
|
||||
|
||||
@@ -81,7 +80,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
void defaultConfiguration() {
|
||||
registerAndRefresh(DataSourceConfiguration.class, DefaultConfiguration.class);
|
||||
|
||||
JdbcOperationsSessionRepository sessionRepository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository sessionRepository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
assertThat(sessionRepository).isNotNull();
|
||||
assertThat(sessionRepository).extracting("transactionOperations")
|
||||
.hasFieldOrPropertyWithValue("propagationBehavior", TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
@@ -91,7 +90,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
void customTableNameAnnotation() {
|
||||
registerAndRefresh(DataSourceConfiguration.class, CustomTableNameAnnotationConfiguration.class);
|
||||
|
||||
JdbcOperationsSessionRepository repository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
assertThat(repository).isNotNull();
|
||||
assertThat(ReflectionTestUtils.getField(repository, "tableName")).isEqualTo(TABLE_NAME);
|
||||
}
|
||||
@@ -100,7 +99,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
void customTableNameSetter() {
|
||||
registerAndRefresh(DataSourceConfiguration.class, CustomTableNameSetterConfiguration.class);
|
||||
|
||||
JdbcOperationsSessionRepository repository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
assertThat(repository).isNotNull();
|
||||
assertThat(ReflectionTestUtils.getField(repository, "tableName")).isEqualTo(TABLE_NAME);
|
||||
}
|
||||
@@ -110,7 +109,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
registerAndRefresh(DataSourceConfiguration.class,
|
||||
CustomMaxInactiveIntervalInSecondsAnnotationConfiguration.class);
|
||||
|
||||
JdbcOperationsSessionRepository repository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
assertThat(repository).isNotNull();
|
||||
assertThat(ReflectionTestUtils.getField(repository, "defaultMaxInactiveInterval"))
|
||||
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
@@ -120,7 +119,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
void customMaxInactiveIntervalInSecondsSetter() {
|
||||
registerAndRefresh(DataSourceConfiguration.class, CustomMaxInactiveIntervalInSecondsSetterConfiguration.class);
|
||||
|
||||
JdbcOperationsSessionRepository repository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
assertThat(repository).isNotNull();
|
||||
assertThat(ReflectionTestUtils.getField(repository, "defaultMaxInactiveInterval"))
|
||||
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
@@ -176,7 +175,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
void qualifiedDataSourceConfiguration() {
|
||||
registerAndRefresh(DataSourceConfiguration.class, QualifiedDataSourceConfiguration.class);
|
||||
|
||||
JdbcOperationsSessionRepository repository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
DataSource dataSource = this.context.getBean("qualifiedDataSource", DataSource.class);
|
||||
assertThat(repository).isNotNull();
|
||||
assertThat(dataSource).isNotNull();
|
||||
@@ -189,7 +188,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
void primaryDataSourceConfiguration() {
|
||||
registerAndRefresh(DataSourceConfiguration.class, PrimaryDataSourceConfiguration.class);
|
||||
|
||||
JdbcOperationsSessionRepository repository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
DataSource dataSource = this.context.getBean("primaryDataSource", DataSource.class);
|
||||
assertThat(repository).isNotNull();
|
||||
assertThat(dataSource).isNotNull();
|
||||
@@ -202,7 +201,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
void qualifiedAndPrimaryDataSourceConfiguration() {
|
||||
registerAndRefresh(DataSourceConfiguration.class, QualifiedAndPrimaryDataSourceConfiguration.class);
|
||||
|
||||
JdbcOperationsSessionRepository repository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
DataSource dataSource = this.context.getBean("qualifiedDataSource", DataSource.class);
|
||||
assertThat(repository).isNotNull();
|
||||
assertThat(dataSource).isNotNull();
|
||||
@@ -215,7 +214,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
void namedDataSourceConfiguration() {
|
||||
registerAndRefresh(DataSourceConfiguration.class, NamedDataSourceConfiguration.class);
|
||||
|
||||
JdbcOperationsSessionRepository repository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
DataSource dataSource = this.context.getBean("dataSource", DataSource.class);
|
||||
assertThat(repository).isNotNull();
|
||||
assertThat(dataSource).isNotNull();
|
||||
@@ -236,7 +235,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
void customTransactionOperationsConfiguration() {
|
||||
registerAndRefresh(DataSourceConfiguration.class, CustomTransactionOperationsConfiguration.class);
|
||||
|
||||
JdbcOperationsSessionRepository repository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
TransactionOperations transactionOperations = this.context.getBean(TransactionOperations.class);
|
||||
assertThat(repository).isNotNull();
|
||||
assertThat(transactionOperations).isNotNull();
|
||||
@@ -247,7 +246,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
void customLobHandlerConfiguration() {
|
||||
registerAndRefresh(DataSourceConfiguration.class, CustomLobHandlerConfiguration.class);
|
||||
|
||||
JdbcOperationsSessionRepository repository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
LobHandler lobHandler = this.context.getBean(LobHandler.class);
|
||||
assertThat(repository).isNotNull();
|
||||
assertThat(lobHandler).isNotNull();
|
||||
@@ -258,7 +257,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
void customConversionServiceConfiguration() {
|
||||
registerAndRefresh(DataSourceConfiguration.class, CustomConversionServiceConfiguration.class);
|
||||
|
||||
JdbcOperationsSessionRepository repository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
ConversionService conversionService = this.context.getBean("springSessionConversionService",
|
||||
ConversionService.class);
|
||||
assertThat(repository).isNotNull();
|
||||
@@ -279,7 +278,7 @@ class JdbcHttpSessionConfigurationTests {
|
||||
@Test
|
||||
void sessionRepositoryCustomizer() {
|
||||
registerAndRefresh(DataSourceConfiguration.class, SessionRepositoryCustomizerConfiguration.class);
|
||||
JdbcOperationsSessionRepository sessionRepository = this.context.getBean(JdbcOperationsSessionRepository.class);
|
||||
JdbcIndexedSessionRepository sessionRepository = this.context.getBean(JdbcIndexedSessionRepository.class);
|
||||
assertThat(sessionRepository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
|
||||
MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
}
|
||||
@@ -488,13 +487,13 @@ class JdbcHttpSessionConfigurationTests {
|
||||
|
||||
@Bean
|
||||
@Order(0)
|
||||
public SessionRepositoryCustomizer<JdbcOperationsSessionRepository> sessionRepositoryCustomizerOne() {
|
||||
public SessionRepositoryCustomizer<JdbcIndexedSessionRepository> sessionRepositoryCustomizerOne() {
|
||||
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(1)
|
||||
public SessionRepositoryCustomizer<JdbcOperationsSessionRepository> sessionRepositoryCustomizerTwo() {
|
||||
public SessionRepositoryCustomizer<JdbcIndexedSessionRepository> sessionRepositoryCustomizerTwo() {
|
||||
return (sessionRepository) -> sessionRepository
|
||||
.setDefaultMaxInactiveInterval(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user