Add reactive streams support

This commit is contained in:
Greg Turnquist
2017-06-28 16:00:43 -05:00
parent 5e8273c35c
commit 51f4f2ae23
11 changed files with 466 additions and 44 deletions

View File

@@ -90,9 +90,7 @@ public abstract class AbstractMongoSessionConverter implements GenericConverter
if (resolvedPrincipal != null) {
return resolvedPrincipal;
} else {
return expiringSession.getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME)
.map(Object::toString)
.orElse("");
return expiringSession.getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
}
}

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.session.data.mongo;
import java.util.Optional;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
@@ -38,14 +36,15 @@ final class AuthenticationParser {
* @param authentication Authentication object
* @return principal name
*/
static String extractName(Optional<Object> authentication) {
static String extractName(Object authentication) {
return authentication
.map(auth -> {
Expression expression = PARSER.parseExpression(NAME_EXPRESSION);
return expression.getValue(auth, String.class);
})
.orElse(null);
if (authentication == null) {
return null;
}
Expression expression = PARSER.parseExpression(NAME_EXPRESSION);
return expression.getValue(authentication, String.class);
}
private AuthenticationParser() {}

View File

@@ -132,7 +132,7 @@ public class JdkMongoSessionConverter extends AbstractMongoSessionConverter {
Map<String, Object> attributes = new HashMap<>();
for (String attrName : session.getAttributeNames()) {
attributes.put(attrName, session.getAttribute(attrName).get());
attributes.put(attrName, session.getAttribute(attrName));
}
return this.serializer.convert(attributes);

View File

@@ -16,6 +16,8 @@
package org.springframework.session.data.mongo;
import static org.springframework.session.data.mongo.MongoSessionUtils.*;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
@@ -26,7 +28,6 @@ import javax.annotation.PostConstruct;
import org.bson.Document;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.mongodb.core.IndexOperations;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Query;
@@ -86,7 +87,7 @@ public class MongoOperationsSessionRepository
@Override
public void save(MongoSession session) {
DBObject sessionDbObject = convertToDBObject(session);
DBObject sessionDbObject = convertToDBObject(this.mongoSessionConverter, session);
this.mongoOperations.save(sessionDbObject, this.collectionName);
}
@@ -99,7 +100,7 @@ public class MongoOperationsSessionRepository
return null;
}
MongoSession session = convertToSession(sessionWrapper);
MongoSession session = convertToSession(this.mongoSessionConverter, sessionWrapper);
if (session.isExpired()) {
deleteById(id);
@@ -132,7 +133,7 @@ public class MongoOperationsSessionRepository
List<Document> mapSessions = this.mongoOperations.find(query, Document.class, this.collectionName);
for (Document dbSession : mapSessions) {
MongoSession mapSession = convertToSession(dbSession);
MongoSession mapSession = convertToSession(this.mongoSessionConverter, dbSession);
result.put(mapSession.getId(), mapSession);
}
@@ -155,20 +156,6 @@ public class MongoOperationsSessionRepository
return this.mongoOperations.findById(id, Document.class, this.collectionName);
}
MongoSession convertToSession(Document session) {
return (MongoSession) this.mongoSessionConverter.convert(session,
TypeDescriptor.valueOf(Document.class),
TypeDescriptor.valueOf(MongoSession.class));
}
DBObject convertToDBObject(MongoSession session) {
return (DBObject) this.mongoSessionConverter.convert(session,
TypeDescriptor.valueOf(MongoSession.class),
TypeDescriptor.valueOf(DBObject.class));
}
public void setMongoSessionConverter(AbstractMongoSessionConverter mongoSessionConverter) {
this.mongoSessionConverter = mongoSessionConverter;
}

View File

@@ -21,7 +21,6 @@ import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@@ -67,9 +66,9 @@ public class MongoSession implements Session {
return this.id;
}
@SuppressWarnings("unchecked")
public <T> Optional<T> getAttribute(String attributeName) {
return Optional.ofNullable((T) this.attrs.get(coverDot(attributeName)));
@Override
public <T> T getAttribute(String attributeName) {
return (T) this.attrs.get(coverDot(attributeName));
}
public Set<String> getAttributeNames() {

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.session.data.mongo;
import org.bson.Document;
import org.springframework.core.convert.TypeDescriptor;
import com.mongodb.DBObject;
/**
* @author Greg Turnquist
*/
public final class MongoSessionUtils {
static DBObject convertToDBObject(AbstractMongoSessionConverter mongoSessionConverter, MongoSession session) {
return (DBObject) mongoSessionConverter.convert(session,
TypeDescriptor.valueOf(MongoSession.class),
TypeDescriptor.valueOf(DBObject.class));
}
static MongoSession convertToSession(AbstractMongoSessionConverter mongoSessionConverter, Document session) {
return (MongoSession) mongoSessionConverter.convert(session,
TypeDescriptor.valueOf(Document.class),
TypeDescriptor.valueOf(MongoSession.class));
}
}

View File

@@ -0,0 +1,144 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.session.data.mongo;
import static org.springframework.session.data.mongo.MongoSessionUtils.*;
import java.time.Duration;
import org.bson.Document;
import reactor.core.publisher.Mono;
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.session.ReactorSessionRepository;
/**
* @author Greg Turnquist
*/
public class ReactiveMongoOperationsSessionRepository implements ReactorSessionRepository<MongoSession> {
/**
* The default time period in seconds in which a session will expire.
*/
public static final int DEFAULT_INACTIVE_INTERVAL = 1800;
/**
* the default collection name for storing session.
*/
public static final String DEFAULT_COLLECTION_NAME = "sessions";
private final ReactiveMongoOperations mongoOperations;
private AbstractMongoSessionConverter mongoSessionConverter =
SessionConverterProvider.getDefaultMongoConverter();
private Integer maxInactiveIntervalInSeconds = DEFAULT_INACTIVE_INTERVAL;
private String collectionName = DEFAULT_COLLECTION_NAME;
public ReactiveMongoOperationsSessionRepository(ReactiveMongoOperations mongoOperations) {
this.mongoOperations = mongoOperations;
}
/**
* Creates a new {@link MongoSession} that is capable of being persisted by this
* {@link ReactorSessionRepository}.
* <p>
* This allows optimizations and customizations in how the {@link MongoSession} is
* persisted. For example, the implementation returned might keep track of the changes
* ensuring that only the delta needs to be persisted on a save.
* </p>
*
* @return a new {@link MongoSession} that is capable of being persisted by this
* {@link ReactorSessionRepository}
*/
@Override
public Mono<MongoSession> createSession() {
return Mono.defer(() -> {
MongoSession session = new MongoSession();
if (this.maxInactiveIntervalInSeconds != null) {
session.setMaxInactiveInterval(Duration.ofSeconds(this.maxInactiveIntervalInSeconds));
}
return Mono.just(session);
});
}
/**
* Ensures the {@link MongoSession} created by
* {@link ReactorSessionRepository#createSession()} is saved.
* <p>
* Some implementations may choose to save as the {@link MongoSession} is updated by
* returning a {@link MongoSession} that immediately persists any changes. In this case,
* this method may not actually do anything.
* </p>
*
* @param session the {@link MongoSession} to save
*/
@Override
public Mono<Void> save(MongoSession session) {
return this.mongoOperations
.save(convertToDBObject(this.mongoSessionConverter, session), this.collectionName)
.then();
}
/**
* Gets the {@link MongoSession} by the {@link MongoSession#getId()} or null if no
* {@link MongoSession} is found.
*
* @param id the {@link MongoSession#getId()} to lookup
* @return the {@link MongoSession} by the {@link MongoSession#getId()} or null if no
* {@link MongoSession} is found.
*/
@Override
public Mono<MongoSession> findById(String id) {
return findSession(id)
.map(document -> convertToSession(this.mongoSessionConverter, document))
.filter(mongoSession -> !mongoSession.isExpired())
.switchIfEmpty(Mono.defer(() -> delete(id).then(Mono.empty())));
}
/**
* Deletes the {@link MongoSession} with the given {@link MongoSession#getId()} or does nothing
* if the {@link MongoSession} is not found.
*
* @param id the {@link MongoSession#getId()} to delete
*/
@Override
public Mono<Void> delete(String id) {
return this.mongoOperations.remove(findSession(id), this.collectionName).then();
}
Mono<Document> findSession(String id) {
return this.mongoOperations.findById(id, Document.class, this.collectionName);
}
public void setMongoSessionConverter(AbstractMongoSessionConverter mongoSessionConverter) {
this.mongoSessionConverter = mongoSessionConverter;
}
public void setMaxInactiveIntervalInSeconds(Integer maxInactiveIntervalInSeconds) {
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
}
public void setCollectionName(String collectionName) {
this.collectionName = collectionName;
}
}