Harmonize naming of session repositories

Resolves: #1455
This commit is contained in:
Vedran Pavic
2019-09-18 20:50:38 +02:00
parent 96715e04f2
commit 8cc8fbb7fd
64 changed files with 3029 additions and 2888 deletions

View File

@@ -75,7 +75,7 @@ To get started with Spring Session, the best place to start is our Sample Applic
|
| {gh-samples-url}spring-session-sample-boot-redis-simple[HttpSession with simple Redis `SessionRepository`]
| Demonstrates how to use Spring Session to replace the `HttpSession` with Redis using `SimpleRedisOperationsSessionRepository`.
| Demonstrates how to use Spring Session to replace the `HttpSession` with Redis using `RedisSessionRepository`.
|
|===
@@ -590,12 +590,12 @@ You can browse the complete link:../../api/[Javadoc] online. The key APIs are de
* <<api-reactivesessionrepository>>
* <<api-enablespringhttpsession>>
* <<api-enablespringwebsession>>
* <<api-redisoperationssessionrepository>>
* <<api-reactiveredisoperationssessionrepository>>
* <<api-redisindexedsessionrepository>>
* <<api-reactiveredissessionrepository>>
* <<api-mapsessionrepository>>
* <<api-reactivemapsessionrepository>>
* <<api-jdbcoperationssessionrepository>>
* <<api-hazelcastsessionrepository>>
* <<api-jdbcindexedsessionrepository>>
* <<api-hazelcastindexedsessionrepository>>
[[api-session]]
=== Using `Session`
@@ -727,31 +727,31 @@ Note that no infrastructure for session expirations is configured for you.
This is because things such as session expiration are highly implementation-dependent.
This means that, if you require cleaning up expired sessions, you are responsible for cleaning up the expired sessions.
[[api-redisoperationssessionrepository]]
=== Using `RedisOperationsSessionRepository`
[[api-redisindexedsessionrepository]]
=== Using `RedisIndexedSessionRepository`
`RedisOperationsSessionRepository` is a `SessionRepository` that is implemented by using Spring Data's `RedisOperations`.
`RedisIndexedSessionRepository` is a `SessionRepository` that is implemented by using Spring Data's `RedisOperations`.
In a web environment, this is typically used in combination with `SessionRepositoryFilter`.
The implementation supports `SessionDestroyedEvent` and `SessionCreatedEvent` through `SessionMessageListener`.
[[api-redisoperationssessionrepository-new]]
==== Instantiating a `RedisOperationsSessionRepository`
[[api-redisindexedsessionrepository-new]]
==== Instantiating a `RedisIndexedSessionRepository`
You can see a typical example of how to create a new instance in the following listing:
====
[source,java,indent=0]
----
include::{indexdoc-tests}[tags=new-redisoperationssessionrepository]
include::{indexdoc-tests}[tags=new-redisindexedsessionrepository]
----
====
For additional information on how to create a `RedisConnectionFactory`, see the Spring Data Redis Reference.
[[api-redisoperationssessionrepository-config]]
[[api-redisindexedsessionrepository-config]]
==== Using `@EnableRedisHttpSession`
In a web environment, the simplest way to create a new `RedisOperationsSessionRepository` is to use `@EnableRedisHttpSession`.
In a web environment, the simplest way to create a new `RedisIndexedSessionRepository` is to use `@EnableRedisHttpSession`.
You can find complete example usage in the <<samples>>.
You can use the following attributes to customize the configuration:
@@ -766,11 +766,11 @@ You can customize the serialization by creating a bean named `springSessionDefau
==== Redis `TaskExecutor`
`RedisOperationsSessionRepository` is subscribed to receive events from Redis by using a `RedisMessageListenerContainer`.
`RedisIndexedSessionRepository` is subscribed to receive events from Redis by using a `RedisMessageListenerContainer`.
You can customize the way those events are dispatched by creating a bean named `springSessionRedisTaskExecutor`, a bean `springSessionRedisSubscriptionExecutor`, or both.
You can find more details on configuring Redis task executors https://docs.spring.io/spring-data-redis/docs/{spring-data-redis-version}/reference/html/#redis:pubsub:subscribe:containers[here].
[[api-redisoperationssessionrepository-storage]]
[[api-redisindexedsessionrepository-storage]]
==== Storage Details
The following sections outline how Redis is updated for each operation.
@@ -819,10 +819,10 @@ In the preceding example, the following statements are true about the session:
The first is `attrName`, with a value of `someAttrValue`.
The second session attribute is named `attrName2`, with a value of `someAttrValue2`.
[[api-redisoperationssessionrepository-writes]]
[[api-redisindexedsessionrepository-writes]]
===== Optimized Writes
The `Session` instances managed by `RedisOperationsSessionRepository` keeps track of the properties that have changed and updates only those.
The `Session` instances managed by `RedisIndexedSessionRepository` keeps track of the properties that have changed and updates only those.
This means that, if an attribute is written once and read many times, we need to write that attribute only once.
For example, assume the `sessionAttr2` session attribute from the lsiting in the preceding section was updated.
The following command would be run upon saving:
@@ -833,7 +833,7 @@ HMSET spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe sessionAttr:a
----
====
[[api-redisoperationssessionrepository-expiration]]
[[api-redisindexedsessionrepository-expiration]]
===== Session Expiration
An expiration is associated with each session by using the `EXPIRE` command, based upon the `Session.getMaxInactiveInterval()`.
@@ -852,7 +852,7 @@ An expiration is set on the session itself five minutes after it actually expire
NOTE: The `SessionRepository.findById(String)` method ensures that no expired sessions are returned.
This means that you need not check the expiration before using a session.
Spring Session relies on the delete and expired https://redis.io/topics/notifications[keyspace notifications] from Redis to fire a <<api-redisoperationssessionrepository-sessiondestroyedevent,`SessionDeletedEvent`>> and a <<api-redisoperationssessionrepository-sessiondestroyedevent,`SessionExpiredEvent`>>, respectively.
Spring Session relies on the delete and expired https://redis.io/topics/notifications[keyspace notifications] from Redis to fire a <<api-redisindexedsessionrepository-sessiondestroyedevent,`SessionDeletedEvent`>> and a <<api-redisindexedsessionrepository-sessiondestroyedevent,`SessionExpiredEvent`>>, respectively.
`SessionDeletedEvent` or `SessionExpiredEvent` ensure that resources associated with the `Session` are cleaned up.
For example, when you use Spring Session's WebSocket support, the Redis expired or delete event triggers any WebSocket connections associated with the session to be closed.
@@ -893,12 +893,12 @@ Short of using distributed locks (which would kill our performance), there is no
By simply accessing the key, we ensure that the key is only removed if the TTL on that key is expired.
[[api-redisoperationssessionrepository-sessiondestroyedevent]]
[[api-redisindexedsessionrepository-sessiondestroyedevent]]
==== `SessionDeletedEvent` and `SessionExpiredEvent`
`SessionDeletedEvent` and `SessionExpiredEvent` are both types of `SessionDestroyedEvent`.
`RedisOperationsSessionRepository` supports firing a `SessionDeletedEvent` when a `Session` is deleted or a `SessionExpiredEvent` when a `Session` expires.
`RedisIndexedSessionRepository` supports firing a `SessionDeletedEvent` when a `Session` is deleted or a `SessionExpiredEvent` when a `Session` expires.
This is necessary to ensure resources associated with the `Session` are properly cleaned up.
For example, when integrating with WebSockets, the `SessionDestroyedEvent` is in charge of closing any active WebSocket connections.
@@ -937,15 +937,15 @@ include::{docs-test-resources-dir}docs/HttpSessionConfigurationNoOpConfigureRedi
----
====
[[api-redisoperationssessionrepository-sessioncreatedevent]]
[[api-redisindexedsessionrepository-sessioncreatedevent]]
==== Using `SessionCreatedEvent`
When a session is created, an event is sent to Redis with a channel ID of `spring:session:channel:created:33fdd1b6-b496-4b33-9f7d-df96679d32fe`,
where `33fdd1b6-b496-4b33-9f7d-df96679d32fe` is the session ID. The body of the event is the session that was created.
If registered as a `MessageListener` (the default), `RedisOperationsSessionRepository` then translates the Redis message into a `SessionCreatedEvent`.
If registered as a `MessageListener` (the default), `RedisIndexedSessionRepository` then translates the Redis message into a `SessionCreatedEvent`.
[[api-redisoperationssessionrepository-cli]]
[[api-redisindexedsessionrepository-cli]]
==== Viewing the Session in Redis
After https://redis.io/topics/quickstart[installing redis-cli], you can inspect the values in Redis https://redis.io/commands#hash[using the redis-cli].
@@ -980,30 +980,30 @@ redis 127.0.0.1:6379> hget spring:session:sessions:4fc39ce3-63b3-4e17-b1c4-5e1ed
----
====
[[api-reactiveredisoperationssessionrepository]]
=== Using `ReactiveRedisOperationsSessionRepository`
[[api-reactiveredissessionrepository]]
=== Using `ReactiveRedisSessionRepository`
`ReactiveRedisOperationsSessionRepository` is a `ReactiveSessionRepository` that is implemented by using Spring Data's `ReactiveRedisOperations`.
`ReactiveRedisSessionRepository` is a `ReactiveSessionRepository` that is implemented by using Spring Data's `ReactiveRedisOperations`.
In a web environment, this is typically used in combination with `WebSessionStore`.
[[api-reactiveredisoperationssessionrepository-new]]
==== Instantiating a `ReactiveRedisOperationsSessionRepository`
[[api-reactiveredissessionrepository-new]]
==== Instantiating a `ReactiveRedisSessionRepository`
The following example shows how to create a new instance:
====
[source,java,indent=0]
----
include::{indexdoc-tests}[tags=new-reactiveredisoperationssessionrepository]
include::{indexdoc-tests}[tags=new-reactiveredissessionrepository]
----
====
For additional information on how to create a `ReactiveRedisConnectionFactory`, see the Spring Data Redis Reference.
[[api-reactiveredisoperationssessionrepository-config]]
[[api-reactiveredissessionrepository-config]]
==== Using `@EnableRedisWebSession`
In a web environment, the simplest way to create a new `ReactiveRedisOperationsSessionRepository` is to use `@EnableRedisWebSession`.
In a web environment, the simplest way to create a new `ReactiveRedisSessionRepository` is to use `@EnableRedisWebSession`.
You can use the following attributes to customize the configuration:
* *maxInactiveIntervalInSeconds*: The amount of time before the session expires, in seconds
@@ -1011,13 +1011,13 @@ You can use the following attributes to customize the configuration:
* *flushMode*: Allows specifying when data is written to Redis. The default is only when `save` is invoked on `ReactiveSessionRepository`.
A value of `FlushMode.IMMEDIATE` writes to Redis as soon as possible.
[[api-reactiveredisoperationssessionrepository-writes]]
[[api-reactiveredissessionrepository-writes]]
===== Optimized Writes
The `Session` instances managed by `ReactiveRedisOperationsSessionRepository` keep track of the properties that have changed and updates only those.
The `Session` instances managed by `ReactiveRedisSessionRepository` keep track of the properties that have changed and updates only those.
This means that, if an attribute is written once and read many times, we need to write that attribute only once.
[[api-reactiveredisoperationssessionrepository-cli]]
[[api-reactiveredissessionrepository-cli]]
==== Viewing the Session in Redis
After https://redis.io/topics/quickstart[installing redis-cli], you can inspect the values in Redis https://redis.io/commands#hash[using the redis-cli].
@@ -1101,31 +1101,31 @@ The `ReactiveMapSessionRepository` allows for persisting `Session` in a `Map`, w
You can use the implementation with a `ConcurrentHashMap` as a testing or convenience mechanism.
Alternatively, you can use it with distributed `Map` implementations, with the requirement that the supplied `Map` must be non-blocking.
[[api-jdbcoperationssessionrepository]]
=== Using `JdbcOperationsSessionRepository`
[[api-jdbcindexedsessionrepository]]
=== Using `JdbcIndexedSessionRepository`
`JdbcOperationsSessionRepository` is a `SessionRepository` implementation that uses Spring's `JdbcOperations` to store sessions in a relational database.
`JdbcIndexedSessionRepository` is a `SessionRepository` implementation that uses Spring's `JdbcOperations` to store sessions in a relational database.
In a web environment, this is typically used in combination with `SessionRepositoryFilter`.
Note that this implementation does not support publishing of session events.
[[api-jdbcoperationssessionrepository-new]]
==== Instantiating a `JdbcOperationsSessionRepository`
[[api-jdbcindexedsessionrepository-new]]
==== Instantiating a `JdbcIndexedSessionRepository`
The following example shows how to create a new instance:
====
[source,java,indent=0]
----
include::{indexdoc-tests}[tags=new-jdbcoperationssessionrepository]
include::{indexdoc-tests}[tags=new-jdbcindexedsessionrepository]
----
====
For additional information on how to create and configure `JdbcTemplate` and `PlatformTransactionManager`, see the https://docs.spring.io/spring/docs/{spring-framework-version}/spring-framework-reference/data-access.html[Spring Framework Reference Documentation].
[[api-jdbcoperationssessionrepository-config]]
[[api-jdbcindexedsessionrepository-config]]
==== Using `@EnableJdbcHttpSession`
In a web environment, the simplest way to create a new `JdbcOperationsSessionRepository` is to use `@EnableJdbcHttpSession`.
In a web environment, the simplest way to create a new `JdbcIndexedSessionRepository` is to use `@EnableJdbcHttpSession`.
You can find complete example usage in the <<samples>>
You can use the following attributes to customize the configuration:
@@ -1142,7 +1142,7 @@ You can customize the default serialization and deserialization of the session b
When working in a typical Spring environment, the default `ConversionService` bean (named `conversionService`) is automatically picked up and used for serialization and deserialization.
However, you can override the default `ConversionService` by providing a bean named `springSessionConversionService`.
[[api-jdbcoperationssessionrepository-storage]]
[[api-jdbcindexedsessionrepository-storage]]
==== Storage Details
By default, this implementation uses `SPRING_SESSION` and `SPRING_SESSION_ATTRIBUTES` tables to store sessions.
@@ -1172,24 +1172,24 @@ include::{session-jdbc-main-resources-dir}org/springframework/session/jdbc/schem
==== Transaction Management
All JDBC operations in `JdbcOperationsSessionRepository` are executed in a transactional manner.
All JDBC operations in `JdbcIndexedSessionRepository` are executed in a transactional manner.
Transactions are executed with propagation set to `REQUIRES_NEW` in order to avoid unexpected behavior due to interference with existing transactions (for example, running a `save` operation in a thread that already participates in a read-only transaction).
[[api-hazelcastsessionrepository]]
=== Using `HazelcastSessionRepository`
[[api-hazelcastindexedsessionrepository]]
=== Using `HazelcastIndexedSessionRepository`
`HazelcastSessionRepository` is a `SessionRepository` implementation that stores sessions in Hazelcast's distributed `IMap`.
`HazelcastIndexedSessionRepository` is a `SessionRepository` implementation that stores sessions in Hazelcast's distributed `IMap`.
In a web environment, this is typically used in combination with `SessionRepositoryFilter`.
[[api-hazelcastsessionrepository-new]]
==== Instantiating a `HazelcastSessionRepository`
[[api-hazelcastindexedsessionrepository-new]]
==== Instantiating a `HazelcastIndexedSessionRepository`
The following example shows how to create a new instance:
====
[source,java,indent=0]
----
include::{indexdoc-tests}[tags=new-hazelcastsessionrepository]
include::{indexdoc-tests}[tags=new-hazelcastindexedsessionrepository]
----
====
@@ -1351,7 +1351,7 @@ The minimum requirements for Spring Session are:
* Java 8+.
* If you run in a Servlet Container (not required), Servlet 3.1+.
* If you use other Spring libraries (not required), the minimum required version is Spring 5.0.x.
* `@EnableRedisHttpSession` requires Redis 2.8+. This is necessary to support <<api-redisoperationssessionrepository-expiration,Session Expiration>>
* `@EnableRedisHttpSession` requires Redis 2.8+. This is necessary to support <<api-redisindexedsessionrepository-expiration,Session Expiration>>
* `@EnableHazelcastHttpSession` requires Hazelcast 3.6+. This is necessary to support <<api-enablehazelcasthttpsession-storage,`FindByIndexNameSessionRepository`>>
NOTE: At its core, Spring Session has a required dependency only on `spring-jcl`.

View File

@@ -36,10 +36,10 @@ import org.springframework.session.MapSessionRepository;
import org.springframework.session.ReactiveSessionRepository;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.session.data.redis.ReactiveRedisOperationsSessionRepository;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.session.hazelcast.HazelcastSessionRepository;
import org.springframework.session.jdbc.JdbcOperationsSessionRepository;
import org.springframework.session.data.redis.ReactiveRedisSessionRepository;
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
import org.springframework.session.web.http.SessionRepositoryFilter;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
@@ -119,32 +119,31 @@ class IndexDocTests {
@Test
@SuppressWarnings("unused")
void newRedisOperationsSessionRepository() {
// tag::new-redisoperationssessionrepository[]
void newRedisIndexedSessionRepository() {
// tag::new-redisindexedsessionrepository[]
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
// ... configure redisTemplate ...
SessionRepository<? extends Session> repository = new RedisOperationsSessionRepository(redisTemplate);
// end::new-redisoperationssessionrepository[]
SessionRepository<? extends Session> repository = new RedisIndexedSessionRepository(redisTemplate);
// end::new-redisindexedsessionrepository[]
}
@Test
@SuppressWarnings("unused")
void newReactiveRedisOperationsSessionRepository() {
void newReactiveRedisSessionRepository() {
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory();
RedisSerializationContext<String, Object> serializationContext = RedisSerializationContext
.<String, Object>newSerializationContext(new JdkSerializationRedisSerializer()).build();
// tag::new-reactiveredisoperationssessionrepository[]
// tag::new-reactiveredissessionrepository[]
// ... create and configure connectionFactory and serializationContext ...
ReactiveRedisTemplate<String, Object> redisTemplate = new ReactiveRedisTemplate<>(connectionFactory,
serializationContext);
ReactiveSessionRepository<? extends Session> repository = new ReactiveRedisOperationsSessionRepository(
redisTemplate);
// end::new-reactiveredisoperationssessionrepository[]
ReactiveSessionRepository<? extends Session> repository = new ReactiveRedisSessionRepository(redisTemplate);
// end::new-reactiveredissessionrepository[]
}
@Test
@@ -157,8 +156,8 @@ class IndexDocTests {
@Test
@SuppressWarnings("unused")
void newJdbcOperationsSessionRepository() {
// tag::new-jdbcoperationssessionrepository[]
void newJdbcIndexedSessionRepository() {
// tag::new-jdbcindexedsessionrepository[]
JdbcTemplate jdbcTemplate = new JdbcTemplate();
// ... configure jdbcTemplate ...
@@ -167,15 +166,15 @@ class IndexDocTests {
// ... configure transactionTemplate ...
SessionRepository<? extends Session> repository = new JdbcOperationsSessionRepository(jdbcTemplate,
SessionRepository<? extends Session> repository = new JdbcIndexedSessionRepository(jdbcTemplate,
transactionTemplate);
// end::new-jdbcoperationssessionrepository[]
// end::new-jdbcindexedsessionrepository[]
}
@Test
@SuppressWarnings("unused")
void newHazelcastSessionRepository() {
// tag::new-hazelcastsessionrepository[]
void newHazelcastIndexedSessionRepository() {
// tag::new-hazelcastindexedsessionrepository[]
Config config = new Config();
@@ -183,8 +182,8 @@ class IndexDocTests {
HazelcastInstance hazelcastInstance = Hazelcast.newHazelcastInstance(config);
HazelcastSessionRepository repository = new HazelcastSessionRepository(hazelcastInstance);
// end::new-hazelcastsessionrepository[]
HazelcastIndexedSessionRepository repository = new HazelcastIndexedSessionRepository(hazelcastInstance);
// end::new-hazelcastindexedsessionrepository[]
}
@Test

View File

@@ -24,7 +24,7 @@ import com.hazelcast.core.HazelcastInstance;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.hazelcast.HazelcastSessionRepository;
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
import org.springframework.session.hazelcast.PrincipalNameExtractor;
import org.springframework.session.hazelcast.config.annotation.web.http.EnableHazelcastHttpSession;
@@ -36,14 +36,14 @@ public class HazelcastHttpSessionConfig {
@Bean
public HazelcastInstance hazelcastInstance() {
MapAttributeConfig attributeConfig = new MapAttributeConfig()
.setName(HazelcastSessionRepository.PRINCIPAL_NAME_ATTRIBUTE)
.setName(HazelcastIndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE)
.setExtractor(PrincipalNameExtractor.class.getName());
Config config = new Config();
config.getMapConfig(HazelcastSessionRepository.DEFAULT_SESSION_MAP_NAME) // <2>
.addMapAttributeConfig(attributeConfig)
.addMapIndexConfig(new MapIndexConfig(HazelcastSessionRepository.PRINCIPAL_NAME_ATTRIBUTE, false));
config.getMapConfig(HazelcastIndexedSessionRepository.DEFAULT_SESSION_MAP_NAME) // <2>
.addMapAttributeConfig(attributeConfig).addMapIndexConfig(
new MapIndexConfig(HazelcastIndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE, false));
return Hazelcast.newHazelcastInstance(config); // <3>
}