Skip to content
This repository was archived by the owner on Apr 4, 2025. It is now read-only.

Commit 4fbb1d3

Browse files
committed
Introduce ReactiveMongoSessionRepository.
1 parent e3b4c38 commit 4fbb1d3

File tree

7 files changed

+221
-223
lines changed

7 files changed

+221
-223
lines changed

src/main/java/org/springframework/session/data/mongo/ReactiveMongoOperationsSessionRepository.java

Lines changed: 7 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -15,183 +15,20 @@
1515
*/
1616
package org.springframework.session.data.mongo;
1717

18-
import static org.springframework.session.data.mongo.MongoSessionUtils.*;
19-
20-
import java.time.Duration;
21-
22-
import org.bson.Document;
23-
import org.slf4j.Logger;
24-
import org.slf4j.LoggerFactory;
25-
import reactor.core.publisher.Mono;
26-
import org.springframework.beans.factory.InitializingBean;
27-
import org.springframework.context.ApplicationEvent;
28-
import org.springframework.context.ApplicationEventPublisher;
29-
import org.springframework.context.ApplicationEventPublisherAware;
30-
import org.springframework.data.mongodb.core.MongoOperations;
3118
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
32-
import org.springframework.data.mongodb.core.index.IndexOperations;
3319
import org.springframework.session.ReactiveSessionRepository;
34-
import org.springframework.session.events.SessionCreatedEvent;
35-
import org.springframework.session.events.SessionDeletedEvent;
36-
37-
import com.mongodb.DBObject;
3820

