Introduce Session-based events

Resolves #22.
This commit is contained in:
Greg Turnquist
2018-01-10 17:01:37 -06:00
parent b77a7b3c67
commit f2a6caa6fd
3 changed files with 76 additions and 4 deletions

View File

@@ -28,10 +28,18 @@ import java.util.Optional;
import javax.annotation.PostConstruct;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.events.SessionCreatedEvent;
import org.springframework.session.events.SessionDeletedEvent;
import org.springframework.session.events.SessionExpiredEvent;
import com.mongodb.DBObject;
@@ -48,7 +56,7 @@ import com.mongodb.DBObject;
* @since 1.2
*/
public class MongoOperationsSessionRepository
implements FindByIndexNameSessionRepository<MongoSession> {
implements FindByIndexNameSessionRepository<MongoSession>, ApplicationEventPublisherAware {
/**
* The default time period in seconds in which a session will expire.
@@ -60,12 +68,15 @@ public class MongoOperationsSessionRepository
*/
public static final String DEFAULT_COLLECTION_NAME = "sessions";
private static final Logger logger = LoggerFactory.getLogger(MongoOperationsSessionRepository.class);
private final MongoOperations mongoOperations;
private Integer maxInactiveIntervalInSeconds = DEFAULT_INACTIVE_INTERVAL;
private String collectionName = DEFAULT_COLLECTION_NAME;
private AbstractMongoSessionConverter mongoSessionConverter = new JdkMongoSessionConverter(
Duration.ofSeconds(this.maxInactiveIntervalInSeconds));
private ApplicationEventPublisher eventPublisher;
public MongoOperationsSessionRepository(MongoOperations mongoOperations) {
this.mongoOperations = mongoOperations;
@@ -79,6 +90,8 @@ public class MongoOperationsSessionRepository
if (this.maxInactiveIntervalInSeconds != null) {
session.setMaxInactiveInterval(Duration.ofSeconds(this.maxInactiveIntervalInSeconds));
}
publishEvent(new SessionCreatedEvent(this, session));
return session;
}
@@ -102,6 +115,7 @@ public class MongoOperationsSessionRepository
MongoSession session = convertToSession(this.mongoSessionConverter, sessionWrapper);
if (session.isExpired()) {
publishEvent(new SessionExpiredEvent(this, session));
deleteById(id);
return null;
}
@@ -142,7 +156,10 @@ public class MongoOperationsSessionRepository
@Override
public void deleteById(String id) {
Optional.ofNullable(findSession(id))
.ifPresent(document -> this.mongoOperations.remove(document, this.collectionName));
.ifPresent(document -> {
publishEvent(new SessionDeletedEvent(this, convertToSession(this.mongoSessionConverter, document)));
this.mongoOperations.remove(document, this.collectionName);
});
}
@PostConstruct
@@ -167,4 +184,19 @@ public class MongoOperationsSessionRepository
public void setCollectionName(String collectionName) {
this.collectionName = collectionName;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
private void publishEvent(ApplicationEvent event) {
try {
this.eventPublisher.publishEvent(event);
}
catch (Throwable ex) {
logger.error("Error publishing " + event + ".", ex);
}
}
}

View File

@@ -22,16 +22,24 @@ import java.time.Duration;
import javax.annotation.PostConstruct;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
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.ReactiveSessionRepository;
import org.springframework.session.events.SessionCreatedEvent;
import org.springframework.session.events.SessionDeletedEvent;
/**
* @author Greg Turnquist
*/
public class ReactiveMongoOperationsSessionRepository implements ReactiveSessionRepository<MongoSession> {
public class ReactiveMongoOperationsSessionRepository
implements ReactiveSessionRepository<MongoSession>, ApplicationEventPublisherAware {
/**
* The default time period in seconds in which a session will expire.
@@ -43,6 +51,8 @@ public class ReactiveMongoOperationsSessionRepository implements ReactiveSession
*/
public static final String DEFAULT_COLLECTION_NAME = "sessions";
private static final Logger logger = LoggerFactory.getLogger(ReactiveMongoOperationsSessionRepository.class);
private final ReactiveMongoOperations mongoOperations;
private Integer maxInactiveIntervalInSeconds = DEFAULT_INACTIVE_INTERVAL;
@@ -51,6 +61,7 @@ public class ReactiveMongoOperationsSessionRepository implements ReactiveSession
Duration.ofSeconds(this.maxInactiveIntervalInSeconds));
private MongoOperations blockingMongoOperations;
private ApplicationEventPublisher eventPublisher;
public ReactiveMongoOperationsSessionRepository(ReactiveMongoOperations mongoOperations) {
this.mongoOperations = mongoOperations;
@@ -73,6 +84,10 @@ public class ReactiveMongoOperationsSessionRepository implements ReactiveSession
return Mono.justOrEmpty(this.maxInactiveIntervalInSeconds)
.map(MongoSession::new)
.map(mongoSession -> {
publishEvent(new SessionCreatedEvent(this, mongoSession));
return mongoSession;
})
.switchIfEmpty(Mono.just(new MongoSession()));
}
@@ -120,7 +135,12 @@ public class ReactiveMongoOperationsSessionRepository implements ReactiveSession
*/
@Override
public Mono<Void> deleteById(String id) {
return this.mongoOperations.remove(findSession(id), this.collectionName).then();
return findSession(id)
.flatMap(document -> this.mongoOperations.remove(document, this.collectionName).then(Mono.just(document)))
.map(document -> convertToSession(this.mongoSessionConverter, document))
.map(mongoSession -> Mono.fromRunnable(() -> publishEvent(new SessionDeletedEvent(this, mongoSession))))
.then();
}
/**
@@ -167,4 +187,18 @@ public class ReactiveMongoOperationsSessionRepository implements ReactiveSession
public void setBlockingMongoOperations(MongoOperations blockingMongoOperations) {
this.blockingMongoOperations = blockingMongoOperations;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
private void publishEvent(ApplicationEvent event) {
try {
this.eventPublisher.publishEvent(event);
}
catch (Throwable ex) {
logger.error("Error publishing " + event + ".", ex);
}
}
}

View File

@@ -141,6 +141,7 @@ public class MongoOperationsSessionRepositoryTest {
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);
@@ -156,7 +157,12 @@ public class MongoOperationsSessionRepositoryTest {
String sessionId = UUID.randomUUID().toString();
Document sessionDocument = new Document();
sessionDocument.put("id", sessionId);
MongoSession mongoSession = new MongoSession(sessionId, MongoOperationsSessionRepository.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(MongoOperationsSessionRepository.DEFAULT_COLLECTION_NAME))).willReturn(sessionDocument);