Introduce Spring Session MongoDB

* Migrate the module's code back into this project.
* Fold the documentation in.
* Update to current Gradle conventions.
* Reformat to match styling.
This commit is contained in:
Greg L. Turnquist
2021-08-13 13:40:28 -05:00
committed by Eleftheria Stein
parent d10c18eb88
commit bf139dbbb3
63 changed files with 5773 additions and 17 deletions

View File

@@ -0,0 +1,141 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.data.mongo;
import java.time.Duration;
import com.mongodb.DBObject;
import org.bson.Document;
import org.junit.jupiter.api.Test;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.session.FindByIndexNameSessionRepository;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Greg Turnquist
*/
public abstract class AbstractMongoSessionConverterTest {
abstract AbstractMongoSessionConverter getMongoSessionConverter();
@Test
void verifyRoundTripSerialization() throws Exception {
// given
MongoSession toSerialize = new MongoSession();
toSerialize.setAttribute("username", "john_the_springer");
// when
DBObject dbObject = convertToDBObject(toSerialize);
MongoSession deserialized = convertToSession(dbObject);
// then
assertThat(deserialized).isEqualToComparingFieldByField(toSerialize);
}
@Test
void verifyRoundTripSecuritySerialization() {
// given
MongoSession toSerialize = new MongoSession();
String principalName = "john_the_springer";
SecurityContextImpl context = new SecurityContextImpl();
context.setAuthentication(new UsernamePasswordAuthenticationToken(principalName, null));
toSerialize.setAttribute("SPRING_SECURITY_CONTEXT", context);
// when
DBObject serialized = convertToDBObject(toSerialize);
MongoSession deserialized = convertToSession(serialized);
// then
assertThat(deserialized).isEqualToComparingOnlyGivenFields(toSerialize, "id", "createdMillis", "accessedMillis",
"intervalSeconds", "expireAt");
SecurityContextImpl springSecurityContextBefore = toSerialize.getAttribute("SPRING_SECURITY_CONTEXT");
SecurityContextImpl springSecurityContextAfter = deserialized.getAttribute("SPRING_SECURITY_CONTEXT");
assertThat(springSecurityContextBefore).isEqualToComparingOnlyGivenFields(springSecurityContextAfter,
"authentication.principal", "authentication.authorities", "authentication.authenticated");
assertThat(springSecurityContextAfter.getAuthentication().getPrincipal()).isEqualTo("john_the_springer");
assertThat(springSecurityContextAfter.getAuthentication().getCredentials()).isNull();
}
@Test
void shouldExtractPrincipalNameFromAttributes() throws Exception {
// given
MongoSession toSerialize = new MongoSession();
String principalName = "john_the_springer";
toSerialize.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
// when
DBObject dbObject = convertToDBObject(toSerialize);
// then
assertThat(dbObject.get("principal")).isEqualTo(principalName);
}
@Test
void shouldExtractPrincipalNameFromAuthentication() throws Exception {
// given
MongoSession toSerialize = new MongoSession();
String principalName = "john_the_springer";
SecurityContextImpl context = new SecurityContextImpl();
context.setAuthentication(new UsernamePasswordAuthenticationToken(principalName, null));
toSerialize.setAttribute("SPRING_SECURITY_CONTEXT", context);
// when
DBObject dbObject = convertToDBObject(toSerialize);
// then
assertThat(dbObject.get("principal")).isEqualTo(principalName);
}
@Test
void sessionWrapperWithNoMaxIntervalShouldFallbackToDefaultValues() {
// given
MongoSession toSerialize = new MongoSession();
DBObject dbObject = convertToDBObject(toSerialize);
Document document = new Document(dbObject.toMap());
document.remove("interval");
// when
MongoSession convertedSession = getMongoSessionConverter().convert(document);
// then
assertThat(convertedSession.getMaxInactiveInterval()).isEqualTo(Duration.ofMinutes(30));
}
@Nullable
MongoSession convertToSession(DBObject session) {
return (MongoSession) getMongoSessionConverter().convert(session, TypeDescriptor.valueOf(DBObject.class),
TypeDescriptor.valueOf(MongoSession.class));
}
@Nullable
DBObject convertToDBObject(MongoSession session) {
return (DBObject) getMongoSessionConverter().convert(session, TypeDescriptor.valueOf(MongoSession.class),
TypeDescriptor.valueOf(DBObject.class));
}
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.data.mongo;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.DBObject;
import org.assertj.core.api.Assertions;
import org.assertj.core.api.AssertionsForClassTypes;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.junit.jupiter.api.Test;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.ReflectionUtils;
/**
* @author Jakub Kubrynski
* @author Greg Turnquist
*/
public class JacksonMongoSessionConverterTest extends AbstractMongoSessionConverterTest {
JacksonMongoSessionConverter mongoSessionConverter = new JacksonMongoSessionConverter();
@Override
AbstractMongoSessionConverter getMongoSessionConverter() {
return this.mongoSessionConverter;
}
@Test
void shouldSaveIdField() {
// given
MongoSession session = new MongoSession();
// when
DBObject convert = this.mongoSessionConverter.convert(session);
// then
AssertionsForClassTypes.assertThat(convert.get("_id")).isEqualTo(session.getId());
AssertionsForClassTypes.assertThat(convert.get("id")).isNull();
}
@Test
void shouldQueryAgainstAttribute() throws Exception {
// when
Query cart = this.mongoSessionConverter.getQueryForIndex("cart", "my-cart");
// then
AssertionsForClassTypes.assertThat(cart.getQueryObject().get("attrs.cart")).isEqualTo("my-cart");
}
@Test
void shouldAllowCustomObjectMapper() {
// given
ObjectMapper myMapper = new ObjectMapper();
// when
JacksonMongoSessionConverter converter = new JacksonMongoSessionConverter(myMapper);
// then
Field objectMapperField = ReflectionUtils.findField(JacksonMongoSessionConverter.class, "objectMapper");
ReflectionUtils.makeAccessible(objectMapperField);
ObjectMapper converterMapper = (ObjectMapper) ReflectionUtils.getField(objectMapperField, converter);
AssertionsForClassTypes.assertThat(converterMapper).isEqualTo(myMapper);
}
@Test
void shouldNotAllowNullObjectMapperToBeInjected() {
Assertions.assertThatIllegalArgumentException()
.isThrownBy(() -> new JacksonMongoSessionConverter((ObjectMapper) null));
}
@Test
void shouldSaveExpireAtAsDate() {
// given
MongoSession session = new MongoSession();
// when
DBObject convert = this.mongoSessionConverter.convert(session);
// then
AssertionsForClassTypes.assertThat(convert.get("expireAt")).isInstanceOf(Date.class);
AssertionsForClassTypes.assertThat(convert.get("expireAt")).isEqualTo(session.getExpireAt());
}
@Test
void shouldLoadExpireAtFromDocument() {
// given
Date now = new Date();
HashMap<String, Object> data = new HashMap<>();
data.put("expireAt", now);
data.put("@class", MongoSession.class.getName());
data.put("_id", new ObjectId().toString());
Document document = new Document(data);
// when
MongoSession convertedSession = this.mongoSessionConverter.convert(document);
// then
AssertionsForClassTypes.assertThat(convertedSession).isNotNull();
AssertionsForClassTypes.assertThat(convertedSession.getExpireAt()).isEqualTo(now);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.data.mongo;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* @author Jakub Kubrynski
* @author Rob Winch
* @author Greg Turnquist
*/
public class JdkMongoSessionConverterTest extends AbstractMongoSessionConverterTest {
Duration inactiveInterval = Duration.ofMinutes(30);
JdkMongoSessionConverter mongoSessionConverter = new JdkMongoSessionConverter(this.inactiveInterval);
@Override
AbstractMongoSessionConverter getMongoSessionConverter() {
return this.mongoSessionConverter;
}
@Test
void constructorNullSerializer() {
assertThatIllegalArgumentException().isThrownBy(
() -> new JdkMongoSessionConverter(null, new DeserializingConverter(), this.inactiveInterval));
}
@Test
void constructorNullDeserializer() {
assertThatIllegalArgumentException().isThrownBy(
() -> new JdkMongoSessionConverter(new SerializingConverter(), null, this.inactiveInterval));
}
}

View File

@@ -0,0 +1,225 @@
/*
* Copyright 2014-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.data.mongo;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.bson.Document;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.session.FindByIndexNameSessionRepository;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.mock;
import static org.mockito.BDDMockito.verify;
/**
* Tests for {@link MongoIndexedSessionRepository}.
*
* @author Jakub Kubrynski
* @author Vedran Pavic
* @author Greg Turnquist
*/
@ExtendWith(MockitoExtension.class)
public class MongoIndexedSessionRepositoryTest {
@Mock
private AbstractMongoSessionConverter converter;
@Mock
private MongoOperations mongoOperations;
private MongoIndexedSessionRepository repository;
@BeforeEach
void setUp() {
this.repository = new MongoIndexedSessionRepository(this.mongoOperations);
this.repository.setMongoSessionConverter(this.converter);
}
@Test
void shouldCreateSession() {
// when
MongoSession session = this.repository.createSession();
// then
assertThat(session.getId()).isNotEmpty();
assertThat(session.getMaxInactiveInterval().getSeconds())
.isEqualTo(MongoIndexedSessionRepository.DEFAULT_INACTIVE_INTERVAL);
}
@Test
void shouldCreateSessionWhenMaxInactiveIntervalNotDefined() {
// when
this.repository.setMaxInactiveIntervalInSeconds(null);
MongoSession session = this.repository.createSession();
// then
assertThat(session.getId()).isNotEmpty();
assertThat(session.getMaxInactiveInterval().getSeconds())
.isEqualTo(MongoIndexedSessionRepository.DEFAULT_INACTIVE_INTERVAL);
}
@Test
void shouldSaveSession() {
// given
MongoSession session = new MongoSession();
BasicDBObject dbSession = new BasicDBObject();
given(this.converter.convert(session, TypeDescriptor.valueOf(MongoSession.class),
TypeDescriptor.valueOf(DBObject.class))).willReturn(dbSession);
// when
this.repository.save(session);
// then
verify(this.mongoOperations).save(dbSession, MongoIndexedSessionRepository.DEFAULT_COLLECTION_NAME);
}
@Test
void shouldGetSession() {
// given
String sessionId = UUID.randomUUID().toString();
Document sessionDocument = new Document();
given(this.mongoOperations.findById(sessionId, Document.class,
MongoIndexedSessionRepository.DEFAULT_COLLECTION_NAME)).willReturn(sessionDocument);
MongoSession session = new MongoSession();
given(this.converter.convert(sessionDocument, TypeDescriptor.valueOf(Document.class),
TypeDescriptor.valueOf(MongoSession.class))).willReturn(session);
// when
MongoSession retrievedSession = this.repository.findById(sessionId);
// then
assertThat(retrievedSession).isEqualTo(session);
}
@Test
void shouldHandleExpiredSession() {
// given
String sessionId = UUID.randomUUID().toString();
Document sessionDocument = new Document();
given(this.mongoOperations.findById(sessionId, Document.class,
MongoIndexedSessionRepository.DEFAULT_COLLECTION_NAME)).willReturn(sessionDocument);
MongoSession session = mock(MongoSession.class);
given(session.isExpired()).willReturn(true);
given(this.converter.convert(sessionDocument, TypeDescriptor.valueOf(Document.class),
TypeDescriptor.valueOf(MongoSession.class))).willReturn(session);
given(session.getId()).willReturn("sessionId");
// when
this.repository.findById(sessionId);
// then
verify(this.mongoOperations).remove(any(Document.class),
eq(MongoIndexedSessionRepository.DEFAULT_COLLECTION_NAME));
}
@Test
void shouldDeleteSession() {
// given
String sessionId = UUID.randomUUID().toString();
Document sessionDocument = new Document();
sessionDocument.put("id", sessionId);
MongoSession mongoSession = new MongoSession(sessionId,
MongoIndexedSessionRepository.DEFAULT_INACTIVE_INTERVAL);
given(this.converter.convert(sessionDocument, TypeDescriptor.valueOf(Document.class),
TypeDescriptor.valueOf(MongoSession.class))).willReturn(mongoSession);
given(this.mongoOperations.findById(eq(sessionId), eq(Document.class),
eq(MongoIndexedSessionRepository.DEFAULT_COLLECTION_NAME))).willReturn(sessionDocument);
// when
this.repository.deleteById(sessionId);
// then
verify(this.mongoOperations).remove(any(Document.class),
eq(MongoIndexedSessionRepository.DEFAULT_COLLECTION_NAME));
}
@Test
void shouldGetSessionsMapByPrincipal() {
// given
String principalNameIndexName = FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME;
Document document = new Document();
given(this.converter.getQueryForIndex(anyString(), any(Object.class))).willReturn(mock(Query.class));
given(this.mongoOperations.find(any(Query.class), eq(Document.class),
eq(MongoIndexedSessionRepository.DEFAULT_COLLECTION_NAME)))
.willReturn(Collections.singletonList(document));
String sessionId = UUID.randomUUID().toString();
MongoSession session = new MongoSession(sessionId, 1800);
given(this.converter.convert(document, TypeDescriptor.valueOf(Document.class),
TypeDescriptor.valueOf(MongoSession.class))).willReturn(session);
// when
Map<String, MongoSession> sessionsMap = this.repository.findByIndexNameAndIndexValue(principalNameIndexName,
"john");
// then
assertThat(sessionsMap).containsOnlyKeys(sessionId);
assertThat(sessionsMap).containsValues(session);
}
@Test
void shouldReturnEmptyMapForNotSupportedIndex() {
// given
String index = "some_not_supported_index_name";
// when
Map<String, MongoSession> sessionsMap = this.repository.findByIndexNameAndIndexValue(index, "some_value");
// then
assertThat(sessionsMap).isEmpty();
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.data.mongo;
import java.time.Duration;
import java.time.Instant;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Rob Winch
* @author Greg Turnquist
*/
public class MongoSessionTest {
@Test
void isExpiredWhenIntervalNegativeThenFalse() {
MongoSession session = new MongoSession();
session.setMaxInactiveInterval(Duration.ofSeconds(-1));
session.setLastAccessedTime(Instant.ofEpochMilli(0L));
assertThat(session.isExpired()).isFalse();
}
}

View File

@@ -0,0 +1,229 @@
/*
* Copyright 2014-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.data.mongo;
import java.util.UUID;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.client.result.DeleteResult;
import org.bson.Document;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.session.events.SessionDeletedEvent;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.any;
import static org.mockito.BDDMockito.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.mock;
import static org.mockito.BDDMockito.times;
import static org.mockito.BDDMockito.verify;
/**
* Tests for {@link ReactiveMongoSessionRepository}.
*
* @author Jakub Kubrynski
* @author Vedran Pavic
* @author Greg Turnquist
*/
@ExtendWith(MockitoExtension.class)
public class ReactiveMongoSessionRepositoryTest {
@Mock
private AbstractMongoSessionConverter converter;
@Mock
private ReactiveMongoOperations mongoOperations;
@Mock
private MongoOperations blockingMongoOperations;
@Mock
private ApplicationEventPublisher eventPublisher;
private ReactiveMongoSessionRepository repository;
@BeforeEach
void setUp() {
this.repository = new ReactiveMongoSessionRepository(this.mongoOperations);
this.repository.setMongoSessionConverter(this.converter);
this.repository.setApplicationEventPublisher(this.eventPublisher);
}
@Test
void shouldCreateSession() {
this.repository.createSession() //
.as(StepVerifier::create) //
.expectNextMatches((mongoSession) -> {
assertThat(mongoSession.getId()).isNotEmpty();
assertThat(mongoSession.getMaxInactiveInterval().getSeconds())
.isEqualTo(ReactiveMongoSessionRepository.DEFAULT_INACTIVE_INTERVAL);
return true;
}) //
.verifyComplete();
}
@Test
void shouldCreateSessionWhenMaxInactiveIntervalNotDefined() {
// when
this.repository.setMaxInactiveIntervalInSeconds(null);
// then
this.repository.createSession() //
.as(StepVerifier::create) //
.expectNextMatches((mongoSession) -> {
assertThat(mongoSession.getId()).isNotEmpty();
assertThat(mongoSession.getMaxInactiveInterval().getSeconds())
.isEqualTo(ReactiveMongoSessionRepository.DEFAULT_INACTIVE_INTERVAL);
return true;
}) //
.verifyComplete();
}
@Test
void shouldSaveSession() {
// given
MongoSession session = new MongoSession();
BasicDBObject dbSession = new BasicDBObject();
given(this.converter.convert(session, TypeDescriptor.valueOf(MongoSession.class),
TypeDescriptor.valueOf(DBObject.class))).willReturn(dbSession);
given(this.mongoOperations.save(dbSession, "sessions")).willReturn(Mono.just(dbSession));
// when
this.repository.save(session) //
.as(StepVerifier::create) //
.verifyComplete();
verify(this.mongoOperations).save(dbSession, ReactiveMongoSessionRepository.DEFAULT_COLLECTION_NAME);
}
@Test
void shouldGetSession() {
// given
String sessionId = UUID.randomUUID().toString();
Document sessionDocument = new Document();
given(this.mongoOperations.findById(sessionId, Document.class,
ReactiveMongoSessionRepository.DEFAULT_COLLECTION_NAME)).willReturn(Mono.just(sessionDocument));
MongoSession session = new MongoSession();
given(this.converter.convert(sessionDocument, TypeDescriptor.valueOf(Document.class),
TypeDescriptor.valueOf(MongoSession.class))).willReturn(session);
// when
this.repository.findById(sessionId) //
.as(StepVerifier::create) //
.expectNext(session) //
.verifyComplete();
}
@Test
void shouldHandleExpiredSession() {
// given
String sessionId = UUID.randomUUID().toString();
Document sessionDocument = new Document();
given(this.mongoOperations.findById(sessionId, Document.class,
ReactiveMongoSessionRepository.DEFAULT_COLLECTION_NAME)).willReturn(Mono.just(sessionDocument));
given(this.mongoOperations.remove(sessionDocument, ReactiveMongoSessionRepository.DEFAULT_COLLECTION_NAME))
.willReturn(Mono.just(DeleteResult.acknowledged(1)));
MongoSession session = mock(MongoSession.class);
given(session.isExpired()).willReturn(true);
given(this.converter.convert(sessionDocument, TypeDescriptor.valueOf(Document.class),
TypeDescriptor.valueOf(MongoSession.class))).willReturn(session);
// when
this.repository.findById(sessionId) //
.as(StepVerifier::create) //
.verifyComplete();
// then
verify(this.mongoOperations).remove(any(Document.class),
eq(ReactiveMongoSessionRepository.DEFAULT_COLLECTION_NAME));
}
@Test
void shouldDeleteSession() {
// given
String sessionId = UUID.randomUUID().toString();
Document sessionDocument = new Document();
given(this.mongoOperations.findById(sessionId, Document.class,
ReactiveMongoSessionRepository.DEFAULT_COLLECTION_NAME)).willReturn(Mono.just(sessionDocument));
given(this.mongoOperations.remove(sessionDocument, "sessions"))
.willReturn(Mono.just(DeleteResult.acknowledged(1)));
MongoSession session = mock(MongoSession.class);
given(this.converter.convert(sessionDocument, TypeDescriptor.valueOf(Document.class),
TypeDescriptor.valueOf(MongoSession.class))).willReturn(session);
// when
this.repository.deleteById(sessionId) //
.as(StepVerifier::create) //
.verifyComplete();
verify(this.mongoOperations).remove(any(Document.class),
eq(ReactiveMongoSessionRepository.DEFAULT_COLLECTION_NAME));
verify(this.eventPublisher).publishEvent(any(SessionDeletedEvent.class));
}
@Test
void shouldInvokeMethodToCreateIndexesImperatively() {
// given
IndexOperations indexOperations = mock(IndexOperations.class);
given(this.blockingMongoOperations.indexOps((String) any())).willReturn(indexOperations);
this.repository.setBlockingMongoOperations(this.blockingMongoOperations);
// when
this.repository.afterPropertiesSet();
// then
verify(this.blockingMongoOperations, times(1)).indexOps((String) any());
verify(this.converter, times(1)).ensureIndexes(indexOperations);
}
}

View File

@@ -0,0 +1,334 @@
/*
* Copyright 2014-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.data.mongo.config.annotation.web.http;
import java.net.UnknownHostException;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.UnsatisfiedDependencyException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.session.IndexResolver;
import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
import org.springframework.session.data.mongo.JacksonMongoSessionConverter;
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
import org.springframework.session.data.mongo.MongoSession;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.mock;
/**
* Tests for {@link MongoHttpSessionConfiguration}.
*
* @author Eddú Meléndez
* @author Vedran Pavic
*/
public class MongoHttpSessionConfigurationTest {
private static final String COLLECTION_NAME = "testSessions";
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600;
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@AfterEach
void after() {
if (this.context != null) {
this.context.close();
}
}
@Test
void noMongoOperationsConfiguration() {
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
.isThrownBy(() -> registerAndRefresh(EmptyConfiguration.class))
.withMessageContaining("mongoSessionRepository");
}
@Test
void defaultConfiguration() {
registerAndRefresh(DefaultConfiguration.class);
assertThat(this.context.getBean(MongoIndexedSessionRepository.class)).isNotNull();
}
@Test
void customCollectionName() {
registerAndRefresh(CustomCollectionNameConfiguration.class);
MongoIndexedSessionRepository repository = this.context.getBean(MongoIndexedSessionRepository.class);
assertThat(repository).isNotNull();
assertThat(ReflectionTestUtils.getField(repository, "collectionName")).isEqualTo(COLLECTION_NAME);
}
@Test
void setCustomCollectionName() {
registerAndRefresh(CustomCollectionNameSetConfiguration.class);
MongoHttpSessionConfiguration session = this.context.getBean(MongoHttpSessionConfiguration.class);
assertThat(session).isNotNull();
assertThat(ReflectionTestUtils.getField(session, "collectionName")).isEqualTo(COLLECTION_NAME);
}
@Test
void customMaxInactiveIntervalInSeconds() {
registerAndRefresh(CustomMaxInactiveIntervalInSecondsConfiguration.class);
MongoIndexedSessionRepository repository = this.context.getBean(MongoIndexedSessionRepository.class);
assertThat(repository).isNotNull();
assertThat(ReflectionTestUtils.getField(repository, "maxInactiveIntervalInSeconds"))
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
}
@Test
void setCustomMaxInactiveIntervalInSeconds() {
registerAndRefresh(CustomMaxInactiveIntervalInSecondsSetConfiguration.class);
MongoIndexedSessionRepository repository = this.context.getBean(MongoIndexedSessionRepository.class);
assertThat(repository).isNotNull();
assertThat(ReflectionTestUtils.getField(repository, "maxInactiveIntervalInSeconds"))
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
}
@Test
void setCustomSessionConverterConfiguration() {
registerAndRefresh(CustomSessionConverterConfiguration.class);
MongoIndexedSessionRepository repository = this.context.getBean(MongoIndexedSessionRepository.class);
AbstractMongoSessionConverter mongoSessionConverter = this.context.getBean(AbstractMongoSessionConverter.class);
assertThat(repository).isNotNull();
assertThat(mongoSessionConverter).isNotNull();
assertThat(ReflectionTestUtils.getField(repository, "mongoSessionConverter")).isEqualTo(mongoSessionConverter);
}
@Test
void resolveCollectionNameByPropertyPlaceholder() {
this.context
.setEnvironment(new MockEnvironment().withProperty("session.mongo.collectionName", COLLECTION_NAME));
registerAndRefresh(CustomMongoJdbcSessionConfiguration.class);
MongoHttpSessionConfiguration configuration = this.context.getBean(MongoHttpSessionConfiguration.class);
assertThat(ReflectionTestUtils.getField(configuration, "collectionName")).isEqualTo(COLLECTION_NAME);
}
@Test
void sessionRepositoryCustomizer() {
registerAndRefresh(MongoConfiguration.class, SessionRepositoryCustomizerConfiguration.class);
MongoIndexedSessionRepository sessionRepository = this.context.getBean(MongoIndexedSessionRepository.class);
assertThat(sessionRepository).hasFieldOrPropertyWithValue("maxInactiveIntervalInSeconds", 10000);
}
@Test
void customIndexResolverConfigurationWithDefaultMongoSessionConverter() {
registerAndRefresh(MongoConfiguration.class,
CustomIndexResolverConfigurationWithDefaultMongoSessionConverter.class);
MongoIndexedSessionRepository repository = this.context.getBean(MongoIndexedSessionRepository.class);
IndexResolver<MongoSession> indexResolver = this.context.getBean(IndexResolver.class);
assertThat(repository).isNotNull();
assertThat(indexResolver).isNotNull();
assertThat(repository).extracting("mongoSessionConverter").hasFieldOrPropertyWithValue("indexResolver",
indexResolver);
}
@Test
void customIndexResolverConfigurationWithProvidedMongoSessionConverter() {
registerAndRefresh(MongoConfiguration.class,
CustomIndexResolverConfigurationWithProvidedMongoSessionConverter.class);
MongoIndexedSessionRepository repository = this.context.getBean(MongoIndexedSessionRepository.class);
IndexResolver<MongoSession> indexResolver = this.context.getBean(IndexResolver.class);
assertThat(repository).isNotNull();
assertThat(indexResolver).isNotNull();
assertThat(repository).extracting("mongoSessionConverter").hasFieldOrPropertyWithValue("indexResolver",
indexResolver);
}
private void registerAndRefresh(Class<?>... annotatedClasses) {
this.context.register(annotatedClasses);
this.context.refresh();
}
@Configuration
@EnableMongoHttpSession
static class EmptyConfiguration {
}
static class BaseConfiguration {
@Bean
MongoOperations mongoOperations() throws UnknownHostException {
MongoOperations mongoOperations = mock(MongoOperations.class);
IndexOperations indexOperations = mock(IndexOperations.class);
given(mongoOperations.indexOps(anyString())).willReturn(indexOperations);
return mongoOperations;
}
}
@Configuration
@EnableMongoHttpSession
static class DefaultConfiguration extends BaseConfiguration {
}
@Configuration
static class MongoConfiguration extends BaseConfiguration {
}
@Configuration
@EnableMongoHttpSession(collectionName = COLLECTION_NAME)
static class CustomCollectionNameConfiguration extends BaseConfiguration {
}
@Configuration
@Import(MongoConfiguration.class)
static class CustomCollectionNameSetConfiguration extends MongoHttpSessionConfiguration {
CustomCollectionNameSetConfiguration() {
setCollectionName(COLLECTION_NAME);
}
}
@Configuration
@EnableMongoHttpSession(maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
static class CustomMaxInactiveIntervalInSecondsConfiguration extends BaseConfiguration {
}
@Configuration
@Import(MongoConfiguration.class)
static class CustomMaxInactiveIntervalInSecondsSetConfiguration extends MongoHttpSessionConfiguration {
CustomMaxInactiveIntervalInSecondsSetConfiguration() {
setMaxInactiveIntervalInSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS);
}
}
@Configuration
@Import(MongoConfiguration.class)
static class CustomSessionConverterConfiguration extends MongoHttpSessionConfiguration {
@Bean
AbstractMongoSessionConverter mongoSessionConverter() {
return mock(AbstractMongoSessionConverter.class);
}
}
@Configuration
@EnableMongoHttpSession(collectionName = "${session.mongo.collectionName}")
static class CustomMongoJdbcSessionConfiguration extends BaseConfiguration {
@Bean
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
@EnableMongoHttpSession
static class SessionRepositoryCustomizerConfiguration {
@Bean
@Order(0)
SessionRepositoryCustomizer<MongoIndexedSessionRepository> sessionRepositoryCustomizerOne() {
return (sessionRepository) -> sessionRepository.setMaxInactiveIntervalInSeconds(0);
}
@Bean
@Order(1)
SessionRepositoryCustomizer<MongoIndexedSessionRepository> sessionRepositoryCustomizerTwo() {
return (sessionRepository) -> sessionRepository.setMaxInactiveIntervalInSeconds(10000);
}
}
@Configuration
@EnableMongoHttpSession
static class CustomIndexResolverConfigurationWithDefaultMongoSessionConverter {
@Bean
@SuppressWarnings("unchecked")
IndexResolver<MongoSession> indexResolver() {
return mock(IndexResolver.class);
}
}
@Configuration
@EnableMongoHttpSession
static class CustomIndexResolverConfigurationWithProvidedMongoSessionConverter {
@Bean
AbstractMongoSessionConverter mongoSessionConverter() {
return new JacksonMongoSessionConverter();
}
@Bean
@SuppressWarnings("unchecked")
IndexResolver<MongoSession> indexResolver() {
return mock(IndexResolver.class);
}
}
}

View File

@@ -0,0 +1,385 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.data.mongo.config.annotation.web.reactive;
import java.lang.reflect.Field;
import java.util.Collections;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.UnsatisfiedDependencyException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.session.IndexResolver;
import org.springframework.session.ReactiveSessionRepository;
import org.springframework.session.config.ReactiveSessionRepositoryCustomizer;
import org.springframework.session.config.annotation.web.server.EnableSpringWebSession;
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
import org.springframework.session.data.mongo.JacksonMongoSessionConverter;
import org.springframework.session.data.mongo.JdkMongoSessionConverter;
import org.springframework.session.data.mongo.MongoSession;
import org.springframework.session.data.mongo.ReactiveMongoSessionRepository;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
import org.springframework.web.server.session.WebSessionManager;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.BDDMockito.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.mock;
import static org.mockito.BDDMockito.times;
import static org.mockito.BDDMockito.verify;
/**
* Verify various configurations through {@link EnableSpringWebSession}.
*
* @author Greg Turnquist
* @author Vedran Pavić
*/
public class ReactiveMongoWebSessionConfigurationTest {
private AnnotationConfigApplicationContext context;
@AfterEach
void tearDown() {
if (this.context != null) {
this.context.close();
}
}
@Test
void enableSpringWebSessionConfiguresThings() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(GoodConfig.class);
this.context.refresh();
WebSessionManager webSessionManagerFoundByType = this.context.getBean(WebSessionManager.class);
Object webSessionManagerFoundByName = this.context.getBean(WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME);
assertThat(webSessionManagerFoundByType).isNotNull();
assertThat(webSessionManagerFoundByName).isNotNull();
assertThat(webSessionManagerFoundByType).isEqualTo(webSessionManagerFoundByName);
assertThat(this.context.getBean(ReactiveSessionRepository.class)).isNotNull();
}
@Test
void missingReactorSessionRepositoryBreaksAppContext() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(BadConfig.class);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(this.context::refresh)
.withMessageContaining("Error creating bean with name 'reactiveMongoSessionRepository'")
.withMessageContaining(
"No qualifying bean of type '" + ReactiveMongoOperations.class.getCanonicalName());
}
@Test
void defaultSessionConverterShouldBeJdkWhenOnClasspath() throws IllegalAccessException {
this.context = new AnnotationConfigApplicationContext();
this.context.register(GoodConfig.class);
this.context.refresh();
ReactiveMongoSessionRepository repository = this.context.getBean(ReactiveMongoSessionRepository.class);
AbstractMongoSessionConverter converter = findMongoSessionConverter(repository);
assertThat(converter).isOfAnyClassIn(JdkMongoSessionConverter.class);
}
@Test
void overridingMongoSessionConverterWithBeanShouldWork() throws IllegalAccessException {
this.context = new AnnotationConfigApplicationContext();
this.context.register(OverrideSessionConverterConfig.class);
this.context.refresh();
ReactiveMongoSessionRepository repository = this.context.getBean(ReactiveMongoSessionRepository.class);
AbstractMongoSessionConverter converter = findMongoSessionConverter(repository);
assertThat(converter).isOfAnyClassIn(JacksonMongoSessionConverter.class);
}
@Test
void overridingIntervalAndCollectionNameThroughAnnotationShouldWork() throws IllegalAccessException {
this.context = new AnnotationConfigApplicationContext();
this.context.register(OverrideMongoParametersConfig.class);
this.context.refresh();
ReactiveMongoSessionRepository repository = this.context.getBean(ReactiveMongoSessionRepository.class);
Field inactiveField = ReflectionUtils.findField(ReactiveMongoSessionRepository.class,
"maxInactiveIntervalInSeconds");
ReflectionUtils.makeAccessible(inactiveField);
Integer inactiveSeconds = (Integer) inactiveField.get(repository);
Field collectionNameField = ReflectionUtils.findField(ReactiveMongoSessionRepository.class, "collectionName");
ReflectionUtils.makeAccessible(collectionNameField);
String collectionName = (String) collectionNameField.get(repository);
assertThat(inactiveSeconds).isEqualTo(123);
assertThat(collectionName).isEqualTo("test-case");
}
@Test
void reactiveAndBlockingMongoOperationsShouldEnsureIndexing() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(ConfigWithReactiveAndImperativeMongoOperations.class);
this.context.refresh();
MongoOperations operations = this.context.getBean(MongoOperations.class);
IndexOperations indexOperations = this.context.getBean(IndexOperations.class);
verify(operations, times(1)).indexOps((String) any());
verify(indexOperations, times(1)).getIndexInfo();
verify(indexOperations, times(1)).ensureIndex(any());
}
@Test
void overrideCollectionAndInactiveIntervalThroughConfigurationOptions() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(CustomizedReactiveConfiguration.class);
this.context.refresh();
ReactiveMongoSessionRepository repository = this.context.getBean(ReactiveMongoSessionRepository.class);
assertThat(repository.getCollectionName()).isEqualTo("custom-collection");
assertThat(repository.getMaxInactiveIntervalInSeconds()).isEqualTo(123);
}
@Test
void sessionRepositoryCustomizer() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(SessionRepositoryCustomizerConfiguration.class);
this.context.refresh();
ReactiveMongoSessionRepository repository = this.context.getBean(ReactiveMongoSessionRepository.class);
assertThat(repository).hasFieldOrPropertyWithValue("maxInactiveIntervalInSeconds", 10000);
}
@Test
void customIndexResolverConfigurationWithDefaultMongoSessionConverter() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(CustomIndexResolverConfigurationWithDefaultMongoSessionConverter.class);
this.context.refresh();
ReactiveMongoSessionRepository repository = this.context.getBean(ReactiveMongoSessionRepository.class);
IndexResolver<MongoSession> indexResolver = this.context.getBean(IndexResolver.class);
assertThat(repository).isNotNull();
assertThat(indexResolver).isNotNull();
assertThat(repository).extracting("mongoSessionConverter").hasFieldOrPropertyWithValue("indexResolver",
indexResolver);
}
@Test
void customIndexResolverConfigurationWithProvidedMongoSessionConverter() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(CustomIndexResolverConfigurationWithProvidedtMongoSessionConverter.class);
this.context.refresh();
ReactiveMongoSessionRepository repository = this.context.getBean(ReactiveMongoSessionRepository.class);
IndexResolver<MongoSession> indexResolver = this.context.getBean(IndexResolver.class);
assertThat(repository).isNotNull();
assertThat(indexResolver).isNotNull();
assertThat(repository).extracting("mongoSessionConverter").hasFieldOrPropertyWithValue("indexResolver",
indexResolver);
}
/**
* Reflectively extract the {@link AbstractMongoSessionConverter} from the
* {@link ReactiveMongoSessionRepository}. This is to avoid expanding the surface area
* of the API.
*/
private AbstractMongoSessionConverter findMongoSessionConverter(ReactiveMongoSessionRepository repository) {
Field field = ReflectionUtils.findField(ReactiveMongoSessionRepository.class, "mongoSessionConverter");
ReflectionUtils.makeAccessible(field);
try {
return (AbstractMongoSessionConverter) field.get(repository);
}
catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
/**
* A configuration with all the right parts.
*/
@EnableMongoWebSession
static class GoodConfig {
@Bean
ReactiveMongoOperations operations() {
return mock(ReactiveMongoOperations.class);
}
}
/**
* A configuration where no {@link ReactiveMongoOperations} is defined. It's BAD!
*/
@EnableMongoWebSession
static class BadConfig {
}
@EnableMongoWebSession
static class OverrideSessionConverterConfig {
@Bean
ReactiveMongoOperations operations() {
return mock(ReactiveMongoOperations.class);
}
@Bean
AbstractMongoSessionConverter mongoSessionConverter() {
return new JacksonMongoSessionConverter();
}
}
@EnableMongoWebSession(maxInactiveIntervalInSeconds = 123, collectionName = "test-case")
static class OverrideMongoParametersConfig {
@Bean
ReactiveMongoOperations operations() {
return mock(ReactiveMongoOperations.class);
}
}
@EnableMongoWebSession
static class ConfigWithReactiveAndImperativeMongoOperations {
@Bean
ReactiveMongoOperations reactiveMongoOperations() {
return mock(ReactiveMongoOperations.class);
}
@Bean
IndexOperations indexOperations() {
IndexOperations indexOperations = mock(IndexOperations.class);
given(indexOperations.getIndexInfo()).willReturn(Collections.emptyList());
return indexOperations;
}
@Bean
MongoOperations mongoOperations(IndexOperations indexOperations) {
MongoOperations mongoOperations = mock(MongoOperations.class);
given(mongoOperations.indexOps((String) any())).willReturn(indexOperations);
return mongoOperations;
}
}
@EnableSpringWebSession
static class CustomizedReactiveConfiguration extends ReactiveMongoWebSessionConfiguration {
CustomizedReactiveConfiguration() {
this.setCollectionName("custom-collection");
this.setMaxInactiveIntervalInSeconds(123);
}
@Bean
ReactiveMongoOperations reactiveMongoOperations() {
return mock(ReactiveMongoOperations.class);
}
}
@EnableMongoWebSession
static class SessionRepositoryCustomizerConfiguration {
@Bean
ReactiveMongoOperations operations() {
return mock(ReactiveMongoOperations.class);
}
@Bean
@Order(0)
ReactiveSessionRepositoryCustomizer<ReactiveMongoSessionRepository> sessionRepositoryCustomizerOne() {
return (sessionRepository) -> sessionRepository.setMaxInactiveIntervalInSeconds(0);
}
@Bean
@Order(1)
ReactiveSessionRepositoryCustomizer<ReactiveMongoSessionRepository> sessionRepositoryCustomizerTwo() {
return (sessionRepository) -> sessionRepository.setMaxInactiveIntervalInSeconds(10000);
}
}
@EnableMongoWebSession
static class CustomIndexResolverConfigurationWithDefaultMongoSessionConverter {
@Bean
ReactiveMongoOperations operations() {
return mock(ReactiveMongoOperations.class);
}
@Bean
@SuppressWarnings("unchecked")
IndexResolver<MongoSession> indexResolver() {
return mock(IndexResolver.class);
}
}
@EnableMongoWebSession
static class CustomIndexResolverConfigurationWithProvidedtMongoSessionConverter {
@Bean
ReactiveMongoOperations operations() {
return mock(ReactiveMongoOperations.class);
}
@Bean
JacksonMongoSessionConverter jacksonMongoSessionConverter() {
return new JacksonMongoSessionConverter();
}
@Bean
@SuppressWarnings("unchecked")
IndexResolver<MongoSession> indexResolver() {
return mock(IndexResolver.class);
}
}
}

View File

@@ -0,0 +1,17 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%8.-8thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- <logger name="org.springframework.web" level="TRACE" />-->
<!-- <logger name="org.springframework.web.reactive" level="TRACE" />-->
<!-- <logger name="org.springframework.security" level="TRACE" />-->
<!-- <logger name="org.springframework.session" level="TRACE" />-->
<!-- <logger name="org.springframework.data.mongodb" level="TRACE" />-->
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>
</configuration>