3921
/**
22+
* This {@link ReactiveSessionRepository} implementation is kept to support migration to
23+
* {@link ReactiveMongoSessionRepository} in a backwards compatible manner.
24+
*
4025
* @author Greg Turnquist
26+
* @deprecated since 2.2.0 in favor of {@link ReactiveMongoSessionRepository}.
4127
*/
42-
public class ReactiveMongoOperationsSessionRepository
43-
implements ReactiveSessionRepository<MongoSession>, ApplicationEventPublisherAware, InitializingBean {
44-
45-
/**
46-
* The default time period in seconds in which a session will expire.
47-
*/
48-
public static final int DEFAULT_INACTIVE_INTERVAL = 1800;
49-
50-
/**
51-
* The default collection name for storing session.
52-
*/
53-
public static final String DEFAULT_COLLECTION_NAME = "sessions";
54-
55-
private static final Logger logger = LoggerFactory.getLogger(ReactiveMongoOperationsSessionRepository.class);
56-
57-
private final ReactiveMongoOperations mongoOperations;
58-
59-
private Integer maxInactiveIntervalInSeconds = DEFAULT_INACTIVE_INTERVAL;
60-
private String collectionName = DEFAULT_COLLECTION_NAME;
61-
private AbstractMongoSessionConverter mongoSessionConverter = new JdkMongoSessionConverter(
62-
Duration.ofSeconds(this.maxInactiveIntervalInSeconds));
63-
private MongoOperations blockingMongoOperations;
64-
private ApplicationEventPublisher eventPublisher;
28+
@Deprecated
29+
public class ReactiveMongoOperationsSessionRepository extends ReactiveMongoSessionRepository {
6530

6631
public ReactiveMongoOperationsSessionRepository(ReactiveMongoOperations mongoOperations) {
67-
this.mongoOperations = mongoOperations;
68-
}
69-
70-
/**
71-
* Creates a new {@link MongoSession} that is capable of being persisted by this {@link ReactiveSessionRepository}.
72-
* <p>
73-
* This allows optimizations and customizations in how the {@link MongoSession} is persisted. For example, the
74-
* implementation returned might keep track of the changes ensuring that only the delta needs to be persisted on a
75-
* save.
76-
* </p>
77-
*
78-
* @return a new {@link MongoSession} that is capable of being persisted by this {@link ReactiveSessionRepository}
79-
*/
80-
@Override
81-
public Mono<MongoSession> createSession() {
82-
83-
return Mono.justOrEmpty(this.maxInactiveIntervalInSeconds) //
84-
.map(MongoSession::new) //
85-
.doOnNext(mongoSession -> publishEvent(new SessionCreatedEvent(this, mongoSession))) //
86-
.switchIfEmpty(Mono.just(new MongoSession()));
87-
}
88-
89-
/**
90-
* Ensures the {@link MongoSession} created by {@link ReactiveSessionRepository#createSession()} is saved.
91-
* <p>
92-
* Some implementations may choose to save as the {@link MongoSession} is updated by returning a {@link MongoSession}
93-
* that immediately persists any changes. In this case, this method may not actually do anything.
94-
* </p>
95-
*
96-
* @param session the {@link MongoSession} to save
97-
*/
98-
@Override
99-
public Mono<Void> save(MongoSession session) {
100-
101-
DBObject dbObject = convertToDBObject(this.mongoSessionConverter, session);
102-
if (dbObject != null) {
103-
return this.mongoOperations.save(dbObject, this.collectionName).then();
104-
} else {
105-
return Mono.empty();
106-
}
107-
}
108-
109-
/**
110-
* Gets the {@link MongoSession} by the {@link MongoSession#getId()} or {@link Mono#empty()} if no
111-
* {@link MongoSession} is found.
112-
*
113-
* @param id the {@link MongoSession#getId()} to lookup
114-
* @return the {@link MongoSession} by the {@link MongoSession#getId()} or {@link Mono#empty()} if no
115-
* {@link MongoSession} is found.
116-
*/
117-
@Override
118-
public Mono<MongoSession> findById(String id) {
119-
120-
return findSession(id) //
121-
.map(document -> convertToSession(this.mongoSessionConverter, document)) //
122-
.filter(mongoSession -> !mongoSession.isExpired()) //
123-
.switchIfEmpty(Mono.defer(() -> this.deleteById(id).then(Mono.empty())));
124-
}
125-
126-
/**
127-
* Deletes the {@link MongoSession} with the given {@link MongoSession#getId()} or does nothing if the
128-
* {@link MongoSession} is not found.
129-
*
130-
* @param id the {@link MongoSession#getId()} to delete
131-
*/
132-
@Override
133-
public Mono<Void> deleteById(String id) {
134-
135-
return findSession(id) //
136-
.flatMap(document -> this.mongoOperations.remove(document, this.collectionName) //
137-
.then(Mono.just(document))) //
138-
.map(document -> convertToSession(this.mongoSessionConverter, document)) //
139-
.doOnNext(mongoSession -> publishEvent(new SessionDeletedEvent(this, mongoSession))) //
140-
.then();
141-
}
142-
143-
/**
144-
* Do not use {@link org.springframework.data.mongodb.core.index.ReactiveIndexOperations} to ensure indexes exist.
145-
* Instead, get a blocking {@link IndexOperations} and use that instead, if possible.
146-
*/
147-
@Override
148-
public void afterPropertiesSet() {
149-
150-
if (this.blockingMongoOperations != null) {
151-
IndexOperations indexOperations = this.blockingMongoOperations.indexOps(this.collectionName);
152-
this.mongoSessionConverter.ensureIndexes(indexOperations);
153-
}
154-
}
155-
156-
private Mono<Document> findSession(String id) {
157-
return this.mongoOperations.findById(id, Document.class, this.collectionName);
158-
}
159-
160-
@Override
161-
public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
162-
this.eventPublisher = eventPublisher;
163-
}
164-
165-
private void publishEvent(ApplicationEvent event) {
166-
167-
try {
168-
this.eventPublisher.publishEvent(event);
169-
} catch (Throwable ex) {
170-
logger.error("Error publishing " + event + ".", ex);
171-
}
172-
}
173-
174-
public Integer getMaxInactiveIntervalInSeconds() {
175-
return this.maxInactiveIntervalInSeconds;
176-
}
177-
178-
public void setMaxInactiveIntervalInSeconds(final Integer maxInactiveIntervalInSeconds) {
179-
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
180-
}
181-
182-
public String getCollectionName() {
183-
return this.collectionName;
184-
}
185-
186-
public void setCollectionName(final String collectionName) {
187-
this.collectionName = collectionName;
188-
}
189-
190-
public void setMongoSessionConverter(final AbstractMongoSessionConverter mongoSessionConverter) {
191-
this.mongoSessionConverter = mongoSessionConverter;
192-
}
193-
194-
public void setBlockingMongoOperations(final MongoOperations blockingMongoOperations) {
195-
this.blockingMongoOperations = blockingMongoOperations;
32+
super(mongoOperations);
19633
}
19734
}
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
* Copyright 2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.session.data.mongo;
17+
18+
import static org.springframework.session.data.mongo.MongoSessionUtils.*;
19+
20+
import java.time.Duration;
21+
22+
import org.bson.Document;
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
25+
import reactor.core.publisher.Mono;
26+
import org.springframework.beans.factory.InitializingBean;
27+
import org.springframework.context.ApplicationEvent;
28+
import org.springframework.context.ApplicationEventPublisher;
29+
import org.springframework.context.ApplicationEventPublisherAware;
30+
import org.springframework.data.mongodb.core.MongoOperations;
31+
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
32+
import org.springframework.data.mongodb.core.index.IndexOperations;
33+
import org.springframework.session.ReactiveSessionRepository;
34+
import org.springframework.session.events.SessionCreatedEvent;
35+
import org.springframework.session.events.SessionDeletedEvent;
36+
37+
import com.mongodb.DBObject;
38+
39+
/**
40+
* A {@link ReactiveSessionRepository} implementation that uses Spring Data MongoDB.
41+
*
42+
* @author Greg Turnquist
43+
* @since 2.2.0
44+
*/
45+
public class ReactiveMongoSessionRepository
46+
implements ReactiveSessionRepository<MongoSession>, ApplicationEventPublisherAware, InitializingBean {
47+
48+
/**
49+
* The default time period in seconds in which a session will expire.
50+
*/
51+
public static final int DEFAULT_INACTIVE_INTERVAL = 1800;
52+
53+
/**
54+
* The default collection name for storing session.
55+
*/
56+
public static final String DEFAULT_COLLECTION_NAME = "sessions";
57+
58+
private static final Logger logger = LoggerFactory.getLogger(ReactiveMongoSessionRepository.class);
59+
60+
private final ReactiveMongoOperations mongoOperations;
61+
62+
private Integer maxInactiveIntervalInSeconds = DEFAULT_INACTIVE_INTERVAL;
63+
private String collectionName = DEFAULT_COLLECTION_NAME;
64+
private AbstractMongoSessionConverter mongoSessionConverter = new JdkMongoSessionConverter(
65+
Duration.ofSeconds(this.maxInactiveIntervalInSeconds));
66+
private MongoOperations blockingMongoOperations;
67+
private ApplicationEventPublisher eventPublisher;
68+
69+
public ReactiveMongoSessionRepository(ReactiveMongoOperations mongoOperations) {
70+
this.mongoOperations = mongoOperations;
71+
}
72+
73+
/**
74+
* Creates a new {@link MongoSession} that is capable of being persisted by this {@link ReactiveSessionRepository}.
75+
* <p>
76+
* This allows optimizations and customizations in how the {@link MongoSession} is persisted. For example, the
77+
* implementation returned might keep track of the changes ensuring that only the delta needs to be persisted on a
78+
* save.
79+
* </p>
80+
*
81+
* @return a new {@link MongoSession} that is capable of being persisted by this {@link ReactiveSessionRepository}
82+
*/
83+
@Override
84+
public Mono<MongoSession> createSession() {
85+
86+
return Mono.justOrEmpty(this.maxInactiveIntervalInSeconds) //
87+
.map(MongoSession::new) //
88+
.doOnNext(mongoSession -> publishEvent(new SessionCreatedEvent(this, mongoSession))) //
89+
.switchIfEmpty(Mono.just(new MongoSession()));
90+
}
91+
92+
@Override
93+
public Mono<Void> save(MongoSession session) {
94+
95+
DBObject dbObject = convertToDBObject(this.mongoSessionConverter, session);
96+
if (dbObject != null) {
97+
return this.mongoOperations.save(dbObject, this.collectionName).then();
98+
} else {
99+
return Mono.empty();
100+
}
101+
}
102+
103+
@Override
104+
public Mono<MongoSession> findById(String id) {
105+
106+
return findSession(id) //
107+
.map(document -> convertToSession(this.mongoSessionConverter, document)) //
108+
.filter(mongoSession -> !mongoSession.isExpired()) //
109+
.switchIfEmpty(Mono.defer(() -> this.deleteById(id).then(Mono.empty())));
110+
}
111+
112+
@Override
113+
public Mono<Void> deleteById(String id) {
114+
115+
return findSession(id) //
116+
.flatMap(document -> this.mongoOperations.remove(document, this.collectionName) //
117+
.then(Mono.just(document))) //
118+
.map(document -> convertToSession(this.mongoSessionConverter, document)) //
119+
.doOnNext(mongoSession -> publishEvent(new SessionDeletedEvent(this, mongoSession))) //
120+
.then();
121+
}
122+
123+
/**
124+
* Do not use {@link org.springframework.data.mongodb.core.index.ReactiveIndexOperations} to ensure indexes exist.
125+
* Instead, get a blocking {@link IndexOperations} and use that instead, if possible.
126+
*/
127+
@Override
128+
public void afterPropertiesSet() {
129+
130+
if (this.blockingMongoOperations != null) {
131+
IndexOperations indexOperations = this.blockingMongoOperations.indexOps(this.collectionName);
132+
this.mongoSessionConverter.ensureIndexes(indexOperations);
133+
}
134+
}
135+
136+
private Mono<Document> findSession(String id) {
137+
return this.mongoOperations.findById(id, Document.class, this.collectionName);
138+
}
139+
140+
@Override
141+
public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
142+
this.eventPublisher = eventPublisher;
143+
}
144+
145+
private void publishEvent(ApplicationEvent event) {
146+
147+
try {
148+
this.eventPublisher.publishEvent(event);
149+
} catch (Throwable ex) {
150+
logger.error("Error publishing " + event + ".", ex);
151+
}
152+
}
153+
154+
public Integer getMaxInactiveIntervalInSeconds() {
155+
return this.maxInactiveIntervalInSeconds;
156+
}
157+
158+
public void setMaxInactiveIntervalInSeconds(final Integer maxInactiveIntervalInSeconds) {
159+
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
160+
}
161+
162+
public String getCollectionName() {
163+
return this.collectionName;
164+
}
165+
166+
public void setCollectionName(final String collectionName) {
167+
this.collectionName = collectionName;
168+
}
169+
170+
public void setMongoSessionConverter(final AbstractMongoSessionConverter mongoSessionConverter) {
171+
this.mongoSessionConverter = mongoSessionConverter;
172+
}
173+
174+
public void setBlockingMongoOperations(final MongoOperations blockingMongoOperations) {
175+
this.blockingMongoOperations = blockingMongoOperations;
176+
}
177+
}

src/main/java/org/springframework/session/data/mongo/config/annotation/web/reactive/EnableMongoWebSession.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
import org.springframework.context.annotation.Configuration;
2323
import org.springframework.context.annotation.Import;
24-
import org.springframework.session.data.mongo.ReactiveMongoOperationsSessionRepository;
24+
import org.springframework.session.data.mongo.ReactiveMongoSessionRepository;
2525

2626
/**
2727
* Add this annotation to a {@code @Configuration} class to configure a MongoDB-based {@code WebSessionManager} for a
@@ -59,12 +59,12 @@
5959
*
6060
* @return default max inactive interval in seconds
6161
*/
62-
int maxInactiveIntervalInSeconds() default ReactiveMongoOperationsSessionRepository.DEFAULT_INACTIVE_INTERVAL;
62+
int maxInactiveIntervalInSeconds() default ReactiveMongoSessionRepository.DEFAULT_INACTIVE_INTERVAL;
6363

6464
/**
6565
* The collection name to use.
6666
*
6767
* @return name of the collection to store session
6868
*/
69-
String collectionName() default ReactiveMongoOperationsSessionRepository.DEFAULT_COLLECTION_NAME;
69+
String collectionName() default ReactiveMongoSessionRepository.DEFAULT_COLLECTION_NAME;
7070
}

0 commit comments

Comments
 (0)