Compare commits

..

329 Commits

Author SHA1 Message Date
Marcus Da Coregio
37d1f68766 Release 3.0.1 2023-03-21 10:33:18 -03:00
Marcus Da Coregio
d2fe7d0e74 Update org.mongodb to 4.8.2
Closes gh-2271
2023-03-21 10:32:44 -03:00
Marcus Da Coregio
380dae16d2 Update to spring-security-bom:6.0.2
Closes gh-2270
2023-03-21 10:32:37 -03:00
Marcus Da Coregio
6aa71d45f9 Update to spring-data-bom:2022.0.3
Closes gh-2269
2023-03-21 10:32:28 -03:00
Marcus Da Coregio
635a6d4dd6 Update to spring-framework-bom:6.0.6
Closes gh-2268
2023-03-21 10:32:16 -03:00
Marcus Da Coregio
a69d53c17f Update to junit-bom:5.9.2
Closes gh-2267
2023-03-21 10:32:10 -03:00
Marcus Da Coregio
0afc216d21 Update to jackson-bom:2.14.2
Closes gh-2266
2023-03-21 10:32:02 -03:00
Marcus Da Coregio
801a0057fd Update reactor-bom to 2022.0.5
Closes gh-2265
2023-03-21 10:29:14 -03:00
Marcus Da Coregio
7d1b01daf6 Update Antora Plugin to 1.0.0
Issue gh-2234
2023-03-06 14:43:21 -03:00
Marcus Da Coregio
d7d36846a1 Merge branch '2.7.x' 2023-03-06 14:23:39 -03:00
Marcus Da Coregio
d48aa09b9c Update to mariadb-java-client 2.7.8
Closes gh-2255
2023-03-06 13:58:02 -03:00
Marcus Da Coregio
02a6dbc08a Revert "Update to mariadb-java-client 3.0.10"
This reverts commit acb59258
2023-03-06 13:55:08 -03:00
Marcus Da Coregio
e4a023fa64 Revert "Update Antora Plugin to 1.0.0"
This reverts commit 280f311677.
2023-03-06 13:52:52 -03:00
Rob Winch
1e10dfe1a3 Merge remote-tracking branch 'origin/2.7.x' 2023-02-21 17:23:51 -06:00
Rob Winch
e8837c83e9 Next Development Version 2023-02-21 17:21:56 -06:00
Rob Winch
b4b9ea8112 Release 2.7.1 2023-02-21 17:21:18 -06:00
Rob Winch
c571f7479c Update to org.postgresql:postgresql:42.3.8
Closes gh-2250
2023-02-21 17:13:06 -06:00
Rob Winch
63d7580a69 Update to MongoDB 4.6.1
Closes gh-2249
2023-02-21 17:12:19 -06:00
Rob Winch
c466aa5dd3 Update to Mockito 4.5.1
Closes gh-2248
2023-02-21 17:11:33 -06:00
Rob Winch
acb59258c3 Update to mariadb-java-client 3.0.10
Closes gh-2247
2023-02-21 17:10:44 -06:00
Rob Winch
e5022757a9 Update to mysql-connector-java 8.0.32
Closes gh-2246
2023-02-21 17:09:49 -06:00
Rob Winch
ddad8010eb Update to lettuce 6.1.10.RELEASE
Closes gh-2245
2023-02-21 17:09:01 -06:00
Rob Winch
fc3e2e1c64 Update to HikariCP:4.0.3
Closes gh-2244
2023-02-21 17:08:18 -06:00
Rob Winch
eb169f8186 Update to com.ibm.db2:jcc:11.5.8.0
Closes gh-2243
2023-02-21 17:07:23 -06:00
Rob Winch
5fd7c9ddcf Update to testcontainers 1.17.6
Closes gh-2242
2023-02-21 17:06:13 -06:00
Rob Winch
8898ceb4a7 Update to Spring Security 5.7.6
Closes gh-2241
2023-02-21 17:05:25 -06:00
Rob Winch
c4e9a93d02 Update to Spring Data 20201.2.7
Closes gh-2240
2023-02-21 17:04:17 -06:00
Rob Winch
d8ab39eba7 Update to Spring Framework 5.3.25
Closes gh-2239
2023-02-21 17:03:19 -06:00
Rob Winch
6a5f101656 Update to Jackson 2.13.4.20221013
Closes gh-2238
2023-02-21 17:02:26 -06:00
Rob Winch
88d34035a6 Update to Reactor 2020.0.27
Closes gh-2237
2023-02-21 17:01:26 -06:00
Rob Winch
81ef425b1b Spring to Boot 2.7.8
Closes gh-2236
2023-02-21 16:59:46 -06:00
Marcus Da Coregio
280f311677 Update Antora Plugin to 1.0.0
Issue gh-2234
2023-02-16 09:41:50 -03:00
Marcel Wollschläger
8da5068cac Update Redis example documentation
With the release of Spring-Boot 3.x, the application properties for Redis
changed from `spring.redis` to `spring.data.redis`.
This change will update the documentation to be consistent with the latest
changes in Spring-Boot.
2023-01-24 09:44:47 -03:00
Marcus Da Coregio
9276e1ddc6 Merge branch '2.7.x' 2023-01-23 13:59:11 -03:00
Kaoru Muta
fab1f7b38e docs: fix broken links in hazelcast documents 2023-01-23 13:57:39 -03:00
Marcus Da Coregio
a09146a2ed Merge branch '2.7.x' 2023-01-23 13:50:44 -03:00
Eddú Meléndez
0dfc97289f Polish related to testcontainers
* Use getHost instead of getContainerIpAddress
* Rely on OracleContainer and it's improvements which involve the log
wait strategy
2023-01-23 13:47:59 -03:00
Marcus Da Coregio
13c7ee54a8 Merge branch '2.7.x' 2023-01-23 12:59:31 -03:00
Marcus Da Coregio
7c927c7f38 Setup forward merge
Closes gh-2228
2023-01-23 11:52:06 -03:00
Marcus Da Coregio
c98a7be0e2 Remove System.out.println
Closes gh-2215
2022-12-01 10:17:20 -03:00
Marcus Da Coregio
8f9c69ea02 Add jakarta.servlet.jsp.jstl-api to non Spring Boot samples
Closes gh-2216
2022-12-01 09:07:19 -03:00
Rob Winch
df3f9a386e Next Development Version 2022-11-22 09:09:55 -06:00
Rob Winch
77e062b2cd Release 3.0.0 2022-11-22 09:08:17 -06:00
Rob Winch
2a3b76fee5 Update to Spring Security 6.0.0
Closes gh-2211
2022-11-22 09:06:02 -06:00
Rob Winch
d5b75228fc Update to Spring Data 2022.0.0
Closes gh-2210
2022-11-22 09:03:59 -06:00
Rob Winch
3d7c668e57 Update to Spring Framework 6.0.0
Closes gh-2209
2022-11-22 09:02:56 -06:00
Rob Winch
e83cf082c4 Merge branch '2.7.x' 2022-11-15 14:20:11 -06:00
Rob Winch
cbd1c66c13 Merge branch '2.6.x' into 2.7.x 2022-11-15 14:20:00 -06:00
Rob Winch
9f7a969a6e Fix Snapshot Deploy
This commit merges a workaround to an issue in JFrog's Gradle plugin
which causes SNAPSHOTs to be out of sync and thus prevents downloading.

Closes gh-2177
2022-11-15 14:17:26 -06:00
Rob Winch
f51310ee64 Merge branch '2.7.x' 2022-11-15 13:45:25 -06:00
Rob Winch
5f2523e211 Merge branch '2.6.x' into 2.7.x 2022-11-15 13:44:56 -06:00
Bakul Kakadiya
26986a6b7d Corrected documentation Reference Link 2022-11-15 11:49:05 -06:00
Craig Andrews
6cdb77378d Update reference site link
https://docs.spring.io/spring-session/docs/current/reference/html5/ goes to a 404 page

Use https://docs.spring.io/spring-session/reference/ instead which is the current documentation site.
2022-11-15 11:48:28 -06:00
Vedran Pavic
238416ec23 Polish HttpSessionAdapter 2022-11-15 11:47:01 -06:00
Vedran Pavic
4b99428267 Polish SessionRepositoryFilterTests 2022-11-15 11:47:01 -06:00
Dan Allen
058e4e46a5 label jpg as binary file in .gitattributes 2022-11-15 11:34:19 -06:00
Rob Winch
fd3609c6f0 Next Development Version 2022-11-09 13:09:53 -06:00
Rob Winch
a0d03adbe1 Release 3.0.0-RC2 2022-11-09 12:44:49 -06:00
Rob Winch
b229103d8c Remove spring-session-sample-javaconfig-rest
Works around a compatability issue for now.

Issue gh-2201
2022-11-09 12:44:31 -06:00
Rob Winch
94b441c676 Define websocket depenendencies
Issue gh-2204
2022-11-09 12:43:22 -06:00
Rob Winch
b2f10c6752 Next Development Version 2022-11-09 10:24:54 -06:00
Rob Winch
b3d228eb2e Release 3.0.0-RC2 2022-11-09 10:24:22 -06:00
Rob Winch
19dd3d8be1 Revert "Update for docs-build branch"
This reverts commit cd628fe5af.
2022-11-09 10:22:52 -06:00
Rob Winch
1aaffb28fc Update to Spring Security 6.0.0-RC2
Closes gh-2206
2022-11-09 09:56:24 -06:00
Rob Winch
75af61ca6c Update to Spring Data 2022.0.0-RC2
Closes gh-2205
2022-11-09 09:55:30 -06:00
Rob Winch
2fff593423 Update to Spring Framework 6.0.0-RC4
Closes gh-2204
2022-11-09 09:54:10 -06:00
Rob Winch
6a381d3226 Update to reactor-bom:2022.0.0
Closes gh-2203
2022-11-09 09:53:09 -06:00
Rob Winch
cd628fe5af Update for docs-build branch 2022-11-08 12:59:06 -06:00
Andy Wilkinson
ee4df64bb1 Align wth Servlet 6.0 API 2022-11-07 10:27:13 -06:00
Andy Wilkinson
d850762bce Avoid changing line endings of png and mmdb files 2022-11-07 10:05:58 -06:00
Vedran Pavic
f71d1d6ca4 Add Spring Session BOM module
With Spring Session Data Geode module being removed from the BOM, all of Spring Session's modules are now managed by this repository.

This means that the BOM itself can be moved to this repository, in order to simplify the overall project maintenance.

See gh-2195
2022-10-25 14:33:58 -05:00
Vedran Pavic
e5eeacec5f Update security config in samples
This commit updates security configuration in samples to:

- use AuthorizationFilter instead of FilterSecurityInterceptor
- update session creation policy in REST sample
2022-10-25 14:27:39 -05:00
Rob Winch
62ec64310b Next Development Version 2022-10-18 20:46:04 -05:00
Rob Winch
25d810eaa3 Release 3.0.0-RC1 2022-10-18 20:46:04 -05:00
Vedran Pavic
82db55c3f8 Polish SessionRepositoryFilter
This commit polishes SessionRepositoryFilter by simplifying some code paths.
2022-10-18 16:47:30 -05:00
Yanming Zhou
1f38a937bd Eliminate unnecessary sessionRepository::findById 2022-10-18 16:47:30 -05:00
Rob Winch
e027d2091b Update to Spring Security 6.0.0-RC1
Closes gh-2193
2022-10-18 16:44:06 -05:00
Vedran Pavic
bcbe53c3dd Make MongoSession package private
See gh-2170
2022-10-18 14:57:23 -05:00
Vedran Pavic
72742b52e3 Make MongoSessionUtils package private
See gh-2170
2022-10-18 14:57:23 -05:00
Vedran Pavic
1889a4c64e Use standard Spring utils in MongoDB module
This commit replaces usages of custom assert utility class with standard one from Spring Framework, and removes the custom utility.

See gh-2170
2022-10-18 14:57:23 -05:00
Jerome Prinet
3000f3198f Update Gradle Enterprise plugin to 3.11.2 2022-10-18 14:32:18 -05:00
Jerome Prinet
82a12afe93 Update Gradle Enterprise plugin to 3.11.1 2022-10-18 14:32:18 -05:00
Vedran Pavic
d2da662c3f Upgrade Gradle to 7.5.1 2022-10-18 14:31:30 -05:00
Vedran Pavic
95e2c9e42a Add .gitattributes 2022-10-18 14:31:30 -05:00
Rob Winch
ff8672b1d5 Update to mongodb 4.8.0-beta0
Closes gh-2182
2022-10-17 22:48:31 -05:00
Rob Winch
31d4a766eb Update to derby 10.16.1.1
Closes gh-2183
2022-10-17 22:48:18 -05:00
Rob Winch
ce332022de Update to lettuce 6.2.1.RELEASE
Closes gh-2184
2022-10-17 22:48:05 -05:00
Rob Winch
5c2ca6d5ac Update to hazelcast 5.1.4
Closes gh-2185
2022-10-17 22:47:54 -05:00
Rob Winch
bc93d80a17 Update to Spring Data 2022.0.0-RC1
Closes gh-2186
2022-10-17 22:47:42 -05:00
Rob Winch
fd835fd316 Update to Spring Framework 6.0.0-RC2
Closes gh-2187
2022-10-17 22:47:25 -05:00
Rob Winch
4e3ea616ba Update to Mockito 4.8.1
Closes gh-2188
2022-10-17 22:47:12 -05:00
Rob Winch
08654749ae Update to JUnit 5.9.1
Closes gh-2189
2022-10-17 22:47:07 -05:00
Rob Winch
88306d037d Update to Jackson 2.13.4.20221013
Closes gh-2190
2022-10-17 22:46:52 -05:00
Rob Winch
de32e4c501 Update to Reactor 2022.0.0-RC1
Closes gh-2191
2022-10-17 22:46:42 -05:00
Vedran Pavic
668f85788a Avoid inheritance in configuration classes
This commit restructures configuration classes to avoid inheritance, where possible. This should provide more flexibility when composing custom configurations.

Closes gh-1415
2022-10-17 21:52:58 -05:00
Vedran Pavic
fc81049cbe Upgrade Logback to 1.4.4 2022-10-17 15:05:24 -05:00
Vedran Pavic
fbb94b40e8 Fix Spring Security XML config 2022-10-17 15:05:24 -05:00
Vedran Pavic
009cb5b592 Fix max inactive interval setters backwards compatibility
This commit restores integer based max inactive interval setters across all session repositories, that were migrated to java.time in 6d74cf5f.

This change caused problems building our Spring Boot based samples, as Spring Boot auto-configuration has move to session repository customizer based approach and is therefore using max inactive interval setters directly on session repository implementations.
2022-10-07 07:56:25 -05:00
Vedran Pavic
525b841ad6 Build against Project Reactor 2022.0.0-RC1 snapshots 2022-10-06 21:52:31 -05:00
Vedran Pavic
185ea87ff4 Build against Spring Security 6.0.0-RC1 snapshots 2022-10-06 21:52:31 -05:00
Vedran Pavic
aebe5ece6f Build against Spring Data 2022.0.0-RC1 snapshots 2022-10-06 21:52:31 -05:00
Vedran Pavic
30b8e68c67 Build against Spring Framework 6.0.0-RC1 snapshots 2022-10-06 21:52:31 -05:00
Vedran Pavic
c2f8428df9 Upgrade Logback to 1.4.1 2022-10-06 10:28:41 -05:00
Vedran Pavic
b5197b8665 Polish RedisIndexedSessionRepository
This commit addresses code warnings due to nullability of return values.
2022-10-06 10:28:11 -05:00
Vedran Pavic
2406ec8302 Fix SessionCreatedEvent handling in RedisIndexedSessionRepository
At present, RedisIndexedSessionRepository publishes a SessionCreatedEvent backed by an empty MapSession instance. This happens because session delta has been cleared before publishing a message to the session created channel.

Fixes gh-1338
2022-10-06 10:28:11 -05:00
Vedran Pavic
6d74cf5f35 Use java.time in all session repositories and configurations
This commit reworks all session repository implementations and their respective configurations to use java.time for managing maxInactiveInterval and other temporal values.
2022-10-06 10:26:50 -05:00
Vedran Pavic
da8e5fbbac Ensure configuration classes can be used with @Import
This commit adds tests that verify that all Spring Session configuration classes can be used with @Import, and fixes JDBC and Hazelcast HttpSession configurations and Redis WebSession configuration.
2022-09-26 09:01:09 -05:00
Vedran Pavic
4b34f35b82 Replace JSR-250 annotations with standard Spring lifecycle callbacks 2022-09-26 08:59:06 -05:00
Vedran Pavic
954a40f5d1 Simplify expired session cleanup jobs
At present, RedisIndexedHttpSessionConfiguration and JdbcHttpSessionConfiguration include [at]EnableScheduling annotated inner configuration classes that configure expired session cleanup jobs. This approach silently opts in users into general purpose task scheduling support provided by Spring Framework, which isn't something a library should do. Ideally, session cleanup jobs should only require a single thread dedicated to their execution and also one that doesn't compete for resources with general purpose task scheduling.

This commit updates RedisIndexedSessionRepository and JdbcIndexedSessionRepository to have them manage their own ThreadPoolTaskScheduler for purposes of running expired session cleanup jobs.

Closes gh-2136
2022-09-23 15:23:29 -05:00
Vedran Pavic
fb66cf3150 Remove @Configuration meta-annotation from @Enable*Session annotations
Closes gh-1361
2022-09-22 16:13:16 -05:00
Vedran Pavic
a23090e7e5 Fix "Find by Username" sample
Spring Boot's auto-configuration support for Spring Session now uses RedisSessionRepository as the default Redis session repository, so applications that rely on indexed session repository need to opt into the previous default. One such example is our "Find by Username" sample.

This commit fixes "Find by Username" sample by opting into the indexed repository type using newly introduced spring.session.redis.repository-type property.
2022-09-22 14:33:52 -05:00
Rob Winch
beaca53d44 Fix major/minor segments 2022-09-21 14:47:06 -05:00
Marcus Da Coregio
baed403a6a Polish SessionJdbcRuntimeHints
Issue gh-2103
2022-09-21 09:12:24 -03:00
Rob Winch
cd51c36dc0 Next Development Version 2022-09-20 14:59:00 -05:00
Rob Winch
7144e626cc Release 3.0.0-M4 2022-09-20 14:57:53 -05:00
Rob Winch
0e0d0007e6 Next Development Version 2022-09-20 14:52:18 -05:00
Rob Winch
573424f2a1 Release 3.0.0-M3 2022-09-20 14:43:52 -05:00
Rob Winch
8e6e9dec53 Allow snapshot repository for samples
When a release is published Spring Boot has not been released, so
it can be beneficial to allow the samples to use the snapshot
repository. This is determined based on the springBootVersion property.
2022-09-20 14:42:49 -05:00
Rob Winch
8216be69cc Upgrade to org.postgresql:postgresql:42.5.0
Closes gh-2161
2022-09-20 14:02:52 -05:00
Rob Winch
0e1914b380 Update to org.mongodb 4.7.1
Closes gh-2162
2022-09-20 14:02:06 -05:00
Rob Winch
ec32a825d9 Upgrade to org.mariadb.jdbc:mariadb-java-client:3.0.7
Closes gh-2159
2022-09-20 14:00:45 -05:00
Rob Winch
8319435f7c Upgrade to org.hsqldb:hsqldb:2.7.0
Closes gh-2158
2022-09-20 13:59:59 -05:00
Rob Winch
45448c3075 Upgrade to org.assertj:assertj-core:3.23.1
Closes gh-2157
2022-09-20 13:59:12 -05:00
Rob Winch
efd18a9fe9 Upgrade to mysql:mysql-connector-java:8.0.30
Closes gh-156
2022-09-20 13:58:40 -05:00
Rob Winch
8cf71b27f9 Update to Upgrade to io.lettuce:lettuce-core:6.2.0.RELEASE
Closes gh-2155
2022-09-20 13:57:56 -05:00
Rob Winch
0ea5ed709d Upgrade to com.oracle.database.jdbc:ojdbc8:21.7.0.0
Closes gh-2153
2022-09-20 13:57:05 -05:00
Rob Winch
a57774bff6 Upgrade to com.microsoft.sqlserver:mssql-jdbc:11.2.1.jre17
Closes gh-2152
2022-09-20 13:55:06 -05:00
Rob Winch
106848fcf7 Upgrade to com.ibm.db2:jcc:11.5.7.0
Closes gh-2151
2022-09-20 13:54:09 -05:00
Rob Winch
a1b87ce1e9 Upgrade to com.h2database:h2:2.1.214
Close gh-2150
2022-09-20 13:53:33 -05:00
Rob Winch
cb75ee603d Upgrade to ch.qos.logback:logback-core:1.2.11
Closes gh-2149
2022-09-20 13:52:57 -05:00
Rob Winch
2eb10a6e58 Upgrade to org.aspectj:aspectjweaver:1.9.9.1
Closes gh-2148
2022-09-20 13:52:21 -05:00
Rob Winch
5bdf5ed780 Upgrade to com.hazelcast:hazelcast:5.1.3
Closes gh-2147
2022-09-20 13:47:14 -05:00
Rob Winch
1ccd1a1eea Upgrade to org.mockito:mockito-bom:4.8.0
Closes gh-2146
2022-09-20 13:46:49 -05:00
Rob Winch
27e90b2e59 Update to spring-security-bom:6.0.0-M7
Closes gh-2145
2022-09-20 13:36:33 -05:00
Rob Winch
b8d660712e Update to spring-data-bom:2022.0.0-M4
Closes gh-2144
2022-09-20 13:35:17 -05:00
Rob Winch
f65f84a129 Update to spring-framework-bom:6.0.0-M6
Closes gh-2143
2022-09-20 13:33:49 -05:00
Rob Winch
0a0e34e248 Update to junit-bom:5.9.0
Closes gh-2142
2022-09-20 13:32:35 -05:00
Rob Winch
bb8b9444e6 Update to jackson-bom:2.13.4
Closes gh-2141
2022-09-20 13:30:19 -05:00
Rob Winch
da1fc676ae Update to reactor-bom:2022.0.0-M6
Closes gh-2140
2022-09-20 13:29:14 -05:00
Vedran Pavic
cb6f5c9588 Align dependency versions in samples
This commit aligns dependency versions used across different samples application by leveraging Spring Boot's BOM, rather than manually managing dependency versions for samples that are not Spring Boot based.
2022-09-20 10:58:05 -05:00
Vedran Pavic
4e311939c2 Use Spring Security auto-configuration in MongoDB samples 2022-09-20 10:58:05 -05:00
Vedran Pavic
e050a92fad Restructure Redis HttpSession configuration support
This commit restructures configuration support for Redis-backed
HttpSession with aim to enable users to easily select the
SessionRepository implementation they prefer to use.

This is achieved by introducing [at]EnableRedisIndexedHttpSession
annotation that can be used to configure RedisIndexedSessionRepository,
while the existing [at]EnableRedisHttpSession will going forward
configure RedisSessionRepository as the SessionRepository implementation
used by Spring Session.

Additionally, this also introduces AbstractRedisHttpSessionConfiguration
as the base configuration class that manages common aspects of
Redis-backed HttpSession support, which is then extended by more
specific configuration classes that provide specific SessionRepository
implementation.

Closes gh-2122
2022-09-07 09:46:55 -05:00
Vedran Pavic
0c1dbc7355 Revert "Use simple Redis repository by default"
This reverts commit 8582b970

See gh-2122
2022-09-07 09:46:55 -05:00
Vedran Pavic
8e8de48614 Fix deprecation warnings 2022-09-06 15:27:53 -05:00
Rob Winch
8c49d5993f Fix antora-playbook.yml
When 3.0.x was renamed to main the antora playbook should have been copied
from 2.7.x to 3.0.x.

Closes gh-2135
2022-08-30 23:04:34 -05:00
Rob Winch
d257f1779e Improve Tags/Branches Antora Processes 2022-08-30 22:58:44 -05:00
Rob Winch
a81918116d Update to Antora 3.1.0 2022-08-30 22:58:02 -05:00
Vedran Pavic
9524730ab1 Update integration tests
This commit updates Docker images used in all the integration tests. Additionally, it updates JDBC session repository Oracle integration tests to run unconditionally.
2022-08-30 21:48:39 -05:00
Vedran Pavic
7856113608 Remove unused test sources in docs
This commit removes test sources that are already present in modules/ROOT/examples path of spring-session-docs module.
2022-08-30 21:46:05 -05:00
Vedran Pavic
820c055e7e Update .gitignore
This commit updates .gitignore to include NPM files created by Antora tasks of spring-session-docs module.
2022-08-30 21:46:05 -05:00
Vedran Pavic
2817d309ac Configure nohttp to ignore docs build output
At present, project build fails with checkstyleNohttp task error if not cleaned beforehand.

This commit updates nohttp configuration so that it ignores build output of examples in spring-session-docs module.

Closes gh-2127
2022-08-30 21:46:05 -05:00
Vedran Pavic
2191c6f296 Use text blocks for SQL statements
With Java 17 now being the baseline, strings containing SQL statements
can be managed more conveniently using text blocks.
2022-08-30 21:44:38 -05:00
Vedran Pavic
87bb3df543 Upgrade Spring JavaFormat to 0.0.34 2022-08-30 21:44:38 -05:00
Vedran Pavic
38a87e093a Disable Hazelcast network join auto-detection in tests
At present, Hazelcast configurations used in tests disable multicast join but leave network join auto-detection enabled. This can cause issues with parallel test execution on machines that have bigger number of CPU cores/threads.

This commit updates Hazelcast configurations used in tests to disable network join auto-detection and thus ensure no network join method ends up being enabled.
2022-08-19 13:33:21 -05:00
Vedran Pavic
75ab31d459 Remove deprecated code in spring-session-data-mongodb 2022-08-19 13:31:44 -05:00
Vedran Pavic
9041ffb29e Remove deprecated code in spring-session-hazelcast 2022-08-19 13:31:44 -05:00
Vedran Pavic
b20b08e020 Remove deprecated code in spring-session-jdbc 2022-08-19 13:31:44 -05:00
Vedran Pavic
de57f2cd14 Remove deprecated code in spring-session-data-redis 2022-08-19 13:31:44 -05:00
Vedran Pavic
b85ec4de1a Fix Spring Security configuration in tests
As of spring-projects/spring-security#11653, Spring Security's [at]Enable*Security annotations are not meta annotated with [at]Configuration which breaks some of our tests.

This commit adds missing [at]Configuration annotations where needed.

Closes gh-2118
2022-08-19 11:20:04 -05:00
Marcus Da Coregio
812ac239c0 Fix Session Security Runtime Hints always being registered
Splits the Security and Common Session hints in two different classes and only register security hints if SecurityContextImpl is present

Issue gh-2104
2022-08-05 10:59:50 -03:00
Marcus Da Coregio
cc4a15db79 Use SQLErrorCodeSQLExceptionTranslator in JdbcTemplate
Closes gh-2108
2022-07-20 09:13:30 -03:00
Marcus Da Coregio
65b994cad1 Polish RuntimeHintsRegistrar
Add RuntimeHints suffix to classes
Make classes package-private
Use ReflectionUtilsPredicates#serialization

Closes gh-2111
Closes gh-2112
2022-07-18 09:06:57 -03:00
Marcus Da Coregio
374ea4a432 Upgrade com.hazelcast:hazelcast to 5.0.3
Closes gh-2110
2022-07-18 09:06:35 -03:00
Marcus Da Coregio
abce2eb555 Add native-image support for Core classes
Closes gh-2104
2022-07-08 11:20:54 -03:00
Marcus Da Coregio
dc2e93f198 Add native-image support for Session JDBC
Closes gh-2103
2022-07-08 11:08:33 -03:00
Marcus Da Coregio
00d248b0b5 Fix failing tests
Issue gh-2107
2022-07-08 11:07:02 -03:00
Marcus Da Coregio
13b0e5cc8a Use Spring Security 6 SNAPSHOTs
Closes gh-2106
2022-07-08 08:45:28 -03:00
Marcus Da Coregio
dd0edeaef8 Use Spring Framework 6 SNAPSHOTs
Closes gh-2105
2022-07-08 08:45:15 -03:00
Rob Winch
7fac9efc89 Next Developement Version 2022-05-18 14:58:54 -05:00
Rob Winch
8553b52431 Release 3.0.0-M3 2022-05-18 14:54:53 -05:00
Rob Winch
69d8fda4cc Update spring-data-bom:2022.0.0-M4 2022-05-18 14:41:48 -05:00
Rob Winch
a9f7a35ef3 Revert "Temporarily Disable Samples"
This reverts commit 2effbd19ab.
2022-05-18 14:41:02 -05:00
Rob Winch
679b6e57df Next Development Version 2022-05-18 13:09:22 -05:00
Rob Winch
1bc21d5187 Release 3.0.0-M2 2022-05-18 13:08:46 -05:00
Rob Winch
2effbd19ab Temporarily Disable Samples 2022-05-18 13:00:33 -05:00
Rob Winch
31275574ee Update to spring-security-bom:6.0.0-M5
Closes gh-2093
2022-05-18 12:04:25 -05:00
Rob Winch
e4201aea05 Update to spring-data-bom:2022.0.0-M3
Closes gh-9092
2022-05-18 12:04:25 -05:00
Rob Winch
3c134778d8 Update to spring-framework-bom:6.0.0-M4
Closes gh-2091
2022-05-18 12:04:25 -05:00
Rob Winch
bc51d842dc Update to jackson-bom:2.13.3
Clsoes gh-2090
2022-05-18 12:04:25 -05:00
Rob Winch
17610e7cc2 Update to reactor-bom:2020.0.19
Closes gh-2089
2022-05-18 12:04:15 -05:00
Rob Winch
58813e9d5a Next Development Version 2022-05-18 11:06:59 -05:00
Rob Winch
c66ee750f9 Release 2.7.0 2022-05-18 11:02:54 -05:00
Rob Winch
9062db3f55 Update to spring-security-bom:5.7.0
Closes gh-2084
2022-05-18 09:29:51 -05:00
Rob Winch
4bf15cda3b Update to spring-data-bom:2021.2.0
Closes gh-2085
2022-05-18 09:29:51 -05:00
Rob Winch
7f8c0387a7 Update to spring-framework-bom:5.3.20
Closes gh-2086
2022-05-18 09:29:51 -05:00
Rob Winch
3bc15c4259 Update to reactor-bom:2020.0.19
Closes gh-2087
2022-05-18 09:29:50 -05:00
Rob Winch
c9add24c77 Add .sdkmanrc
Closes gh-2088
2022-05-18 09:29:44 -05:00
Rob Winch
3ce78f6cd0 Fix formatting 2022-05-13 17:49:29 -05:00
Rob Winch
21b0f60721 Add .sdkmanrc 2022-05-13 17:41:34 -05:00
Rob Winch
0dcdf5f147 Fix Thymeleaf Samples
Thymeleaf removed support for accessing the HttpServletRequest and HttpSession
automatically, so we need to add any properties we want to access as ModelAttributes

Closes gh-2076
2022-05-13 17:37:33 -05:00
Rob Winch
a0bf6a0e62 Restore all Samples 2022-05-13 17:36:52 -05:00
Rob Winch
d23b81f300 Fix spring-session-sample-boot-mongodb-traditional 2022-05-13 17:36:52 -05:00
Rob Winch
f33c5fe19a Fix spring-session-sample-boot-websocket 2022-05-13 17:36:52 -05:00
Rob Winch
e1c4b25671 Fix spring-session-sample-boot-hazelcast 2022-05-13 17:36:52 -05:00
Rob Winch
9bf18059d2 Fix xpring-session-sample-boot-jdbc 2022-05-13 17:36:52 -05:00
Rob Winch
342198cdfb Fix spring-session-sample-boot-redis-json 2022-05-13 17:36:52 -05:00
Rob Winch
c151a97227 Fix spring-session-sample-boot-findbyusername 2022-05-13 17:36:52 -05:00
Rob Winch
0cb6e0ebc9 Fix spring-session-sample-boot-redis-simple 2022-05-13 17:36:52 -05:00
Rob Winch
b4c3cefcf4 fix spring-session-sample-boot-redis 2022-05-13 17:36:52 -05:00
Rob Winch
2a6a9cfb78 Fix Formatting 2022-05-13 17:36:23 -05:00
Greg L. Turnquist
55f9bc9c37 Replace Flapdoodle with Testcontainers for MongoDB support.
For more details on this usage of Testcontainers, see https://bsideup.github.io/posts/local_development_with_testcontainers/

Related issues: https://github.com/spring-projects/spring-boot/issues/30863
2022-05-13 17:34:43 -05:00
Eleftheria Stein
c9cf1eab7b Update Htmlunit test dependency 2022-05-13 13:13:32 -05:00
Eleftheria Stein
003335df73 Update LocalServerPort import to new package 2022-05-13 13:12:38 -05:00
Eleftheria Stein
c3b8634fb4 Use Java 17 in antora pipeline 2022-04-29 11:38:12 +02:00
Eleftheria Stein
28e1ab1d8d Upgrade to Gradle 7.4.2 in buildSrc
Issue gh-2073
2022-04-29 10:56:02 +02:00
Eleftheria Stein
ff8750e9c1 Re-enable working samples
The Spring Boot servlet samples remain disalbed because of gh-2076.
2022-04-29 10:33:32 +02:00
Eleftheria Stein
e51dd2d1b0 Upgrade test dependencies 2022-04-29 10:28:34 +02:00
Eleftheria Stein
a6f24bc27e Upgrade MongoDB to 4.6.0
Closes gh-2075
2022-04-29 10:28:01 +02:00
Eleftheria Stein
42580c3a44 Upgrade samples to Spring Boot 3.0.0-SNAPSHOT #
Closes gh-2074
2022-04-29 10:25:48 +02:00
Eleftheria Stein
ea0aef9d97 Upgrade to Gradle 7.4.2
Closes gh-2073
2022-04-29 10:21:39 +02:00
Eleftheria Stein
0d458a4a5b Update Redis docs
Issue gh-1711
2022-04-29 09:03:57 +02:00
Eleftheria Stein
102027a456 Add Caffeine community extension
Closes gh-2039
2022-04-27 09:53:55 +02:00
Eleftheria Stein
e580a97c0c Fix link to Infinispan cache 2022-04-27 09:53:55 +02:00
Eleftheria Stein
7227949afb Fix formatting 2022-04-27 09:53:55 +02:00
Greg L. Turnquist
34d59a0ed9 Switch back to unicode for the DOT substitute character.
MongoDB doesn't support "." in field names, so a Private Use Area character was used. This was originally stored in unicode format, but delomboking the code caused it to get transformed into another encoding. This causes issues on certain systems when building the software, so we are converting it back to its unicode representation. The character has been the same throughout, ensuring binary compatilibity.

See: https://www.compart.com/en/unicode/U+F607

Related: d601e270fc (diff-57190a47726099e31fdf86b12b80206e2ae24feb28aacaf494b99557583df150L47)
Closes #2053.
2022-04-27 09:53:55 +02:00
Eleftheria Stein
aaed973d27 Add Caffeine community extension
Closes gh-2039
2022-04-27 09:50:11 +02:00
Eleftheria Stein
55c4fcfd3f Fix link to Infinispan cache 2022-04-27 09:49:41 +02:00
Eleftheria Stein
2a5d6b4d2e Next development version 2022-04-19 18:39:03 +02:00
Eleftheria Stein
42aa10bfe8 Release 2.7.0-RC1 2022-04-19 18:20:16 +02:00
Eleftheria Stein
2ce570cbdc Next development version 2022-04-19 18:06:26 +02:00
Eleftheria Stein
221b48094a Upgrade test dependencies 2022-04-19 17:59:17 +02:00
Eleftheria Stein
d43b48bbb0 Revert "Upgrade test dependencies"
This reverts commit 2369b2cfb3.
2022-04-19 17:57:52 +02:00
Eleftheria Stein
840907993b Release 2.6.3 2022-04-19 17:37:41 +02:00
Eleftheria Stein
e1dea5e0a8 Revise Redis test mocks based on new Data implementation
Issue gh-2070
2022-04-19 15:53:23 +02:00
Eleftheria Stein
4db41c1caf Upgrade Spring Data to 2021.1.4
Closes gh-2058
2022-04-19 15:41:20 +02:00
Eleftheria Stein
23a32acd56 Upgrade Spring Data to 2021.2.0-RC1
Closes gh-2059
2022-04-19 15:18:55 +02:00
Eleftheria Stein
dc8cca5351 Upgrade Spring Security to 5.7.0-RC1
Closes gh-2070
2022-04-19 13:19:15 +02:00
Eleftheria Stein
2369b2cfb3 Upgrade test dependencies 2022-04-19 13:19:10 +02:00
Eleftheria Stein
e6ce56ec8b Upgrade Reactor to 2020.0.18
Closes gh-2071
2022-04-19 13:17:57 +02:00
Eleftheria Stein
36939c1b02 Upgrade Jackson to 2.13.2.20220328
Closes gh-2068
2022-04-19 13:17:25 +02:00
Eleftheria Stein
0a84f9d544 Upgrade Spring Framework to 5.3.19
Closes gh-2069
2022-04-19 13:15:32 +02:00
Eleftheria Stein
f4840e98a2 Upgrade test dependencies 2022-04-19 12:27:09 +02:00
Eleftheria Stein
8c99c9f904 Upgrade Spring Security to 5.6.3
Closes gh-2064
2022-04-19 12:26:40 +02:00
Eleftheria Stein
f70f1f20f9 Upgrade Reactor to 2020.0.18
Closes gh-2065
2022-04-19 12:25:20 +02:00
Eleftheria Stein
ac1a77e5fe Upgrade Jackson to 2.13.2.20220328
Closes gh-2066
2022-04-19 12:21:58 +02:00
Eleftheria Stein
214a556dd4 Upgrade Spring Framework to 5.3.19
Closes gh-2063
2022-04-19 12:21:22 +02:00
Eleftheria Stein
cace484fbe Upgrade samples to Spring Boot 2.6.6
Closes gh-2067
2022-04-19 12:20:16 +02:00
Eleftheria Stein
a5ec1ccf1f Fix formatting 2022-04-19 11:13:49 +02:00
Greg L. Turnquist
7fc0ae47d5 Switch back to unicode for the DOT substitute character.
MongoDB doesn't support "." in field names, so a Private Use Area character was used. This was originally stored in unicode format, but delomboking the code caused it to get transformed into another encoding. This causes issues on certain systems when building the software, so we are converting it back to its unicode representation. The character has been the same throughout, ensuring binary compatilibity.

See: https://www.compart.com/en/unicode/U+F607

Related: d601e270fc (diff-57190a47726099e31fdf86b12b80206e2ae24feb28aacaf494b99557583df150L47)
Closes #2053.
2022-04-18 09:49:57 -05:00
Eleftheria Stein
8582b9706d Use simple Redis repository by default
Closes gh-1711
2022-04-14 13:17:28 +02:00
Jerome Prinet
14ecf21c94 Update Gradle Enterprise plugin to 3.9 2022-04-14 11:11:31 +02:00
Jerome Prinet
ce2e644e04 Update Gradle Enterprise plugin to 3.9 2022-04-14 11:10:54 +02:00
John Blum
6fc4097c2e Switch to Spring Security BOM 6.0.0-SNAPSHOT 2022-04-11 15:41:24 -07:00
John Blum
a1cfbcae0c Switch to Spring Data BOM 2022.0.0-SNAPSHOT 2022-04-11 15:40:50 -07:00
John Blum
004cf6656b Switch to Spring Framework BOM 6.0.0-SNAPSHOT 2022-04-11 15:39:51 -07:00
Felix Scheinost
24c198fe98 Fix bug in JDBC SaveMode.ON_GET_ATTRIBUTE 2022-04-08 17:50:51 +02:00
Felix Scheinost
cde256e1a3 Fix bug in JDBC SaveMode.ON_GET_ATTRIBUTE
Closes gh-2040
2022-04-08 17:20:46 +02:00
Felix Scheinost
8800fb9816 Fix bug in JDBC SaveMode.ON_GET_ATTRIBUTE 2022-04-08 17:19:54 +02:00
Eleftheria Stein
63f7f7b0a9 Upgrade Spring Data to 2022.0.0-M3
Closes gh-2048
2022-04-01 18:21:23 +02:00
Eleftheria Stein
b8e94948ae Upgrade MongoDB to 4.5.1
Closes gh-2047
2022-03-30 15:24:02 +02:00
Eleftheria Stein
8d2276341f Upgrade samples to Spring Boot 2.7.0-M3
This also makes the necessary changes for the Thymeleaf Layout Dialect 3.0 update.

Closes gh-2046
2022-03-30 15:23:49 +02:00
Eleftheria Stein
2c1b79375d Upgrade samples to Spring Boot 2.6.5
This also makes the necessary changes for the Thymeleaf Layout Dialect 3.0 update.

Closes gh-1980
2022-03-29 15:33:08 +02:00
Eleftheria Stein
63f1c7bf6f Fix reference documentation redirects
Closes gh-2044
2022-03-23 10:03:32 +01:00
Eleftheria Stein
140cc75583 Make RedisSessionRepository.DEFAULT_KEY_NAMESPACE public
Closes gh-2043
2022-03-15 18:34:59 +01:00
Eleftheria Stein
e8e4ee2850 Make RedisSessionRepository.DEFAULT_KEY_NAMESPACE public
Closes gh-2043
2022-03-15 18:23:17 +01:00
Eleftheria Stein
e157700087 Update to Antora 3.0.1
Closes gh-2038
2022-03-11 15:48:26 +01:00
Eleftheria Stein
1b18d64220 Fix 2.6.2 reference docs
Closes gh-2035
2022-03-11 15:48:18 +01:00
Eleftheria Stein
9a643c8866 Update to Antora 3.0.1
Closes gh-2038
2022-03-11 15:46:19 +01:00
Eleftheria Stein
14756984fd Document release process for 3.0.x
Issueh gh-2036
2022-02-24 13:02:33 +01:00
Eleftheria Stein
282f774e07 Document release process for 2.7.x
Issue gh-2036
2022-02-24 12:46:05 +01:00
Eleftheria Stein
fba9313c6b Document release process for 2.6.x
Issue gh-2036
2022-02-23 14:22:25 +01:00
Eleftheria Stein
e6ec5765b8 Fix 2.6.2 reference docs
Closes gh-2035
2022-02-22 15:43:37 +01:00
Eleftheria Stein
c2288615bf Update antora to 2.6.3 2022-02-22 14:38:24 +01:00
Eleftheria Stein
ad52fc0297 Next development version 2022-02-22 14:13:29 +01:00
Eleftheria Stein
2516a495af Release 2.6.2 2022-02-22 10:31:00 +01:00
Eleftheria Stein
9be7ac7fa6 Upgrade test dependencies 2022-02-22 10:30:29 +01:00
Eleftheria Stein
c335a49924 Upgrade Hazelcast 4 to 4.2.4
Closes gh-2029
2022-02-22 10:29:20 +01:00
Eleftheria Stein
092e6c6607 Upgrade MongoDB to 4.4.2
Closes gh-2034
2022-02-22 10:28:02 +01:00
Eleftheria Stein
0924c9558a Upgrade Reactor to 2020.0.16
Closes gh-2031
2022-02-22 10:27:20 +01:00
Eleftheria Stein
0484781541 Upgrade Jackson to 2.13.1
Closes gh-2033
2022-02-22 10:26:38 +01:00
Eleftheria Stein
3995f8bf65 Upgrade Spring Framework to 5.3.16
Closes gh-2028
2022-02-22 10:25:32 +01:00
Eleftheria Stein
ad16f17398 Upgrade Spring Data to 2021.1.2
Closes gh-2032
2022-02-22 10:24:56 +01:00
Eleftheria Stein
11aa50e83c Upgrade Spring Security to 5.6.2
Closes gh-2030
2022-02-22 10:24:32 +01:00
Eleftheria Stein
34199baded Update Websocket sample to be compatible with H2 2.0
Closes gh-2013
2022-01-27 14:12:23 +01:00
Eleftheria Stein
ab5c727846 Update Websocket sample to be compatible with H2 2.0
Closes gh-2013
2022-01-27 14:11:26 +01:00
Eleftheria Stein
a0246a61b6 Update to jakarta.servlet-api dependency
Closes gh-1960
2022-01-25 13:26:47 +01:00
Eleftheria Stein
8f20fa328a Update to jakarta.annotation-api dependency
Closes gh-1956
2022-01-25 12:50:29 +01:00
Eleftheria Stein
44ff959c59 Include 2.6.x branch in Antora docs
Issue gh-2014
2022-01-21 10:13:52 +01:00
Eleftheria Stein
ad67a3775b Add manual trigger to antora generate workflow
Issue gh-2014
2022-01-20 13:52:11 +01:00
Eleftheria Stein
75c60b27bd Exclude 3.0.0-M1 and 2.7.0-M1 tags from antora
Closes gh-2014
2022-01-20 13:22:31 +01:00
Ruslan Molchanov
12ce8de84e Fix memory leak with null principal in Redis
Closes gh-1987
2022-01-20 10:05:05 +01:00
Ruslan Molchanov
cc5bb1f3a2 Fix memory leak with null principal in Redis 2022-01-20 09:52:44 +01:00
Ruslan Molchanov
81bd6bd261 Fix memory leak with null principal in Redis
Closes gh-1987
2022-01-19 17:31:35 +01:00
Eleftheria Stein
2e8c4292fd Next development version 2022-01-18 13:01:30 +01:00
Eleftheria Stein
315b9c9929 Release 2.7.0-M1 2022-01-18 12:51:40 +01:00
Eleftheria Stein
48cf6849fe Next development version 2022-01-18 12:30:47 +01:00
Eleftheria Stein
a70abd90bd Upgrade test dependencies 2022-01-18 11:29:58 +01:00
Eleftheria Stein
f13df5aa2f Revert "Upgrade test dependencies"
This reverts commit bda72c074f.
2022-01-18 11:14:02 +01:00
Eleftheria Stein
6fd68e093f Upgrade Spring Data to 2021.2.0-M2
Closes gh-1996
2022-01-18 10:47:16 +01:00
Eleftheria Stein
653d820290 Update antora tags to include 3.0 2022-01-18 10:35:06 +01:00
Jerome Prinet
950ac50234 Bump up Gradle plugin dependencies 2022-01-17 17:05:36 +01:00
Eleftheria Stein
bda72c074f Upgrade test dependencies 2022-01-17 14:51:48 +01:00
Eleftheria Stein
fb1362aa2c Upgrade Hazelcast 4 to 4.2.4
Closes gh-2001
2022-01-17 14:51:48 +01:00
Eleftheria Stein
d5dac6629d Upgrade Spring Security to 5.7.0-M1
Closes gh-1997
2022-01-17 14:51:45 +01:00
Eleftheria Stein
04b4b9ba17 Upgrade Spring Framework to 5.3.15
Closes gh-1998
2022-01-17 14:51:18 +01:00
Eleftheria Stein
97308bdbf4 Upgrade Jackson to 2.13.1
Closes gh-2002
2022-01-17 14:50:38 +01:00
Eleftheria Stein
4ba62c71dd Upgrade MongoDB to 4.4.1
Closes gh-2000
2022-01-17 14:50:38 +01:00
Eleftheria Stein
265099c586 Upgrade Reactor to 2020.0.15
Closes gh-1999
2022-01-17 09:41:09 +01:00
Eleftheria Stein
2f4a0110ab Update to jakarta.servlet-api dependency
Closes gh-1960
2022-01-14 16:21:35 +01:00
Eleftheria Stein
7a1cb66dae Update to jakarta.annotation-api dependency
Closes gh-1956
2022-01-14 16:19:22 +01:00
Jerome Prinet
9bad2afa14 Bump up Gradle enterprise plugin to 3.7.2 2022-01-05 14:34:51 +01:00
Eleftheria Stein
dba22292a3 Run CI on all branches 2022-01-05 14:29:57 +02:00
Eleftheria Stein
c79173879f Run CI on all branches 2022-01-05 14:29:28 +02:00
Eleftheria Stein
2c065c0241 Next minor development version 2022-01-05 14:28:19 +02:00
Eleftheria Stein
a08c721118 Next development version 2021-12-21 16:31:16 +02:00
Eleftheria Stein
70e0c6d22d Update antora version 2021-12-21 15:44:58 +02:00
Eleftheria Stein
61bf2eca49 Release 2.6.1 2021-12-21 15:12:26 +02:00
Eleftheria Stein
59923121f0 Make gretty samples compatible with logback 1.2.9
Explicitly reference the logback.xml file to prevent gretty from configuring the defaults using groovy.
2021-12-21 11:10:33 +02:00
Eleftheria Stein
b5f8e29585 Upgrade test dependencies 2021-12-21 11:10:22 +02:00
Eleftheria Stein
307a1f0dde Upgrade Hazelcast 4 to 4.2.3
Closes gh-1979
2021-12-21 10:09:06 +02:00
Eleftheria Stein
ced2d8421c Upgrade Spring Security to 5.6.1
Closes gh-1978
2021-12-21 10:08:25 +02:00
Eleftheria Stein
d98ff97e1a Upgrade Spring Framework to 5.3.14
Closes gh-1977
2021-12-21 10:03:02 +02:00
Eleftheria Stein
757175516f Upgrade Reactor to 2020.0.14
Closes gh-1976
2021-12-21 10:02:30 +02:00
Eleftheria Stein
8ae55b7ee4 GitHub Actions uses spring-builds+github user
This is more clear than spring-builds user
2021-12-07 15:43:42 +01:00
Eleftheria Stein
1eb53ead9d Update README to include MongoDB
Issue gh-1901
2021-11-26 17:37:12 +01:00
Guillaume Husta
72159794f4 Doc : typo on Username _user-
user should be in italic
2021-11-19 14:56:56 +01:00
Eleftheria Stein
aaf122f3a6 Include 2.6.0 and 3.0 snapshots in reference docs 2021-11-17 11:28:54 +01:00
Eleftheria Stein
6f823805f2 Include 2.6.8 release in docs 2021-11-17 11:04:55 +01:00
Eleftheria Stein
7807aa9f3c Next development version 2021-11-16 18:56:49 +01:00
Eleftheria Stein
76924bc923 Release 2.6.0 2021-11-16 14:21:51 +01:00
Eleftheria Stein
134f89dd41 Upgrade test dependencies 2021-11-16 13:57:45 +01:00
Eleftheria Stein
33812f7197 Upgrade MongoDB to 4.4.0
Closes gh-1967
2021-11-16 13:56:44 +01:00
Eleftheria Stein
bcf17ba3b7 Upgrade samples to Spring Boot 2.5.6
Closes gh-1966
2021-11-16 13:37:41 +01:00
Eleftheria Stein
98f656ad46 Upgrade Jackson to 2.13.0
Closes gh-1965
2021-11-16 13:11:51 +01:00
Eleftheria Stein
7832942752 Upgrade Spring Security to 5.6.0
Closes gh-1964
2021-11-16 13:07:43 +01:00
Eleftheria Stein
722069a5f8 Upgrade Spring Data to 2021.1.0
Closes gh-1963
2021-11-16 13:06:41 +01:00
Eleftheria Stein
addbdbc1a2 Upgrade Spring Framework to 5.3.13
Closes gh-1962
2021-11-16 13:05:51 +01:00
Eleftheria Stein
004466ed07 Upgrade Reactor to 2020.0.13
Closes gh-1961
2021-11-16 13:04:32 +01:00
Eleftheria Stein
aeb5bc545c Update to Gradle 7.3
Closes gh-1959
2021-11-15 09:59:22 +01:00
317 changed files with 4967 additions and 5385 deletions

6
.gitattributes vendored Normal file
View File

@@ -0,0 +1,6 @@
* text eol=lf
*.bat text eol=crlf
*.jar binary
*.jpg binary
*.png binary
*.mmdb binary

View File

@@ -1,20 +0,0 @@
{
"index_name": "session-docs",
"start_urls": [
"https://docs.spring.io/spring-session/reference/"
],
"selectors": {
"lvl0": {
"selector": "//nav[@class='crumbs']//li[@class='crumb'][last()-1]",
"type": "xpath",
"global": true,
"default_value": "Home"
},
"lvl1": ".doc h1",
"lvl2": ".doc h2",
"lvl3": ".doc h3",
"lvl4": ".doc h4",
"text": ".doc p, .doc td.content, .doc th.tableblock"
}
}

View File

@@ -1,20 +0,0 @@
#!/bin/bash
HOST="$1"
HOST_PATH="$2"
SSH_PRIVATE_KEY="$3"
SSH_KNOWN_HOST="$4"
if [ "$#" -ne 4 ]; then
echo -e "not enough arguments USAGE:\n\n$0 \$HOST \$HOST_PATH \$SSH_PRIVATE_KEY \$SSH_KNOWN_HOSTS \n\n" >&2
exit 1
fi
# Use a non-default path to avoid overriding when testing locally
SSH_PRIVATE_KEY_PATH=~/.ssh/github-actions-docs
install -m 600 -D /dev/null "$SSH_PRIVATE_KEY_PATH"
echo "$SSH_PRIVATE_KEY" > "$SSH_PRIVATE_KEY_PATH"
echo "$SSH_KNOWN_HOST" > ~/.ssh/known_hosts
rsync --delete -avze "ssh -i $SSH_PRIVATE_KEY_PATH" spring-session-docs/build/site/ "$HOST:$HOST_PATH"
rm -f "$SSH_PRIVATE_KEY_PATH"

View File

@@ -1,21 +0,0 @@
#!/bin/bash
###
# Docs
# config.json https://docsearch.algolia.com/docs/config-file
# Run the crawler https://docsearch.algolia.com/docs/run-your-own/#run-the-crawl-from-the-docker-image
### USAGE
if [ "$#" -ne 3 ]; then
echo -e "not enough arguments USAGE:\n\n$0 \$ALGOLIA_APPLICATION_ID \$ALGOLIA_API_KEY \$CONFIG_FILE\n\n" >&2
exit 1
fi
# Script Parameters
APPLICATION_ID=$1
API_KEY=$2
CONFIG_FILE=$3
#### Script
script_dir=$(dirname $0)
docker run -e "APPLICATION_ID=$APPLICATION_ID" -e "API_KEY=$API_KEY" -e "CONFIG=$(cat $CONFIG_FILE | jq -r tostring)" algolia/docsearch-scraper

View File

@@ -1,5 +0,0 @@
REPOSITORY_REF="$1"
TOKEN="$2"
curl -H "Accept: application/vnd.github.everest-preview+json" -H "Authorization: token ${TOKEN}" --request POST --data '{"event_type": "request-build-reference"}' https://api.github.com/repos/${REPOSITORY_REF}/dispatches
echo "Requested Build for $REPOSITORY_REF"

View File

@@ -1,16 +0,0 @@
name: Update Algolia Index
on:
schedule:
- cron: '0 10 * * *' # Once per day at 10am UTC
workflow_dispatch: # Manual trigger
jobs:
update:
name: Update Algolia Index
runs-on: ubuntu-latest
steps:
- name: Checkout Source
uses: actions/checkout@v2
- name: Update Index
run: ${GITHUB_WORKSPACE}/.github/actions/algolia-docsearch-scraper.sh "${{ secrets.ALGOLIA_APPLICATION_ID }}" "${{ secrets.ALGOLIA_WRITE_API_KEY }}" "${GITHUB_WORKSPACE}/.github/actions/algolia-config.json"

View File

@@ -1,30 +0,0 @@
name: Generate Antora Files and Request Build
on:
push:
branches-ignore:
- 'gh-pages'
env:
GH_ACTIONS_REPO_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Source
uses: actions/checkout@v2
- name: Generate antora.yml
run: ./gradlew :spring-session-docs:generateAntora
- name: Extract Branch Name
id: extract_branch_name
run: echo "##[set-output name=generated_branch_name;]$(echo ${GITHUB_REPOSITORY}/${GITHUB_REF##*/})"
- name: Push generated antora files to the spring-generated-docs
uses: JamesIves/github-pages-deploy-action@4.1.4
with:
branch: ${{ steps.extract_branch_name.outputs.generated_branch_name }} # The branch the action should deploy to.
folder: "spring-session-docs/build/generateAntora" # The folder the action should deploy.
repository-name: "spring-io/spring-generated-docs"
token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
- name: Dispatch Build Request
run: ${GITHUB_WORKSPACE}/.github/actions/dispatch.sh 'spring-projects/spring-session' "$GH_ACTIONS_REPO_TOKEN"

30
.github/workflows/deploy-docs.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: Deploy Docs
on:
push:
branches-ignore: [ gh-pages ]
tags: '**'
repository_dispatch:
types: request-build-reference # legacy
workflow_dispatch:
permissions: read-all
jobs:
build:
runs-on: ubuntu-latest
if: github.repository_owner == 'spring-projects'
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: docs-build
fetch-depth: 1
- name: Dispatch (partial build)
if: github.ref_type == 'branch'
env:
GH_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) -f build-refname=${{ github.ref_name }}
- name: Dispatch (full build)
if: github.ref_type == 'tag'
env:
GH_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD)

View File

@@ -1,33 +0,0 @@
name: Build & Deploy Reference
on:
repository_dispatch:
types: request-build-reference
schedule:
- cron: '0 10 * * *' # Once per day at 10am UTC
workflow_dispatch: # Manual trigger
jobs:
deploy:
name: deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'adopt'
cache: gradle
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
- name: Build with Gradle
run: ./gradlew :spring-session-docs:antora --stacktrace
- name: Cleanup Gradle Cache
# Remove some files from the Gradle cache, so they aren't cached by GitHub Actions.
# Restoring these files from a GitHub Actions cache might cause problems for future builds.
run: |
rm -f ~/.gradle/caches/modules-2/modules-2.lock
rm -f ~/.gradle/caches/modules-2/gc.properties
- name: Deploy
run: ${GITHUB_WORKSPACE}/.github/actions/algolia-deploy.sh "${{ secrets.DOCS_USERNAME }}@${{ secrets.DOCS_HOST }}" "/opt/www/domains/spring.io/docs/htdocs/spring-session/reference/" "${{ secrets.DOCS_SSH_KEY }}" "${{ secrets.DOCS_SSH_HOST_KEY }}"

View File

@@ -0,0 +1,20 @@
name: Rebuild Search Index
on:
schedule:
- cron: '0 10 * * *' # Once per day at 10am UTC
workflow_dispatch:
permissions: read-all
jobs:
build:
if: github.repository_owner == 'spring-projects'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: docs-build
fetch-depth: 1
- name: Dispatch
env:
GH_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
run: gh workflow run rebuild-search-index.yml -r $(git rev-parse --abbrev-ref HEAD)

2
.gitignore vendored
View File

@@ -14,3 +14,5 @@ out
!etc/eclipse/.checkstyle
!**/src/**/build
.DS_Store
spring-session-docs/package-lock.json
spring-session-docs/node_modules/

6
.sdkmanrc Normal file
View File

@@ -0,0 +1,6 @@
# Use sdkman to run "sdk env" to initialize with correct JDK version
# Enable auto-env through the sdkman_auto_env config
# See https://sdkman.io/usage#config
# A summary is to add the following to ~/.sdkman/etc/config
# sdkman_auto_env=true
java=17.0.2-tem

View File

@@ -25,6 +25,13 @@ If you are reporting a bug, please help to speed up problem diagnosis by providi
information as possible. Ideally, that would include a small sample project that
reproduces the problem.
== Create your branch from the oldest maintenance branch
Create your topic branch to be submitted as a pull request from the oldest impacted and supported maintenance branch.
You can find the supported versions by looking at the https://github.com/spring-projects/spring-session/milestones[milestones page].
Switch to a branch named `<major>.<minor>.x` from the smallest milestone in the format of `<major>.<minor>.<patch>(-<prerelease>)`.
The spring team will ensure the code gets merged forward into additional branches.
== Sign the Contributor License Agreement
If you have not previously done so, please fill out and

View File

@@ -63,7 +63,7 @@ Compile and test; build all jars, distribution zips, and docs
You can find the documentation, samples, and guides for using Spring Session on the https://projects.spring.io/spring-session/[Spring Session project site].
For more in depth information, visit the https://docs.spring.io/spring-session/docs/current/reference/html5/[Spring Session Reference].
For more in depth information, visit the https://docs.spring.io/spring-session/reference/[Spring Session Reference].
== Code of Conduct

110
RELEASE.adoc Normal file
View File

@@ -0,0 +1,110 @@
== 1. Update Dependencies
Dependencies are declared in `gradle/dependency-management.gradle`.
Update Spring Framework, Spring Security and Spring Data at a minimum.
Run all the checks:
[source,bash]
----
$ ./gradlew check
----
Create separate issues for each dependency update, aside from test dependencies which can be combined into a single commit.
== 2. Check All Issues are Closed
You can manually check at https://github.com/spring-projects/spring-session/milestones
== 3. Update Release Version
Update the version number in `gradle.properties` for the release, for example `3.0.0-M1`, `3.0.0-RC1`, `3.0.4`
== 4. Update Antora Version
You will need to update the antora.yml version.
For milestone / release candidate releases you should follow this format:
----
version: '3.0.0-RC1'
prerelease: 'true'
display_version: '3.0.0-RC1'
----
== 5. Build Locally
Run the build using
[source,bash]
----
$ ./gradlew check
----
== 6. Push the Release Commit
Push the commit and GitHub actions will build and deploy the artifacts.
Wait for the artifact to appear in https://repo1.maven.org/maven2/org/springframework/session/spring-session-core/
== 7. Tag the release
Tag the release and then push the tag
....
git tag 3.0.0-RC1
git push origin 3.0.0-RC1
....
== 8. Update to Next Development Version
Update `gradle.properties` version to next `+SNAPSHOT+` version, update antora.yml and then push
== 9. Update version on project pages
Update the versions on https://spring.io/projects for Spring Session Core, Spring Session Data Redis, Spring Session JDBC, Spring Session Hazelcast, and Spring Session MongoDB.
== 10. Update Release Notes on GitHub
Download
https://github.com/spring-io/github-changelog-generator/releases/latest[the
GitHub release notes generator]
* Generate the release notes
....
java -jar github-changelog-generator.jar \
--changelog.repository=spring-projects/spring-session \
$MILESTONE release-notes
....
Note 1: `+$MILESTONE+` is something like `+3.0.4+` or `+3.0.0-M1+`. +
Note 2: This will create a file on your filesystem
called `+release-notes+`.
* Copy the release notes to your clipboard (your mileage may vary with
the following command)
....
cat release-notes | xclip -selection clipboard
....
* Create the
https://github.com/spring-projects/spring-session/releases[release on
GitHub], associate it with the tag, and paste the generated notes.
== 11. Close / Create Milestone
* In
https://github.com/spring-projects/spring-session/milestones[GitHub
Milestones], create a new milestone for the next release version.
* Move any open issues from the existing milestone you just released to
the new milestone.
* Close the milestone for the release.
Note: Spring Session typically releases only one milestone (M1) and one release candidate (RC1).
== 12. Announce the release
* Announce via Slack on https://pivotal.slack.com/messages/spring-session[#spring-session], and tag any downstream Spring Session projects (e.g Spring Session for Apache Geode).
Note: Do not post on #spring-release or create a blog post. Those steps happen after the Spring Session BOM is released.

View File

@@ -4,7 +4,7 @@ buildscript {
snapshotBuild = version.endsWith('SNAPSHOT')
milestoneBuild = !(releaseBuild || snapshotBuild)
springBootVersion = '2.5.5'
springBootVersion = '3.0.0-SNAPSHOT'
}
repositories {
@@ -45,4 +45,6 @@ subprojects {
nohttp {
source.exclude "buildSrc/build/**"
source.exclude "spring-session-docs/.gradle/nodejs/**"
source.exclude "spring-session-docs/modules/ROOT/examples/**/build/**"
}

View File

@@ -26,6 +26,10 @@ sourceSets {
gradlePlugin {
plugins {
checkAntoraVersion {
id = "org.springframework.antora.check-version"
implementationClass = "org.springframework.gradle.antora.AntoraVersionPlugin"
}
managementConfiguration {
id = "io.spring.convention.management-configuration"
implementationClass = "io.spring.gradle.convention.ManagementConfigurationPlugin"
@@ -54,6 +58,7 @@ configurations {
dependencies {
implementation 'com.google.code.gson:gson:2.8.8'
implementation 'net.sourceforge.saxon:saxon:9.1.0.8'
implementation 'org.yaml:snakeyaml:1.30'
implementation localGroovy()
implementation 'io.github.gradle-nexus:publish-plugin:1.1.0'
@@ -62,11 +67,11 @@ dependencies {
implementation 'com.apollographql.apollo:apollo-runtime:2.4.5'
implementation 'com.github.ben-manes:gradle-versions-plugin:0.38.0'
implementation 'com.github.spullara.mustache.java:compiler:0.9.10'
implementation 'io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.15'
implementation 'io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.34'
implementation 'io.spring.nohttp:nohttp-gradle:0.0.9'
implementation 'net.sourceforge.htmlunit:htmlunit:2.37.0'
implementation 'org.hidetake:gradle-ssh-plugin:2.10.1'
implementation 'org.jfrog.buildinfo:build-info-extractor-gradle:4.24.20'
implementation 'org.jfrog.buildinfo:build-info-extractor-gradle:4.29.0'
implementation 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
testImplementation platform('org.junit:junit-bom:5.8.1')

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -35,6 +35,7 @@ public abstract class AbstractSpringJavaPlugin implements Plugin<Project> {
@Override
public final void apply(Project project) {
initialPlugins(project);
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply(JavaPlugin.class);
pluginManager.apply(ManagementConfigurationPlugin.class)
@@ -69,5 +70,7 @@ public abstract class AbstractSpringJavaPlugin implements Plugin<Project> {
additionalPlugins(project);
}
protected void initialPlugins(Project project) {}
protected abstract void additionalPlugins(Project project);
}

View File

@@ -18,6 +18,7 @@ package io.spring.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
class ArtifactoryPlugin implements Plugin<Project> {
@@ -37,8 +38,14 @@ class ArtifactoryPlugin implements Plugin<Project> {
password = artifactoryPassword
}
}
defaults {
publications('mavenJava')
}
}
project.plugins.withType(MavenPublishPlugin) {
project.artifactory {
publish {
defaults {
publications('mavenJava')
}
}
}
}

View File

@@ -32,6 +32,7 @@ class RootProjectPlugin implements Plugin<Project> {
pluginManager.apply(SchemaPlugin)
pluginManager.apply(NoHttpPlugin)
pluginManager.apply(SpringNexusPublishPlugin)
pluginManager.apply(ArtifactoryPlugin)
pluginManager.apply("org.sonarqube")
project.repositories.mavenCentral()

View File

@@ -30,4 +30,19 @@ public class SpringSamplePlugin extends AbstractSpringJavaPlugin {
project.sonarqube.skipProject = true
}
}
@Override
protected void initialPlugins(Project project) {
if (project.hasProperty('springBootVersion')) {
String springBootVersion = project.springBootVersion
if (Utils.isSnapshot(springBootVersion)) {
project.ext.forceMavenRepositories = 'snapshot'
}
else if (Utils.isMilestone(springBootVersion)) {
project.ext.forceMavenRepositories = 'milestone'
}
}
}
}

View File

@@ -14,16 +14,29 @@ public class Utils {
static boolean isSnapshot(Project project) {
String projectVersion = projectVersion(project)
return projectVersion.matches('^.*([.-]BUILD)?-SNAPSHOT$')
return isSnapshot(projectVersion)
}
static boolean isMilestone(Project project) {
String projectVersion = projectVersion(project)
return projectVersion.matches('^.*[.-]M\\d+$') || projectVersion.matches('^.*[.-]RC\\d+$')
return isMilestone(projectVersion)
}
static boolean isRelease(Project project) {
return !(isSnapshot(project) || isMilestone(project))
String projectVersion = projectVersion(project)
return isRelease(projectVersion)
}
static boolean isSnapshot(String projectVersion) {
return projectVersion.matches('^.*([.-]BUILD)?-SNAPSHOT$')
}
static boolean isMilestone(String projectVersion) {
return projectVersion.matches('^.*[.-]M\\d+$') || projectVersion.matches('^.*[.-]RC\\d+$')
}
static boolean isRelease(String projectVersion) {
return !(isSnapshot(projectVersion) || isMilestone(projectVersion))
}
private static String projectVersion(Project project) {

View File

@@ -0,0 +1,71 @@
package org.springframework.gradle.antora;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.language.base.plugins.LifecycleBasePlugin;
public class AntoraVersionPlugin implements Plugin<Project> {
public static final String ANTORA_CHECK_VERSION_TASK_NAME = "antoraCheckVersion";
@Override
public void apply(Project project) {
TaskProvider<CheckAntoraVersionTask> antoraCheckVersion = project.getTasks().register(ANTORA_CHECK_VERSION_TASK_NAME, CheckAntoraVersionTask.class, new Action<CheckAntoraVersionTask>() {
@Override
public void execute(CheckAntoraVersionTask antoraCheckVersion) {
antoraCheckVersion.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP);
antoraCheckVersion.setDescription("Checks the antora.yml version properties match the Gradle version");
antoraCheckVersion.getAntoraVersion().convention(project.provider(() -> getDefaultAntoraVersion(project)));
antoraCheckVersion.getAntoraPrerelease().convention(project.provider(() -> getDefaultAntoraPrerelease(project)));
antoraCheckVersion.getAntoraDisplayVersion().convention(project.provider(() -> getDefaultAntoraDisplayVersion(project)));
antoraCheckVersion.getAntoraYmlFile().fileProvider(project.provider(() -> project.file("antora.yml")));
}
});
project.getPlugins().withType(LifecycleBasePlugin.class, new Action<LifecycleBasePlugin>() {
@Override
public void execute(LifecycleBasePlugin lifecycleBasePlugin) {
project.getTasks().named(LifecycleBasePlugin.CHECK_TASK_NAME).configure(new Action<Task>() {
@Override
public void execute(Task check) {
check.dependsOn(antoraCheckVersion);
}
});
}
});
project.getTasks().register("antoraUpdateVersion", UpdateAntoraVersionTask.class, new Action<UpdateAntoraVersionTask>() {
@Override
public void execute(UpdateAntoraVersionTask antoraUpdateVersion) {
antoraUpdateVersion.setGroup("Release");
antoraUpdateVersion.setDescription("Updates the antora.yml version properties to match the Gradle version");
antoraUpdateVersion.getAntoraYmlFile().fileProvider(project.provider(() -> project.file("antora.yml")));
}
});
}
private static String getDefaultAntoraVersion(Project project) {
String projectVersion = getProjectVersion(project);
return AntoraVersionUtils.getDefaultAntoraVersion(projectVersion);
}
private static String getDefaultAntoraPrerelease(Project project) {
String projectVersion = getProjectVersion(project);
return AntoraVersionUtils.getDefaultAntoraPrerelease(projectVersion);
}
private static String getDefaultAntoraDisplayVersion(Project project) {
String projectVersion = getProjectVersion(project);
return AntoraVersionUtils.getDefaultAntoraDisplayVersion(projectVersion);
}
private static String getProjectVersion(Project project) {
Object projectVersion = project.getVersion();
if (projectVersion == null) {
throw new GradleException("Please define antoraVersion and antoraPrerelease on " + ANTORA_CHECK_VERSION_TASK_NAME + " or provide a Project version so they can be defaulted");
}
return String.valueOf(projectVersion);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2019-2022 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.gradle.antora;
public class AntoraVersionUtils {
public static String getDefaultAntoraVersion(String projectVersion) {
int preReleaseIndex = getSnapshotIndex(projectVersion);
return isSnapshot(projectVersion) ? projectVersion.substring(0, preReleaseIndex) : projectVersion;
}
public static String getDefaultAntoraPrerelease(String projectVersion) {
if (isSnapshot(projectVersion)) {
int preReleaseIndex = getSnapshotIndex(projectVersion);
return projectVersion.substring(preReleaseIndex);
}
if (isPreRelease(projectVersion)) {
return Boolean.TRUE.toString();
}
return null;
}
public static String getDefaultAntoraDisplayVersion(String projectVersion) {
if (!isSnapshot(projectVersion) && isPreRelease(projectVersion)) {
return getDefaultAntoraVersion(projectVersion);
}
return null;
}
private static boolean isSnapshot(String projectVersion) {
return getSnapshotIndex(projectVersion) >= 0;
}
private static int getSnapshotIndex(String projectVersion) {
return projectVersion.lastIndexOf("-SNAPSHOT");
}
private static boolean isPreRelease(String projectVersion) {
return projectVersion.lastIndexOf("-") >= 0;
}
}

View File

@@ -0,0 +1,96 @@
package org.springframework.gradle.antora;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.TaskAction;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.representer.Representer;
public abstract class CheckAntoraVersionTask extends DefaultTask {
@TaskAction
public void check() throws FileNotFoundException {
File antoraYmlFile = getAntoraYmlFile().getAsFile().get();
String expectedAntoraVersion = getAntoraVersion().get();
String expectedAntoraPrerelease = getAntoraPrerelease().getOrElse(null);
String expectedAntoraDisplayVersion = getAntoraDisplayVersion().getOrElse(null);
Representer representer = new Representer();
representer.getPropertyUtils().setSkipMissingProperties(true);
Yaml yaml = new Yaml(new Constructor(AntoraYml.class), representer);
AntoraYml antoraYml = yaml.load(new FileInputStream(antoraYmlFile));
String actualAntoraPrerelease = antoraYml.getPrerelease();
boolean preReleaseMatches = antoraYml.getPrerelease() == null && expectedAntoraPrerelease == null ||
(actualAntoraPrerelease != null && actualAntoraPrerelease.equals(expectedAntoraPrerelease));
String actualAntoraDisplayVersion = antoraYml.getDisplay_version();
boolean displayVersionMatches = antoraYml.getDisplay_version() == null && expectedAntoraDisplayVersion == null ||
(actualAntoraDisplayVersion != null && actualAntoraDisplayVersion.equals(expectedAntoraDisplayVersion));
String actualAntoraVersion = antoraYml.getVersion();
if (!preReleaseMatches ||
!displayVersionMatches ||
!expectedAntoraVersion.equals(actualAntoraVersion)) {
throw new GradleException("The Gradle version of '" + getProject().getVersion() + "' should have version: '"
+ expectedAntoraVersion + "' prerelease: '" + expectedAntoraPrerelease + "' display_version: '"
+ expectedAntoraDisplayVersion + "' defined in " + antoraYmlFile + " but got version: '"
+ actualAntoraVersion + "' prerelease: '" + actualAntoraPrerelease + "' display_version: '" + actualAntoraDisplayVersion + "'");
}
}
@InputFile
public abstract RegularFileProperty getAntoraYmlFile();
@Input
public abstract Property<String> getAntoraVersion();
@Input
@Optional
public abstract Property<String> getAntoraPrerelease();
@Input
@Optional
public abstract Property<String> getAntoraDisplayVersion();
public static class AntoraYml {
private String version;
private String prerelease;
private String display_version;
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getPrerelease() {
return prerelease;
}
public void setPrerelease(String prerelease) {
this.prerelease = prerelease;
}
public String getDisplay_version() {
return display_version;
}
public void setDisplay_version(String display_version) {
this.display_version = display_version;
}
}
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright 2019-2022 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.gradle.antora;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.TaskAction;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
public abstract class UpdateAntoraVersionTask extends DefaultTask {
@TaskAction
public void update() throws IOException {
String projectVersion = getProject().getVersion().toString();
File antoraYmlFile = getAntoraYmlFile().getAsFile().get();
String updatedAntoraVersion = AntoraVersionUtils.getDefaultAntoraVersion(projectVersion);
String updatedAntoraPrerelease = AntoraVersionUtils.getDefaultAntoraPrerelease(projectVersion);
String updatedAntoraDisplayVersion = AntoraVersionUtils.getDefaultAntoraDisplayVersion(projectVersion);
Representer representer = new Representer();
representer.getPropertyUtils().setSkipMissingProperties(true);
Yaml yaml = new Yaml(new Constructor(AntoraYml.class), representer);
AntoraYml antoraYml = yaml.load(new FileInputStream(antoraYmlFile));
System.out.println("Updating the version parameters in " + antoraYmlFile.getName() + " to version: "
+ updatedAntoraVersion + ", prerelease: " + updatedAntoraPrerelease + ", display_version: "
+ updatedAntoraDisplayVersion);
antoraYml.setVersion(updatedAntoraVersion);
antoraYml.setPrerelease(updatedAntoraPrerelease);
antoraYml.setDisplay_version(updatedAntoraDisplayVersion);
FileWriter outputWriter = new FileWriter(antoraYmlFile);
getYaml().dump(antoraYml, outputWriter);
}
@InputFile
public abstract RegularFileProperty getAntoraYmlFile();
public static class AntoraYml {
private String name;
private String version;
private String prerelease;
private String display_version;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getPrerelease() {
return prerelease;
}
public void setPrerelease(String prerelease) {
this.prerelease = prerelease;
}
public String getDisplay_version() {
return display_version;
}
public void setDisplay_version(String display_version) {
this.display_version = display_version;
}
}
private Yaml getYaml() {
Representer representer = new Representer() {
@Override
protected NodeTuple representJavaBeanProperty(Object javaBean,
org.yaml.snakeyaml.introspector.Property property, Object propertyValue, Tag customTag) {
// Don't write out null values
if (propertyValue == null) {
return null;
}
else {
return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
}
}
};
representer.addClassTag(AntoraYml.class, Tag.MAP);
DumperOptions ymlOptions = new DumperOptions();
ymlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
ymlOptions.setDefaultScalarStyle(DumperOptions.ScalarStyle.SINGLE_QUOTED);
return new Yaml(representer, ymlOptions);
}
}

135
git/hooks/forward-merge Executable file
View File

@@ -0,0 +1,135 @@
#!/usr/bin/ruby
require 'json'
require 'net/http'
require 'yaml'
require 'logger'
$log = Logger.new(STDOUT)
$log.level = Logger::WARN
class ForwardMerge
attr_reader :issue, :milestone, :message, :line
def initialize(issue, milestone, message, line)
@issue = issue
@milestone = milestone
@message = message
@line = line
end
end
def find_forward_merges(message_file)
$log.debug "Searching for forward merge"
rev=`git rev-parse -q --verify MERGE_HEAD`.strip
$log.debug "Found #{rev} from git rev-parse"
return nil unless rev
message = File.read(message_file)
forward_merges = []
message.each_line do |line|
$log.debug "Checking #{line} for message"
match = /^(?:Fixes|Closes) gh-(\d+) in (\d\.\d\.[\dx](?:[\.\-](?:M|RC)\d)?)$/.match(line)
if match then
issue = match[1]
milestone = match[2]
$log.debug "Matched reference to issue #{issue} in milestone #{milestone}"
forward_merges << ForwardMerge.new(issue, milestone, message, line)
end
end
$log.debug "No match in merge message" unless forward_merges
return forward_merges
end
def get_issue(username, password, repository, number)
$log.debug "Getting issue #{number} from GitHub repository #{repository}"
uri = URI("https://api.github.com/repos/#{repository}/issues/#{number}")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl=true
request = Net::HTTP::Get.new(uri.path)
request.basic_auth(username, password)
response = http.request(request)
$log.debug "Get HTTP response #{response.code}"
return JSON.parse(response.body) unless response.code != '200'
puts "Failed to retrieve issue #{number}: #{response.message}"
exit 1
end
def find_milestone(username, password, repository, title)
$log.debug "Finding milestone #{title} from GitHub repository #{repository}"
uri = URI("https://api.github.com/repos/#{repository}/milestones")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl=true
request = Net::HTTP::Get.new(uri.path)
request.basic_auth(username, password)
response = http.request(request)
milestones = JSON.parse(response.body)
if title.end_with?(".x")
prefix = title.delete_suffix('.x')
$log.debug "Finding nearest milestone from candidates starting with #{prefix}"
titles = milestones.map { |milestone| milestone['title'] }
titles = titles.select{ |title| title.start_with?(prefix) unless title.end_with?('.x')}
titles = titles.sort_by { |v| Gem::Version.new(v) }
$log.debug "Considering candidates #{titles}"
if(titles.empty?)
puts "Cannot find nearest milestone for prefix #{title}"
exit 1
end
title = titles.first
$log.debug "Found nearest milestone #{title}"
end
milestones.each do |milestone|
$log.debug "Considering #{milestone['title']}"
return milestone['number'] if milestone['title'] == title
end
puts "Milestone #{title} not found in #{repository}"
exit 1
end
def create_issue(username, password, repository, original, title, labels, milestone, milestone_name, dry_run)
$log.debug "Finding forward-merge issue in GitHub repository #{repository} for '#{title}'"
uri = URI("https://api.github.com/repos/#{repository}/issues")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl=true
request = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
request.basic_auth(username, password)
request.body = {
title: title,
labels: labels,
milestone: milestone.to_i,
body: "Forward port of issue ##{original} to #{milestone_name}."
}.to_json
if dry_run then
puts "Dry run"
puts "POSTing to #{uri} with body #{request.body}"
return "dry-run"
end
response = JSON.parse(http.request(request).body)
$log.debug "Created new issue #{response['number']}"
return response['number']
end
$log.debug "Running forward-merge hook script"
message_file=ARGV[0]
forward_merges = find_forward_merges(message_file)
exit 0 unless forward_merges
$log.debug "Loading config from ~/.spring-boot/forward_merge.yml"
config = YAML.load_file(File.join(Dir.home, '.spring-boot', 'forward-merge.yml'))
username = config['github']['credentials']['username']
password = config['github']['credentials']['password']
dry_run = config['dry_run']
repository = 'spring-projects/spring-session'
forward_merges.each do |forward_merge|
existing_issue = get_issue(username, password, repository, forward_merge.issue)
title = existing_issue['title']
labels = existing_issue['labels'].map { |label| label['name'] }
labels << "status: forward-port"
$log.debug "Processing issue '#{title}'"
milestone = find_milestone(username, password, repository, forward_merge.milestone)
new_issue_number = create_issue(username, password, repository, forward_merge.issue, title, labels, milestone, forward_merge.milestone, dry_run)
puts "Created gh-#{new_issue_number} for forward port of gh-#{forward_merge.issue} into #{forward_merge.milestone}"
rewritten_message = forward_merge.message.sub(forward_merge.line, "Closes gh-#{new_issue_number}\n")
File.write(message_file, rewritten_message)
end

71
git/hooks/prepare-forward-merge Executable file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/ruby
require 'json'
require 'net/http'
require 'yaml'
require 'logger'
$main_branch = "3.0.x"
$log = Logger.new(STDOUT)
$log.level = Logger::WARN
def get_fixed_issues()
$log.debug "Searching for for forward merge"
rev=`git rev-parse -q --verify MERGE_HEAD`.strip
$log.debug "Found #{rev} from git rev-parse"
return nil unless rev
fixed = []
message = `git log -1 --pretty=%B #{rev}`
message.each_line do |line|
$log.debug "Checking #{line} for message"
fixed << line.strip if /^(?:Fixes|Closes) gh-(\d+)/.match(line)
end
$log.debug "Found fixed issues #{fixed}"
return fixed;
end
def rewrite_message(message_file, fixed)
current_branch = `git rev-parse --abbrev-ref HEAD`.strip
if current_branch == "main"
current_branch = $main_branch
end
rewritten_message = ""
message = File.read(message_file)
message.each_line do |line|
match = /^Merge.*branch\ '(.*)'(?:\ into\ (.*))?$/.match(line)
if match
from_branch = match[1]
if from_branch.include? "/"
from_branch = from_branch.partition("/").last
end
to_brach = match[2]
$log.debug "Rewriting merge message"
line = "Merge branch '#{from_branch}'" + (to_brach ? " into #{to_brach}\n" : "\n")
end
if fixed and line.start_with?("#")
$log.debug "Adding fixed"
rewritten_message << "\n"
fixed.each do |fixes|
rewritten_message << "#{fixes} in #{current_branch}\n"
end
fixed = nil
end
rewritten_message << line
end
return rewritten_message
end
$log.debug "Running prepare-forward-merge hook script"
message_file=ARGV[0]
message_type=ARGV[1]
if message_type != "merge"
$log.debug "Not a merge commit"
exit 0;
end
$log.debug "Searching for for forward merge"
fixed = get_fixed_issues()
rewritten_message = rewrite_message(message_file, fixed)
File.write(message_file, rewritten_message)

View File

@@ -1,3 +1,3 @@
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.parallel=true
version=3.0.0-M1
version=3.0.1

View File

@@ -1,45 +1,45 @@
dependencyManagement {
imports {
mavenBom 'io.projectreactor:reactor-bom:2020.0.15'
mavenBom 'com.fasterxml.jackson:jackson-bom:2.13.1'
mavenBom 'org.junit:junit-bom:5.8.2'
mavenBom 'org.springframework:spring-framework-bom:6.0.0-M2'
mavenBom 'org.springframework.data:spring-data-bom:2022.0.0-M1'
mavenBom 'org.springframework.security:spring-security-bom:6.0.0-M1'
mavenBom 'org.testcontainers:testcontainers-bom:1.16.2'
mavenBom 'io.projectreactor:reactor-bom:2022.0.5'
mavenBom 'com.fasterxml.jackson:jackson-bom:2.14.2'
mavenBom 'org.junit:junit-bom:5.9.2'
mavenBom 'org.mockito:mockito-bom:4.8.1'
mavenBom 'org.springframework:spring-framework-bom:6.0.6'
mavenBom 'org.springframework.data:spring-data-bom:2022.0.3'
mavenBom 'org.springframework.security:spring-security-bom:6.0.2'
mavenBom 'org.testcontainers:testcontainers-bom:1.17.3'
}
dependencies {
dependency 'com.hazelcast:hazelcast:5.0.2'
dependency 'org.aspectj:aspectjweaver:1.9.7'
dependency 'ch.qos.logback:logback-core:1.2.10'
dependency 'com.hazelcast:hazelcast:5.1.4'
dependency 'org.aspectj:aspectjweaver:1.9.9.1'
dependency 'ch.qos.logback:logback-core:1.4.4'
dependency 'com.google.code.findbugs:jsr305:3.0.2'
dependency 'com.h2database:h2:1.4.200'
dependency 'com.ibm.db2:jcc:11.5.6.0'
dependency 'com.microsoft.sqlserver:mssql-jdbc:9.4.1.jre8'
dependency 'com.oracle.database.jdbc:ojdbc8:21.4.0.0.1'
dependency 'com.zaxxer:HikariCP:3.4.5'
dependency 'com.h2database:h2:2.1.214'
dependency 'com.ibm.db2:jcc:11.5.7.0'
dependency 'com.microsoft.sqlserver:mssql-jdbc:11.2.1.jre17'
dependency 'com.oracle.database.jdbc:ojdbc8:21.7.0.0'
dependency 'com.zaxxer:HikariCP:5.0.1'
dependency 'edu.umd.cs.mtc:multithreadedtc:1.01'
dependency 'io.lettuce:lettuce-core:6.1.6.RELEASE'
dependency 'jakarta.annotation:jakarta.annotation-api:2.0.0'
dependency 'jakarta.servlet:jakarta.servlet-api:5.0.0'
dependency 'mysql:mysql-connector-java:8.0.27'
dependency 'org.apache.derby:derby:10.14.2.0'
dependency 'org.assertj:assertj-core:3.22.0'
dependency 'org.hamcrest:hamcrest:2.2'
dependency 'org.hsqldb:hsqldb:2.6.1'
dependency 'org.mariadb.jdbc:mariadb-java-client:2.7.4'
dependencySet(group: 'org.mockito', version: '4.2.0') {
entry 'mockito-core'
entry 'mockito-junit-jupiter'
dependency 'io.lettuce:lettuce-core:6.2.1.RELEASE'
dependency 'jakarta.servlet:jakarta.servlet-api:6.0.0'
dependency 'jakarta.websocket:jakarta.websocket-api:2.1.0'
dependency 'jakarta.websocket:jakarta.websocket-client-api:2.1.0'
dependency 'mysql:mysql-connector-java:8.0.30'
dependencySet(group: 'org.apache.derby', version: '10.16.1.1') {
entry 'derby'
entry 'derbytools'
}
dependencySet(group: 'org.mongodb', version: '4.4.1') {
dependency 'org.assertj:assertj-core:3.23.1'
dependency 'org.hamcrest:hamcrest:2.2'
dependency 'org.hsqldb:hsqldb:2.7.0'
dependency 'org.mariadb.jdbc:mariadb-java-client:3.0.7'
dependencySet(group: 'org.mongodb', version: '4.8.2') {
entry 'mongodb-driver-core'
entry 'mongodb-driver-sync'
entry 'mongodb-driver-reactivestreams'
}
dependency 'org.postgresql:postgresql:42.3.1'
dependency 'org.postgresql:postgresql:42.5.0'
}
}

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

6
gradlew vendored
View File

@@ -205,6 +205,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.

180
gradlew.bat vendored
View File

@@ -1,89 +1,91 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -6,12 +6,13 @@ pluginManagement {
}
plugins {
id "com.gradle.enterprise" version "3.8.1"
id "com.gradle.enterprise" version "3.11.2"
id "io.spring.ge.conventions" version "0.0.7"
}
rootProject.name = 'spring-session-build'
include 'spring-session-bom'
include 'spring-session-core'
include 'spring-session-data-mongodb'
include 'spring-session-data-redis'
@@ -19,23 +20,10 @@ include 'spring-session-docs'
include 'spring-session-hazelcast'
include 'spring-session-jdbc'
include 'spring-session-sample-javaconfig-custom-cookie'
project(':spring-session-sample-javaconfig-custom-cookie').projectDir = file('spring-session-samples/spring-session-sample-javaconfig-custom-cookie')
include 'spring-session-sample-javaconfig-jdbc'
project(':spring-session-sample-javaconfig-jdbc').projectDir = file('spring-session-samples/spring-session-sample-javaconfig-jdbc')
include 'spring-session-sample-javaconfig-redis'
project(':spring-session-sample-javaconfig-redis').projectDir = file('spring-session-samples/spring-session-sample-javaconfig-redis')
include 'spring-session-sample-misc-hazelcast'
project(':spring-session-sample-misc-hazelcast').projectDir = file('spring-session-samples/spring-session-sample-misc-hazelcast')
include 'spring-session-sample-xml-redis'
project(':spring-session-sample-xml-redis').projectDir = file('spring-session-samples/spring-session-sample-xml-redis')
include 'spring-session-sample-xml-jdbc'
project(':spring-session-sample-xml-jdbc').projectDir = file('spring-session-samples/spring-session-sample-xml-jdbc')
//file('spring-session-samples').eachDirMatch(~/spring-session-sample-.*/) { dir ->
// include dir.name
// project(":$dir.name").projectDir = dir
//}
file('spring-session-samples').eachDirMatch(~/spring-session-sample-.*/) { dir ->
include dir.name
project(":$dir.name").projectDir = dir
}
rootProject.children.each { project ->
project.buildFileName = "${project.name}.gradle"

View File

@@ -0,0 +1,15 @@
import io.spring.gradle.convention.SpringModulePlugin
plugins {
id("io.spring.convention.bom")
}
dependencies {
constraints {
project.rootProject.allprojects { project ->
project.plugins.withType(SpringModulePlugin) {
api(project)
}
}
}
}

View File

@@ -6,7 +6,6 @@ dependencies {
api "org.springframework:spring-jcl"
optional "io.projectreactor:reactor-core"
optional "jakarta.annotation:jakarta.annotation-api"
optional "jakarta.servlet:jakarta.servlet-api"
optional "org.springframework:spring-context"
optional "org.springframework:spring-jdbc"
@@ -19,6 +18,8 @@ dependencies {
testImplementation "io.projectreactor:reactor-test"
testImplementation "org.mockito:mockito-core"
testImplementation "org.mockito:mockito-junit-jupiter"
testImplementation "org.mockito:mockito-inline"
testImplementation "edu.umd.cs.mtc:multithreadedtc"
testImplementation "org.springframework:spring-test"
testImplementation "org.assertj:assertj-core"

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -49,10 +49,16 @@ import java.util.UUID;
public final class MapSession implements Session, Serializable {
/**
* Default {@link #setMaxInactiveInterval(Duration)} (30 minutes).
* Default {@link #setMaxInactiveInterval(Duration)} (30 minutes) in seconds.
*/
public static final int DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS = 1800;
/**
* Default {@link #setMaxInactiveInterval(Duration)} (30 minutes).
*/
public static final Duration DEFAULT_MAX_INACTIVE_INTERVAL = Duration
.ofSeconds(DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
private String id;
private final String originalId;
@@ -66,7 +72,7 @@ public final class MapSession implements Session, Serializable {
/**
* Defaults to 30 minutes.
*/
private Duration maxInactiveInterval = Duration.ofSeconds(DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
private Duration maxInactiveInterval = DEFAULT_MAX_INACTIVE_INTERVAL;
/**
* Creates a new instance with a secure randomly generated identifier.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -21,6 +21,7 @@ import java.util.Map;
import org.springframework.session.events.SessionDeletedEvent;
import org.springframework.session.events.SessionExpiredEvent;
import org.springframework.util.Assert;
/**
* A {@link SessionRepository} backed by a {@link java.util.Map} and that uses a
@@ -38,11 +39,7 @@ import org.springframework.session.events.SessionExpiredEvent;
*/
public class MapSessionRepository implements SessionRepository<MapSession> {
/**
* If non-null, this value is used to override
* {@link Session#setMaxInactiveInterval(Duration)}.
*/
private Integer defaultMaxInactiveInterval;
private Duration defaultMaxInactiveInterval = Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
private final Map<String, Session> sessions;
@@ -59,12 +56,13 @@ public class MapSessionRepository implements SessionRepository<MapSession> {
}
/**
* If non-null, this value is used to override
* {@link Session#setMaxInactiveInterval(Duration)}.
* @param defaultMaxInactiveInterval the number of seconds that the {@link Session}
* should be kept alive between client requests.
* Set the maximum inactive interval in seconds between requests before newly created
* sessions will be invalidated. A negative time indicates that the session will never
* time out. The default is 30 minutes.
* @param defaultMaxInactiveInterval the default maxInactiveInterval
*/
public void setDefaultMaxInactiveInterval(int defaultMaxInactiveInterval) {
public void setDefaultMaxInactiveInterval(Duration defaultMaxInactiveInterval) {
Assert.notNull(defaultMaxInactiveInterval, "defaultMaxInactiveInterval must not be null");
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
}
@@ -97,9 +95,7 @@ public class MapSessionRepository implements SessionRepository<MapSession> {
@Override
public MapSession createSession() {
MapSession result = new MapSession();
if (this.defaultMaxInactiveInterval != null) {
result.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
}
result.setMaxInactiveInterval(this.defaultMaxInactiveInterval);
return result;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -23,6 +23,7 @@ import reactor.core.publisher.Mono;
import org.springframework.session.events.SessionDeletedEvent;
import org.springframework.session.events.SessionExpiredEvent;
import org.springframework.util.Assert;
/**
* A {@link ReactiveSessionRepository} backed by a {@link Map} and that uses a
@@ -40,11 +41,7 @@ import org.springframework.session.events.SessionExpiredEvent;
*/
public class ReactiveMapSessionRepository implements ReactiveSessionRepository<MapSession> {
/**
* If non-null, this value is used to override
* {@link Session#setMaxInactiveInterval(Duration)}.
*/
private Integer defaultMaxInactiveInterval;
private Duration defaultMaxInactiveInterval = Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
private final Map<String, Session> sessions;
@@ -61,12 +58,13 @@ public class ReactiveMapSessionRepository implements ReactiveSessionRepository<M
}
/**
* If non-null, this value is used to override
* {@link Session#setMaxInactiveInterval(Duration)}.
* @param defaultMaxInactiveInterval the number of seconds that the {@link Session}
* should be kept alive between client requests.
* Set the maximum inactive interval in seconds between requests before newly created
* sessions will be invalidated. A negative time indicates that the session will never
* time out. The default is 30 minutes.
* @param defaultMaxInactiveInterval the default maxInactiveInterval
*/
public void setDefaultMaxInactiveInterval(int defaultMaxInactiveInterval) {
public void setDefaultMaxInactiveInterval(Duration defaultMaxInactiveInterval) {
Assert.notNull(defaultMaxInactiveInterval, "defaultMaxInactiveInterval must not be null");
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
}
@@ -99,9 +97,7 @@ public class ReactiveMapSessionRepository implements ReactiveSessionRepository<M
public Mono<MapSession> createSession() {
return Mono.defer(() -> {
MapSession result = new MapSession();
if (this.defaultMaxInactiveInterval != null) {
result.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
}
result.setMaxInactiveInterval(this.defaultMaxInactiveInterval);
return Mono.just(result);
});
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2014-2022 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.aot.hint;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.TreeSet;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
/**
* A {@link RuntimeHintsRegistrar} for common session hints.
*
* @author Marcus Da Coregio
*/
class CommonSessionRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
Arrays.asList(TypeReference.of(String.class), TypeReference.of(ArrayList.class),
TypeReference.of(TreeSet.class), TypeReference.of(Number.class), TypeReference.of(Long.class),
TypeReference.of(Integer.class), TypeReference.of(StackTraceElement.class),
TypeReference.of(Throwable.class), TypeReference.of(Exception.class),
TypeReference.of(RuntimeException.class),
TypeReference.of("java.util.Collections$UnmodifiableCollection"),
TypeReference.of("java.util.Collections$UnmodifiableList"),
TypeReference.of("java.util.Collections$EmptyList"),
TypeReference.of("java.util.Collections$UnmodifiableRandomAccessList"),
TypeReference.of("java.util.Collections$UnmodifiableSet")).forEach(hints.serialization()::registerType);
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2014-2022 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.aot.hint;
import java.util.Arrays;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
/**
* A {@link RuntimeHintsRegistrar} for common session security hints.
*
* @author Marcus Da Coregio
*/
class CommonSessionSecurityRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
registerSecurityHintsIfNeeded(hints);
registerOAuth2ClientHintsIfNeeded(hints);
registerOAuth2ResourceServerHintsIfNeeded(hints);
}
private void registerSecurityHintsIfNeeded(RuntimeHints hints) {
Arrays.asList(TypeReference.of("org.springframework.security.core.context.SecurityContextImpl"),
TypeReference.of("org.springframework.security.core.authority.SimpleGrantedAuthority"),
TypeReference.of("org.springframework.security.core.userdetails.User"),
TypeReference.of("org.springframework.security.authentication.AbstractAuthenticationToken"),
TypeReference.of("org.springframework.security.authentication.UsernamePasswordAuthenticationToken"),
TypeReference.of("org.springframework.security.core.AuthenticationException"),
TypeReference.of("org.springframework.security.authentication.BadCredentialsException"),
TypeReference.of("org.springframework.security.core.userdetails.UsernameNotFoundException"),
TypeReference.of("org.springframework.security.authentication.AccountExpiredException"),
TypeReference.of("org.springframework.security.authentication.ProviderNotFoundException"),
TypeReference.of("org.springframework.security.authentication.DisabledException"),
TypeReference.of("org.springframework.security.authentication.LockedException"),
TypeReference.of("org.springframework.security.authentication.AuthenticationServiceException"),
TypeReference.of("org.springframework.security.authentication.CredentialsExpiredException"),
TypeReference.of("org.springframework.security.authentication.InsufficientAuthenticationException"),
TypeReference
.of("org.springframework.security.web.authentication.session.SessionAuthenticationException"),
TypeReference.of(
"org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException"),
TypeReference.of("org.springframework.security.core.userdetails.User$AuthorityComparator"))
.forEach((type) -> hints.serialization().registerType(type, (hint) -> hint.onReachableType(
TypeReference.of("org.springframework.security.core.context.SecurityContextImpl"))));
}
private void registerOAuth2ResourceServerHintsIfNeeded(RuntimeHints hints) {
Arrays.asList(
TypeReference.of("org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken"),
TypeReference.of(
"org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken"),
TypeReference.of("org.springframework.security.oauth2.core.OAuth2AuthenticationException"))
.forEach((type) -> hints.serialization().registerType(type, (hint) -> hint.onReachableType(TypeReference
.of("org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken"))));
}
private void registerOAuth2ClientHintsIfNeeded(RuntimeHints hints) {
Arrays.asList(
TypeReference.of("org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken"),
TypeReference
.of("org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationToken"),
TypeReference.of(
"org.springframework.security.oauth2.client.authentication.OAuth2AuthorizationCodeAuthenticationToken"),
TypeReference.of("org.springframework.security.oauth2.core.OAuth2AuthenticationException"))
.forEach((type) -> hints.serialization().registerType(type, (hint) -> hint.onReachableType(TypeReference
.of("org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken"))));
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2014-2022 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.aot.hint.server;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.security.web.server.csrf.DefaultCsrfToken;
import org.springframework.util.ClassUtils;
/**
* {@link RuntimeHintsRegistrar} for Reactive Session hints.
*
* @author Marcus Da Coregio
*/
class WebSessionSecurityRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
if (!ClassUtils.isPresent("org.springframework.web.server.WebSession", classLoader) || !ClassUtils
.isPresent("org.springframework.security.web.server.csrf.DefaultCsrfToken", classLoader)) {
return;
}
hints.serialization().registerType(DefaultCsrfToken.class);
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2014-2022 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.aot.hint.servlet;
import java.util.Arrays;
import java.util.Locale;
import java.util.TreeMap;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.csrf.DefaultCsrfToken;
import org.springframework.security.web.savedrequest.DefaultSavedRequest;
import org.springframework.security.web.savedrequest.SavedCookie;
import org.springframework.util.ClassUtils;
/**
* {@link RuntimeHintsRegistrar} for Servlet Session hints.
*
* @author Marcus Da Coregio
*/
class HttpSessionSecurityRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
if (!ClassUtils.isPresent("jakarta.servlet.http.HttpSession", classLoader)
|| !ClassUtils.isPresent("org.springframework.security.web.csrf.DefaultCsrfToken", classLoader)) {
return;
}
Arrays.asList(TypeReference.of(TreeMap.class), TypeReference.of(Locale.class),
TypeReference.of(DefaultSavedRequest.class), TypeReference.of(DefaultCsrfToken.class),
TypeReference.of(WebAuthenticationDetails.class), TypeReference.of(SavedCookie.class),
TypeReference.of("java.lang.String$CaseInsensitiveComparator"))
.forEach(hints.serialization()::registerType);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -20,7 +20,6 @@ import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.session.SessionRepository;
import org.springframework.session.events.SessionCreatedEvent;
@@ -34,7 +33,7 @@ import org.springframework.session.events.SessionDestroyedEvent;
*
* <pre>
* <code>
* {@literal @Configuration}
* {@literal @Configuration(proxyBeanMethods = false)}
* {@literal @EnableSpringHttpSession}
* public class SpringHttpSessionConfig {
*
@@ -74,7 +73,6 @@ import org.springframework.session.events.SessionDestroyedEvent;
@Target({ java.lang.annotation.ElementType.TYPE })
@Documented
@Import(SpringHttpSessionConfiguration.class)
@Configuration(proxyBeanMethods = false)
public @interface EnableSpringHttpSession {
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -19,7 +19,6 @@ package org.springframework.session.config.annotation.web.http;
import java.util.ArrayList;
import java.util.List;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.ServletContext;
import jakarta.servlet.SessionCookieConfig;
import jakarta.servlet.http.HttpSessionListener;
@@ -28,6 +27,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -91,7 +91,7 @@ import org.springframework.util.ObjectUtils;
* @see EnableSpringHttpSession
*/
@Configuration(proxyBeanMethods = false)
public class SpringHttpSessionConfiguration implements ApplicationContextAware {
public class SpringHttpSessionConfiguration implements InitializingBean, ApplicationContextAware {
private final Log logger = LogFactory.getLog(getClass());
@@ -107,8 +107,8 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
private List<HttpSessionListener> httpSessionListeners = new ArrayList<>();
@PostConstruct
public void init() {
@Override
public void afterPropertiesSet() {
CookieSerializer cookieSerializer = (this.cookieSerializer != null) ? this.cookieSerializer
: createDefaultCookieSerializer();
this.defaultHttpSessionIdResolver.setCookieSerializer(cookieSerializer);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -20,7 +20,6 @@ import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
@@ -31,7 +30,7 @@ import org.springframework.context.annotation.Import;
*
* <pre>
* <code>
* {@literal @Configuration}
* {@literal @Configuration(proxyBeanMethods = false)}
* {@literal @EnableSpringWebSession}
* public class SpringWebFluxConfig {
*
@@ -50,7 +49,6 @@ import org.springframework.context.annotation.Import;
@Target({ java.lang.annotation.ElementType.TYPE })
@Documented
@Import(SpringWebSessionConfiguration.class)
@Configuration(proxyBeanMethods = false)
public @interface EnableSpringWebSession {
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -19,14 +19,11 @@ package org.springframework.session.web.http;
import java.time.Duration;
import java.util.Collections;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.Set;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpSessionBindingEvent;
import jakarta.servlet.http.HttpSessionBindingListener;
import jakarta.servlet.http.HttpSessionContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -41,12 +38,11 @@ import org.springframework.session.Session;
* @author Vedran Pavic
* @since 1.1
*/
@SuppressWarnings("deprecation")
class HttpSessionAdapter<S extends Session> implements HttpSession {
private static final Log logger = LogFactory.getLog(HttpSessionAdapter.class);
private S session;
private final S session;
private final ServletContext servletContext;
@@ -101,35 +97,18 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
return (int) this.session.getMaxInactiveInterval().getSeconds();
}
@Override
public HttpSessionContext getSessionContext() {
return NOOP_SESSION_CONTEXT;
}
@Override
public Object getAttribute(String name) {
checkState();
return this.session.getAttribute(name);
}
@Override
public Object getValue(String name) {
return getAttribute(name);
}
@Override
public Enumeration<String> getAttributeNames() {
checkState();
return Collections.enumeration(this.session.getAttributeNames());
}
@Override
public String[] getValueNames() {
checkState();
Set<String> attrs = this.session.getAttributeNames();
return attrs.toArray(new String[0]);
}
@Override
public void setAttribute(String name, Object value) {
checkState();
@@ -156,11 +135,6 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
}
}
@Override
public void putValue(String name, Object value) {
setAttribute(name, value);
}
@Override
public void removeAttribute(String name) {
checkState();
@@ -176,11 +150,6 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
}
}
@Override
public void removeValue(String name) {
removeAttribute(name);
}
@Override
public void invalidate() {
checkState();
@@ -203,32 +172,4 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
}
}
private static final HttpSessionContext NOOP_SESSION_CONTEXT = new HttpSessionContext() {
@Override
public HttpSession getSession(String sessionId) {
return null;
}
@Override
public Enumeration<String> getIds() {
return EMPTY_ENUMERATION;
}
};
private static final Enumeration<String> EMPTY_ENUMERATION = new Enumeration<String>() {
@Override
public boolean hasMoreElements() {
return false;
}
@Override
public String nextElement() {
throw new NoSuchElementException("a");
}
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2021 the original author or authors.
* Copyright 2014-2022 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.
@@ -75,6 +75,7 @@ import org.springframework.session.SessionRepository;
* @author Rob Winch
* @author Vedran Pavic
* @author Josh Cummings
* @author Yanming Zhou
* @since 1.0
*/
@Order(SessionRepositoryFilter.DEFAULT_ORDER)
@@ -222,10 +223,11 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
}
else {
S session = wrappedSession.getSession();
String requestedSessionId = getRequestedSessionId();
clearRequestedSessionCache();
SessionRepositoryFilter.this.sessionRepository.save(session);
String sessionId = session.getId();
if (!isRequestedSessionIdValid() || !sessionId.equals(getRequestedSessionId())) {
if (!isRequestedSessionIdValid() || !sessionId.equals(requestedSessionId)) {
SessionRepositoryFilter.this.httpSessionIdResolver.setSessionId(this, this.response, sessionId);
}
}
@@ -265,14 +267,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
if (requestedSession != null) {
requestedSession.setLastAccessedTime(Instant.now());
}
return isRequestedSessionIdValid(requestedSession);
}
return this.requestedSessionIdValid;
}
private boolean isRequestedSessionIdValid(S session) {
if (this.requestedSessionIdValid == null) {
this.requestedSessionIdValid = session != null;
this.requestedSessionIdValid = (requestedSession != null);
}
return this.requestedSessionIdValid;
}
@@ -356,7 +351,6 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
S session = SessionRepositoryFilter.this.sessionRepository.findById(sessionId);
if (session != null) {
this.requestedSession = session;
this.requestedSessionId = sessionId;
break;
}
}

View File

@@ -0,0 +1,5 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.session.aot.hint.CommonSessionRuntimeHints,\
org.springframework.session.aot.hint.CommonSessionSecurityRuntimeHints,\
org.springframework.session.aot.hint.servlet.HttpSessionSecurityRuntimeHints,\
org.springframework.session.aot.hint.server.WebSessionSecurityRuntimeHints

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -60,8 +60,8 @@ class MapSessionRepositoryTests {
@Test
void createSessionCustomDefaultExpiration() {
final Duration expectedMaxInterval = new MapSession().getMaxInactiveInterval().plusSeconds(10);
this.repository.setDefaultMaxInactiveInterval((int) expectedMaxInterval.getSeconds());
Duration expectedMaxInterval = new MapSession().getMaxInactiveInterval().plusSeconds(10);
this.repository.setDefaultMaxInactiveInterval(expectedMaxInterval);
Session session = this.repository.createSession();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -103,8 +103,8 @@ class ReactiveMapSessionRepositoryTests {
@Test
void createSessionWhenCustomMaxInactiveIntervalThenCustomMaxInactiveInterval() {
final Duration expectedMaxInterval = new MapSession().getMaxInactiveInterval().plusSeconds(10);
this.repository.setDefaultMaxInactiveInterval((int) expectedMaxInterval.getSeconds());
Duration expectedMaxInterval = new MapSession().getMaxInactiveInterval().plusSeconds(10);
this.repository.setDefaultMaxInactiveInterval(expectedMaxInterval);
Session session = this.repository.createSession().block();

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2014-2022 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.aot.hint;
import java.util.ArrayList;
import java.util.TreeSet;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.core.io.support.SpringFactoriesLoader;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link CommonSessionRuntimeHints}
*
* @author Marcus Da Coregio
*/
class CommonSessionRuntimeHintsTests {
private final RuntimeHints hints = new RuntimeHints();
private final CommonSessionRuntimeHints commonSessionRuntimeHints = new CommonSessionRuntimeHints();
@ParameterizedTest
@MethodSource("getSerializationHintTypes")
void commonSessionTypesHasHints(TypeReference typeReference) {
this.commonSessionRuntimeHints.registerHints(this.hints, getClass().getClassLoader());
assertThat(RuntimeHintsPredicates.serialization().onType(typeReference)).accepts(this.hints);
}
@Test
void aotFactoriesContainsRegistrar() {
boolean match = SpringFactoriesLoader.forResourceLocation("META-INF/spring/aot.factories")
.load(RuntimeHintsRegistrar.class).stream()
.anyMatch((registrar) -> registrar instanceof CommonSessionRuntimeHints);
assertThat(match).isTrue();
}
private static Stream<TypeReference> getSerializationHintTypes() {
return Stream.of(TypeReference.of(String.class), TypeReference.of(ArrayList.class),
TypeReference.of(TreeSet.class), TypeReference.of(Number.class), TypeReference.of(Long.class),
TypeReference.of(Integer.class), TypeReference.of(StackTraceElement.class),
TypeReference.of(Throwable.class), TypeReference.of(Exception.class),
TypeReference.of(RuntimeException.class),
TypeReference.of("java.util.Collections$UnmodifiableCollection"),
TypeReference.of("java.util.Collections$UnmodifiableList"),
TypeReference.of("java.util.Collections$EmptyList"),
TypeReference.of("java.util.Collections$UnmodifiableRandomAccessList"),
TypeReference.of("java.util.Collections$UnmodifiableSet"));
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2014-2022 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.aot.hint;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.core.io.support.SpringFactoriesLoader;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link CommonSessionSecurityRuntimeHints}
*
* @author Marcus Da Coregio
*/
class CommonSessionSecurityRuntimeHintsTests {
private final RuntimeHints hints = new RuntimeHints();
private final CommonSessionSecurityRuntimeHints commonSessionSecurityRuntimeHints = new CommonSessionSecurityRuntimeHints();
@ParameterizedTest
@MethodSource("getSerializationHintTypes")
void commonSecurityTypesHasHints(TypeReference typeReference) {
this.commonSessionSecurityRuntimeHints.registerHints(this.hints, getClass().getClassLoader());
assertThat(RuntimeHintsPredicates.serialization().onType(typeReference)).accepts(this.hints);
}
@Test
void aotFactoriesContainsRegistrar() {
boolean match = SpringFactoriesLoader.forResourceLocation("META-INF/spring/aot.factories")
.load(RuntimeHintsRegistrar.class).stream()
.anyMatch((registrar) -> registrar instanceof CommonSessionSecurityRuntimeHints);
assertThat(match).isTrue();
}
private static Stream<TypeReference> getSerializationHintTypes() {
return Stream.of(TypeReference.of("org.springframework.security.core.context.SecurityContextImpl"),
TypeReference.of("org.springframework.security.core.authority.SimpleGrantedAuthority"),
TypeReference.of("org.springframework.security.core.userdetails.User"),
TypeReference.of("org.springframework.security.authentication.AbstractAuthenticationToken"),
TypeReference.of("org.springframework.security.authentication.UsernamePasswordAuthenticationToken"),
TypeReference.of("org.springframework.security.core.AuthenticationException"),
TypeReference.of("org.springframework.security.authentication.BadCredentialsException"),
TypeReference.of("org.springframework.security.core.userdetails.UsernameNotFoundException"),
TypeReference.of("org.springframework.security.authentication.AccountExpiredException"),
TypeReference.of("org.springframework.security.authentication.ProviderNotFoundException"),
TypeReference.of("org.springframework.security.authentication.DisabledException"),
TypeReference.of("org.springframework.security.authentication.LockedException"),
TypeReference.of("org.springframework.security.authentication.AuthenticationServiceException"),
TypeReference.of("org.springframework.security.authentication.CredentialsExpiredException"),
TypeReference.of("org.springframework.security.authentication.InsufficientAuthenticationException"),
TypeReference
.of("org.springframework.security.web.authentication.session.SessionAuthenticationException"),
TypeReference.of(
"org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException"),
TypeReference.of("org.springframework.security.core.userdetails.User$AuthorityComparator"),
TypeReference.of("org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken"),
TypeReference.of(
"org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken"),
TypeReference.of("org.springframework.security.oauth2.core.OAuth2AuthenticationException"),
TypeReference.of("org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken"),
TypeReference
.of("org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationToken"),
TypeReference.of(
"org.springframework.security.oauth2.client.authentication.OAuth2AuthorizationCodeAuthenticationToken"),
TypeReference.of("org.springframework.security.oauth2.core.OAuth2AuthenticationException"));
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright 2014-2022 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.aot.hint.server;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.security.web.server.csrf.DefaultCsrfToken;
import org.springframework.util.ClassUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mockStatic;
/**
* Tests for {@link WebSessionSecurityRuntimeHints}
*
* @author Marcus Da Coregio
*/
class WebSessionSecurityRuntimeHintsTests {
private final RuntimeHints hints = new RuntimeHints();
private final WebSessionSecurityRuntimeHints webSessionSecurityRuntimeHints = new WebSessionSecurityRuntimeHints();
@Test
void defaultCsrfTokenHasHints() {
this.webSessionSecurityRuntimeHints.registerHints(this.hints, getClass().getClassLoader());
assertThat(RuntimeHintsPredicates.serialization().onType(DefaultCsrfToken.class)).accepts(this.hints);
}
@Test
void registerHintsWhenWebSessionMissingThenDoNotRegisterHints() {
try (MockedStatic<ClassUtils> classUtilsMock = mockStatic(ClassUtils.class)) {
classUtilsMock.when(() -> ClassUtils.isPresent(eq("org.springframework.web.server.WebSession"), any()))
.thenReturn(false);
this.webSessionSecurityRuntimeHints.registerHints(this.hints, getClass().getClassLoader());
assertThat(this.hints.serialization().javaSerializationHints()).isEmpty();
}
}
@Test
void registerHintsWhenDefaultCsrfTokenMissingThenDoNotRegisterHints() {
try (MockedStatic<ClassUtils> classUtilsMock = mockStatic(ClassUtils.class)) {
classUtilsMock
.when(() -> ClassUtils
.isPresent(eq("org.springframework.security.web.server.csrf.DefaultCsrfToken"), any()))
.thenReturn(false);
this.webSessionSecurityRuntimeHints.registerHints(this.hints, getClass().getClassLoader());
assertThat(this.hints.serialization().javaSerializationHints()).isEmpty();
}
}
@Test
void aotFactoriesContainsRegistrar() {
boolean match = SpringFactoriesLoader.forResourceLocation("META-INF/spring/aot.factories")
.load(RuntimeHintsRegistrar.class).stream()
.anyMatch((registrar) -> registrar instanceof WebSessionSecurityRuntimeHints);
assertThat(match).isTrue();
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2014-2022 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.aot.hint.servlet;
import java.util.Locale;
import java.util.TreeMap;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.MockedStatic;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.csrf.DefaultCsrfToken;
import org.springframework.security.web.savedrequest.DefaultSavedRequest;
import org.springframework.security.web.savedrequest.SavedCookie;
import org.springframework.util.ClassUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mockStatic;
/**
* Tests for {@link HttpSessionSecurityRuntimeHints}
*
* @author Marcus Da Coregio
*/
class HttpSessionSecurityRuntimeHintsTests {
private final RuntimeHints hints = new RuntimeHints();
private final HttpSessionSecurityRuntimeHints httpSessionSecurityRuntimeHints = new HttpSessionSecurityRuntimeHints();
@ParameterizedTest
@MethodSource("getSerializationHintTypes")
void httpSessionHasHints(TypeReference typeReference) {
this.httpSessionSecurityRuntimeHints.registerHints(this.hints, getClass().getClassLoader());
assertThat(RuntimeHintsPredicates.serialization().onType(typeReference)).accepts(this.hints);
}
@Test
void registerHintsWhenHttpSessionMissingThenDoNotRegisterHints() {
try (MockedStatic<ClassUtils> classUtilsMock = mockStatic(ClassUtils.class)) {
classUtilsMock.when(() -> ClassUtils.isPresent(eq("jakarta.servlet.http.HttpSession"), any()))
.thenReturn(false);
this.httpSessionSecurityRuntimeHints.registerHints(this.hints, getClass().getClassLoader());
assertThat(this.hints.serialization().javaSerializationHints()).isEmpty();
}
}
@Test
void registerHintsWhenDefaultCsrfTokenMissingThenDoNotRegisterHints() {
try (MockedStatic<ClassUtils> classUtilsMock = mockStatic(ClassUtils.class)) {
classUtilsMock.when(
() -> ClassUtils.isPresent(eq("org.springframework.security.web.csrf.DefaultCsrfToken"), any()))
.thenReturn(false);
this.httpSessionSecurityRuntimeHints.registerHints(this.hints, getClass().getClassLoader());
assertThat(this.hints.serialization().javaSerializationHints()).isEmpty();
}
}
@Test
void aotFactoriesContainsRegistrar() {
boolean match = SpringFactoriesLoader.forResourceLocation("META-INF/spring/aot.factories")
.load(RuntimeHintsRegistrar.class).stream()
.anyMatch((registrar) -> registrar instanceof HttpSessionSecurityRuntimeHints);
assertThat(match).isTrue();
}
private static Stream<TypeReference> getSerializationHintTypes() {
return Stream.of(TypeReference.of(TreeMap.class), TypeReference.of(Locale.class),
TypeReference.of(DefaultSavedRequest.class), TypeReference.of(DefaultCsrfToken.class),
TypeReference.of(WebAuthenticationDetails.class), TypeReference.of(SavedCookie.class),
TypeReference.of("java.lang.String$CaseInsensitiveComparator"));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -24,6 +24,7 @@ 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.session.ReactiveMapSessionRepository;
import org.springframework.session.ReactiveSessionRepository;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
@@ -105,6 +106,7 @@ class SpringWebSessionConfigurationTests {
/**
* A configuration with all the right parts.
*/
@Configuration(proxyBeanMethods = false)
@EnableSpringWebSession
static class GoodConfig {
@@ -122,11 +124,13 @@ class SpringWebSessionConfigurationTests {
/**
* A configuration where no {@link ReactiveSessionRepository} is defined. It's BAD!
*/
@Configuration(proxyBeanMethods = false)
@EnableSpringWebSession
static class BadConfig {
}
@Configuration(proxyBeanMethods = false)
@EnableSpringWebSession
static class OverrideSessionIdResolver {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2021 the original author or authors.
* Copyright 2014-2022 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.
@@ -24,12 +24,12 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.core.AuthenticatedPrincipal;
import org.springframework.security.core.Authentication;
@@ -44,10 +44,12 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.mock;
import static org.mockito.BDDMockito.verify;
import static org.mockito.Mockito.withSettings;
/**
* Tests for {@link SpringSessionBackedSessionRegistry}.
*/
@ExtendWith(MockitoExtension.class)
class SpringSessionBackedSessionRegistryTest {
private static final String SESSION_ID = "sessionId";
@@ -66,11 +68,6 @@ class SpringSessionBackedSessionRegistryTest {
@InjectMocks
private SpringSessionBackedSessionRegistry<Session> sessionRegistry;
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
void sessionInformationForExistingSession() {
Session session = createSession(SESSION_ID, USER_NAME, NOW);
@@ -157,7 +154,7 @@ class SpringSessionBackedSessionRegistryTest {
private Session createSession(String sessionId, String userName, Instant lastAccessed) {
MapSession session = new MapSession(sessionId);
session.setLastAccessedTime(lastAccessed);
Authentication authentication = mock(Authentication.class);
Authentication authentication = mock(Authentication.class, withSettings().lenient());
given(authentication.getName()).willReturn(userName);
SecurityContextImpl securityContext = new SecurityContextImpl();
securityContext.setAuthentication(authentication);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -26,18 +26,20 @@ import jakarta.servlet.http.HttpServletResponse;
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.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
class OnCommittedResponseWrapperTests {
private static final String NL = "\r\n";
@Mock
@Mock(lenient = true)
HttpServletResponse delegate;
@Mock
@@ -52,7 +54,6 @@ class OnCommittedResponseWrapperTests {
@BeforeEach
void setup() throws Exception {
MockitoAnnotations.initMocks(this);
this.response = new OnCommittedResponseWrapper(this.delegate) {
@Override
protected void onResponseCommitted() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2021 the original author or authors.
* Copyright 2014-2022 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.
@@ -25,10 +25,11 @@ import jakarta.servlet.http.HttpSessionListener;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.mock.web.MockServletContext;
import org.springframework.session.MapSession;
@@ -47,6 +48,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
* @author Rob Winch
* @since 1.1
*/
@ExtendWith(MockitoExtension.class)
class SessionEventHttpSessionListenerAdapterTests {
@Mock
@@ -69,7 +71,6 @@ class SessionEventHttpSessionListenerAdapterTests {
@BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
this.listener = new SessionEventHttpSessionListenerAdapter(Arrays.asList(this.listener1, this.listener2));
this.listener.setServletContext(new MockServletContext());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -24,7 +24,6 @@ import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -40,13 +39,13 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpSessionBindingEvent;
import jakarta.servlet.http.HttpSessionBindingListener;
import jakarta.servlet.http.HttpSessionContext;
import org.assertj.core.data.Offset;
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.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
@@ -78,7 +77,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
/**
* Tests for {@link SessionRepositoryFilter}.
*/
@SuppressWarnings("deprecation")
@ExtendWith(MockitoExtension.class)
class SessionRepositoryFilterTests {
@Mock
@@ -98,7 +97,6 @@ class SessionRepositoryFilterTests {
@BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
this.sessions = new HashMap<>();
this.sessionRepository = new MapSessionRepository(this.sessions);
this.filter = new SessionRepositoryFilter<>(this.sessionRepository);
@@ -315,52 +313,6 @@ class SessionRepositoryFilterTests {
});
}
@Test
void doFilterValue() throws Exception {
final String ATTR = "ATTR";
final String VALUE = "VALUE";
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
wrappedRequest.getSession().putValue(ATTR, VALUE);
assertThat(wrappedRequest.getSession().getValue(ATTR)).isEqualTo(VALUE);
assertThat(Arrays.asList(wrappedRequest.getSession().getValueNames())).containsOnly(ATTR);
}
});
nextRequest();
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
assertThat(wrappedRequest.getSession().getValue(ATTR)).isEqualTo(VALUE);
assertThat(Arrays.asList(wrappedRequest.getSession().getValueNames())).containsOnly(ATTR);
}
});
nextRequest();
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
assertThat(wrappedRequest.getSession().getValue(ATTR)).isEqualTo(VALUE);
wrappedRequest.getSession().removeValue(ATTR);
assertThat(wrappedRequest.getSession().getValue(ATTR)).isNull();
}
});
nextRequest();
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
assertThat(wrappedRequest.getSession().getValue(ATTR)).isNull();
}
});
}
@Test
void doFilterIsNewTrue() throws Exception {
doFilter(new DoInFilter() {
@@ -636,27 +588,6 @@ class SessionRepositoryFilterTests {
assertThat(session.getSecure()).describedAs("Session Cookie should be marked as Secure").isTrue();
}
@Test
void doFilterSessionContext() throws Exception {
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
HttpSessionContext sessionContext = wrappedRequest.getSession().getSessionContext();
assertThat(sessionContext).isNotNull();
assertThat(sessionContext.getSession("a")).isNull();
assertThat(sessionContext.getIds()).isNotNull();
assertThat(sessionContext.getIds().hasMoreElements()).isFalse();
try {
sessionContext.getIds().nextElement();
fail("Expected Exception");
}
catch (NoSuchElementException ignored) {
}
}
});
}
// --- saving
@Test
@@ -740,23 +671,6 @@ class SessionRepositoryFilterTests {
});
}
@Test
void doFilterInvalidateValueIllegalState() throws Exception {
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
HttpSession session = wrappedRequest.getSession();
session.invalidate();
try {
session.getValue("attr");
fail("Expected Exception");
}
catch (IllegalStateException ignored) {
}
}
});
}
@Test
void doFilterInvalidateAttributeNamesIllegalState() throws Exception {
doFilter(new DoInFilter() {
@@ -774,23 +688,6 @@ class SessionRepositoryFilterTests {
});
}
@Test
void doFilterInvalidateValueNamesIllegalState() throws Exception {
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
HttpSession session = wrappedRequest.getSession();
session.invalidate();
try {
session.getValueNames();
fail("Expected Exception");
}
catch (IllegalStateException ignored) {
}
}
});
}
@Test
void doFilterInvalidateSetAttributeIllegalState() throws Exception {
doFilter(new DoInFilter() {
@@ -808,23 +705,6 @@ class SessionRepositoryFilterTests {
});
}
@Test
void doFilterInvalidatePutValueIllegalState() throws Exception {
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
HttpSession session = wrappedRequest.getSession();
session.invalidate();
try {
session.putValue("a", "b");
fail("Expected Exception");
}
catch (IllegalStateException ignored) {
}
}
});
}
@Test
void doFilterInvalidateRemoveAttributeIllegalState() throws Exception {
doFilter(new DoInFilter() {
@@ -842,23 +722,6 @@ class SessionRepositoryFilterTests {
});
}
@Test
void doFilterInvalidateRemoveValueIllegalState() throws Exception {
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
HttpSession session = wrappedRequest.getSession();
session.invalidate();
try {
session.removeValue("name");
fail("Expected Exception");
}
catch (IllegalStateException ignored) {
}
}
});
}
@Test
void doFilterInvalidateNewIllegalState() throws Exception {
doFilter(new DoInFilter() {
@@ -920,20 +783,6 @@ class SessionRepositoryFilterTests {
});
}
@Test
void doFilterInvalidateSessionContext() throws Exception {
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
HttpSession session = wrappedRequest.getSession();
session.invalidate();
// no exception
session.getSessionContext();
}
});
}
@Test
void doFilterInvalidateMaxInteractiveInterval() throws Exception {
doFilter(new DoInFilter() {
@@ -1326,8 +1175,8 @@ class SessionRepositoryFilterTests {
}
});
// 3 invocations expected: initial resolution, after invalidation, after commit
verify(sessionRepository, times(3)).findById(eq(session.getId()));
// 2 invocations expected: initial resolution, after invalidation
verify(sessionRepository, times(2)).findById(eq(session.getId()));
verify(sessionRepository).deleteById(eq(session.getId()));
verify(sessionRepository).createSession();
verify(sessionRepository).save(any());
@@ -1338,8 +1187,9 @@ class SessionRepositoryFilterTests {
@Test
void order() {
assertThat(AnnotationAwareOrderComparator.INSTANCE.compare(this.filter,
new SessionRepositoryFilterDefaultOrder()));
assertThat(
AnnotationAwareOrderComparator.INSTANCE.compare(this.filter, new SessionRepositoryFilterDefaultOrder()))
.isZero();
}
// We want the filter to work without any dependencies on Spring
@@ -1551,7 +1401,7 @@ class SessionRepositoryFilterTests {
}
private abstract class DoInFilter {
private abstract static class DoInFilter {
void doFilter(HttpServletRequest wrappedRequest, HttpServletResponse wrappedResponse)
throws ServletException, IOException {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -23,8 +23,9 @@ import java.util.Set;
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.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Mono;
import org.springframework.session.ReactiveSessionRepository;
@@ -43,9 +44,10 @@ import static org.mockito.Mockito.verify;
* @author Rob Winch
* @author Vedran Pavic
*/
@ExtendWith(MockitoExtension.class)
class SpringSessionWebSessionStoreTests<S extends Session> {
@Mock
@Mock(lenient = true)
private ReactiveSessionRepository<S> sessionRepository;
@Mock
@@ -58,7 +60,6 @@ class SpringSessionWebSessionStoreTests<S extends Session> {
@BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
this.webSessionStore = new SpringSessionWebSessionStore<>(this.sessionRepository);
given(this.sessionRepository.findById(any())).willReturn(Mono.just(this.findByIdSession));
given(this.sessionRepository.createSession()).willReturn(Mono.just(this.createSession));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -18,10 +18,11 @@ package org.springframework.session.web.socket.handler;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
@@ -35,6 +36,7 @@ import static org.mockito.BDDMockito.willThrow;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
class WebSocketConnectHandlerDecoratorFactoryTests {
@Mock
@@ -53,7 +55,6 @@ class WebSocketConnectHandlerDecoratorFactoryTests {
@BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
this.factory = new WebSocketConnectHandlerDecoratorFactory(this.eventPublisher);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -22,8 +22,9 @@ import java.util.Map;
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.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
@@ -44,15 +45,16 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
class WebSocketRegistryListenerTests {
@Mock
@Mock(lenient = true)
private WebSocketSession wsSession;
@Mock
@Mock(lenient = true)
private WebSocketSession wsSession2;
@Mock
@Mock(lenient = true)
private Message<byte[]> message;
@Mock
@@ -74,7 +76,6 @@ class WebSocketRegistryListenerTests {
@BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
String sessionId = "session-id";
MapSession session = new MapSession(sessionId);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -27,9 +27,10 @@ import jakarta.servlet.http.HttpSession;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.messaging.Message;
@@ -51,9 +52,10 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@ExtendWith(MockitoExtension.class)
class SessionRepositoryMessageInterceptorTests {
@Mock
@Mock(lenient = true)
SessionRepository<Session> sessionRepository;
@Mock
@@ -70,7 +72,6 @@ class SessionRepositoryMessageInterceptorTests {
@BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
this.interceptor = new SessionRepositoryMessageInterceptor<>(this.sessionRepository);
this.headers = SimpMessageHeaderAccessor.create();
this.headers.setSessionId("session");

View File

@@ -18,6 +18,8 @@ dependencies {
optional "org.mongodb:mongodb-driver-core"
testImplementation "org.mongodb:mongodb-driver-sync"
testImplementation "org.mongodb:mongodb-driver-reactivestreams"
testImplementation 'jakarta.websocket:jakarta.websocket-api'
testImplementation 'jakarta.websocket:jakarta.websocket-client-api'
integrationTestCompile "org.testcontainers:mongodb"
// Everything else

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2018 the original author or authors.
* Copyright 2014-2022 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.session.data.mongo.integration;
package org.springframework.session.data.mongo;
import java.lang.reflect.Field;
@@ -25,9 +25,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.serializer.DefaultDeserializer;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
import org.springframework.session.data.mongo.Assert;
import org.springframework.session.data.mongo.JdkMongoSessionConverter;
import org.springframework.util.ReflectionUtils;
/**
@@ -49,8 +46,7 @@ public abstract class AbstractClassLoaderTest<T> extends AbstractITest {
Field mongoSessionConverterField = ReflectionUtils.findField(this.sessionRepository.getClass(),
"mongoSessionConverter");
ReflectionUtils.makeAccessible(
Assert.requireNonNull(mongoSessionConverterField, "mongoSessionConverter must not be null!"));
ReflectionUtils.makeAccessible(mongoSessionConverterField);
AbstractMongoSessionConverter sessionConverter = (AbstractMongoSessionConverter) ReflectionUtils
.getField(mongoSessionConverterField, this.sessionRepository);
@@ -70,7 +66,7 @@ public abstract class AbstractClassLoaderTest<T> extends AbstractITest {
private static Object extractField(Class<?> clazz, String fieldName, Object obj) {
Field field = ReflectionUtils.findField(clazz, fieldName);
ReflectionUtils.makeAccessible(Assert.requireNonNull(field, fieldName + " must not be null!"));
ReflectionUtils.makeAccessible(field);
return ReflectionUtils.getField(field, obj);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2022 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.session.data.mongo.integration;
package org.springframework.session.data.mongo;
import java.util.UUID;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2022 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.session.data.mongo.integration;
package org.springframework.session.data.mongo;
import java.time.Duration;
import java.time.Instant;
@@ -37,8 +37,6 @@ import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
import org.springframework.session.data.mongo.MongoSession;
import static org.assertj.core.api.Assertions.assertThat;
@@ -389,18 +387,20 @@ public abstract class AbstractMongoRepositoryITest extends AbstractITest {
protected static class BaseConfig {
private static final String DOCKER_IMAGE = "mongo:4.0.10";
private static final String DOCKER_IMAGE = "mongo:5.0.11";
@Bean(initMethod = "start", destroyMethod = "stop")
public MongoDBContainer mongoContainer() {
return new MongoDBContainer(DOCKER_IMAGE).withExposedPorts(27017);
@Bean
public MongoDBContainer mongoDbContainer() {
MongoDBContainer mongoDbContainer = new MongoDBContainer(DOCKER_IMAGE);
mongoDbContainer.start();
return mongoDbContainer;
}
@Bean
public MongoOperations mongoOperations(MongoDBContainer mongoContainer) {
MongoClient mongo = MongoClients.create(
"mongodb://" + mongoContainer.getContainerIpAddress() + ":" + mongoContainer.getFirstMappedPort());
MongoClient mongo = MongoClients
.create("mongodb://" + mongoContainer.getHost() + ":" + mongoContainer.getFirstMappedPort());
return new MongoTemplate(mongo, "test");
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.session.data.mongo.integration;
package org.springframework.session.data.mongo;
import java.net.URI;
@@ -41,8 +41,6 @@ import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
import org.springframework.session.data.mongo.JacksonMongoSessionConverter;
import org.springframework.session.data.mongo.config.annotation.web.reactive.EnableMongoWebSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -137,6 +135,7 @@ public class MongoDbDeleteJacksonSessionVerificationTest {
}
@Configuration(proxyBeanMethods = false)
@EnableWebFluxSecurity
static class SecurityConfig {
@@ -156,9 +155,8 @@ public class MongoDbDeleteJacksonSessionVerificationTest {
@Bean
MapReactiveUserDetailsService userDetailsService() {
return new MapReactiveUserDetailsService(User.withDefaultPasswordEncoder() //
.username("admin") //
.password("password") //
return new MapReactiveUserDetailsService(User.withUsername("admin") //
.password("{noop}password") //
.roles("USER,ADMIN") //
.build());
}
@@ -175,18 +173,20 @@ public class MongoDbDeleteJacksonSessionVerificationTest {
@EnableMongoWebSession
static class Config {
private static final String DOCKER_IMAGE = "mongo:4.0.10";
private static final String DOCKER_IMAGE = "mongo:5.0.11";
@Bean(initMethod = "start", destroyMethod = "stop")
MongoDBContainer mongoContainer() {
return new MongoDBContainer(DOCKER_IMAGE).withExposedPorts(27017);
@Bean
MongoDBContainer mongoDbContainer() {
MongoDBContainer mongoDbContainer = new MongoDBContainer(DOCKER_IMAGE);
mongoDbContainer.start();
return mongoDbContainer;
}
@Bean
ReactiveMongoOperations mongoOperations(MongoDBContainer mongoContainer) {
MongoClient mongo = MongoClients.create(
"mongodb://" + mongoContainer.getContainerIpAddress() + ":" + mongoContainer.getFirstMappedPort());
MongoClient mongo = MongoClients
.create("mongodb://" + mongoContainer.getHost() + ":" + mongoContainer.getFirstMappedPort());
return new ReactiveMongoTemplate(mongo, "DB_Name_DeleteJacksonSessionVerificationTest");
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.session.data.mongo.integration;
package org.springframework.session.data.mongo;
import java.net.URI;
@@ -135,6 +135,7 @@ public class MongoDbLogoutVerificationTest {
}
@Configuration(proxyBeanMethods = false)
@EnableWebFluxSecurity
static class SecurityConfig {
@@ -156,9 +157,8 @@ public class MongoDbLogoutVerificationTest {
@Bean
MapReactiveUserDetailsService userDetailsService() {
return new MapReactiveUserDetailsService(User.withDefaultPasswordEncoder() //
.username("admin") //
.password("password") //
return new MapReactiveUserDetailsService(User.withUsername("admin") //
.password("{noop}password") //
.roles("USER,ADMIN") //
.build());
}
@@ -170,18 +170,20 @@ public class MongoDbLogoutVerificationTest {
@EnableMongoWebSession
static class Config {
private static final String DOCKER_IMAGE = "mongo:4.0.10";
private static final String DOCKER_IMAGE = "mongo:5.0.11";
@Bean(initMethod = "start", destroyMethod = "stop")
MongoDBContainer mongoContainer() {
return new MongoDBContainer(DOCKER_IMAGE).withExposedPorts(27017);
@Bean
MongoDBContainer mongoDbContainer() {
MongoDBContainer mongoDbContainer = new MongoDBContainer(DOCKER_IMAGE);
mongoDbContainer.start();
return mongoDbContainer;
}
@Bean
ReactiveMongoOperations mongoOperations(MongoDBContainer mongoContainer) {
MongoClient mongo = MongoClients.create(
"mongodb://" + mongoContainer.getContainerIpAddress() + ":" + mongoContainer.getFirstMappedPort());
MongoClient mongo = MongoClients
.create("mongodb://" + mongoContainer.getHost() + ":" + mongoContainer.getFirstMappedPort());
return new ReactiveMongoTemplate(mongo, "test");
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2022 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.session.data.mongo.integration;
package org.springframework.session.data.mongo;
import java.util.Collections;
import java.util.Map;
@@ -25,9 +25,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.geo.GeoModule;
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
import org.springframework.session.data.mongo.JacksonMongoSessionConverter;
import org.springframework.session.data.mongo.MongoSession;
import org.springframework.session.data.mongo.config.annotation.web.http.EnableMongoHttpSession;
import org.springframework.test.context.ContextConfiguration;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2022 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.session.data.mongo.integration;
package org.springframework.session.data.mongo;
import java.time.Duration;
import java.util.Map;
@@ -23,9 +23,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
import org.springframework.session.data.mongo.JdkMongoSessionConverter;
import org.springframework.session.data.mongo.MongoSession;
import org.springframework.session.data.mongo.config.annotation.web.http.EnableMongoHttpSession;
import org.springframework.test.context.ContextConfiguration;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2022 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.
@@ -36,6 +36,8 @@ import org.springframework.session.DelegatingIndexResolver;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.IndexResolver;
import org.springframework.session.PrincipalNameIndexResolver;
import org.springframework.session.Session;
import org.springframework.util.Assert;
/**
* Base class for serializing and deserializing session objects. To create custom
@@ -54,8 +56,7 @@ public abstract class AbstractMongoSessionConverter implements GenericConverter
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private IndexResolver<MongoSession> indexResolver = new DelegatingIndexResolver<>(
new PrincipalNameIndexResolver<>());
private IndexResolver<Session> indexResolver = new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>());
/**
* Returns query to be executed to return sessions based on a particular index.
@@ -122,8 +123,9 @@ public abstract class AbstractMongoSessionConverter implements GenericConverter
protected abstract MongoSession convert(Document sessionWrapper);
public void setIndexResolver(IndexResolver<MongoSession> indexResolver) {
this.indexResolver = Assert.requireNonNull(indexResolver, "indexResolver must not be null!");
public void setIndexResolver(IndexResolver<Session> indexResolver) {
Assert.notNull(indexResolver, "indexResolver must not be null");
this.indexResolver = indexResolver;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2022 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.
@@ -29,7 +29,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.apache.commons.logging.Log;
@@ -168,18 +168,18 @@ public class JacksonMongoSessionConverter extends AbstractMongoSessionConverter
}
private static class MongoIdNamingStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase {
private static class MongoIdNamingStrategy extends PropertyNamingStrategies.NamingBase {
@Override
public String translate(String propertyName) {
switch (propertyName) {
case "id":
return "_id";
case "_id":
return "id";
default:
return propertyName;
case "id":
return "_id";
case "_id":
return "id";
default:
return propertyName;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -22,6 +22,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import com.mongodb.DBObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bson.Document;
@@ -34,9 +35,11 @@ import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.lang.Nullable;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.MapSession;
import org.springframework.session.events.SessionCreatedEvent;
import org.springframework.session.events.SessionDeletedEvent;
import org.springframework.session.events.SessionExpiredEvent;
import org.springframework.util.Assert;
/**
* Session repository implementation which stores sessions in Mongo. Uses
@@ -46,6 +49,7 @@ import org.springframework.session.events.SessionExpiredEvent;
*
* @author Jakub Kubrynski
* @author Greg Turnquist
* @author Vedran Pavic
* @since 2.2.0
*/
public class MongoIndexedSessionRepository
@@ -53,8 +57,11 @@ public class MongoIndexedSessionRepository
/**
* The default time period in seconds in which a session will expire.
* @deprecated since 3.0.0 in favor of
* {@link MapSession#DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS}
*/
public static final int DEFAULT_INACTIVE_INTERVAL = 1800;
@Deprecated
public static final int DEFAULT_INACTIVE_INTERVAL = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
/**
* the default collection name for storing session.
@@ -65,12 +72,12 @@ public class MongoIndexedSessionRepository
private final MongoOperations mongoOperations;
private Integer maxInactiveIntervalInSeconds = DEFAULT_INACTIVE_INTERVAL;
private Duration defaultMaxInactiveInterval = Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
private String collectionName = DEFAULT_COLLECTION_NAME;
private AbstractMongoSessionConverter mongoSessionConverter = new JdkMongoSessionConverter(
Duration.ofSeconds(this.maxInactiveIntervalInSeconds));
this.defaultMaxInactiveInterval);
private ApplicationEventPublisher eventPublisher;
@@ -83,9 +90,7 @@ public class MongoIndexedSessionRepository
MongoSession session = new MongoSession();
if (this.maxInactiveIntervalInSeconds != null) {
session.setMaxInactiveInterval(Duration.ofSeconds(this.maxInactiveIntervalInSeconds));
}
session.setMaxInactiveInterval(this.defaultMaxInactiveInterval);
publishEvent(new SessionCreatedEvent(this, session));
@@ -94,9 +99,9 @@ public class MongoIndexedSessionRepository
@Override
public void save(MongoSession session) {
this.mongoOperations
.save(Assert.requireNonNull(MongoSessionUtils.convertToDBObject(this.mongoSessionConverter, session),
"convertToDBObject must not null!"), this.collectionName);
DBObject dbObject = MongoSessionUtils.convertToDBObject(this.mongoSessionConverter, session);
Assert.notNull(dbObject, "dbObject must not be null");
this.mongoOperations.save(dbObject, this.collectionName);
}
@Override
@@ -178,8 +183,29 @@ public class MongoIndexedSessionRepository
}
}
public void setMaxInactiveIntervalInSeconds(final Integer maxInactiveIntervalInSeconds) {
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
/**
* Set the maximum inactive interval in seconds between requests before newly created
* sessions will be invalidated. A negative time indicates that the session will never
* time out. The default is 30 minutes.
* @param defaultMaxInactiveInterval the default maxInactiveInterval
*/
public void setDefaultMaxInactiveInterval(Duration defaultMaxInactiveInterval) {
org.springframework.util.Assert.notNull(defaultMaxInactiveInterval,
"defaultMaxInactiveInterval must not be null");
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
}
/**
* Set the maximum inactive interval in seconds between requests before newly created
* sessions will be invalidated. A negative time indicates that the session will never
* time out. The default is 1800 (30 minutes).
* @param defaultMaxInactiveInterval the default maxInactiveInterval in seconds
* @deprecated since 3.0.0, in favor of
* {@link #setDefaultMaxInactiveInterval(Duration)}
*/
@Deprecated(since = "3.0.0")
public void setMaxInactiveIntervalInSeconds(Integer defaultMaxInactiveInterval) {
setDefaultMaxInactiveInterval(Duration.ofSeconds(defaultMaxInactiveInterval));
}
public void setCollectionName(final String collectionName) {

View File

@@ -1,36 +0,0 @@
/*
* 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 org.springframework.data.mongodb.core.MongoOperations;
/**
* This {@link org.springframework.session.FindByIndexNameSessionRepository}
* implementation is kept to support backwards compatibility.
*
* @author Rob Winch
* @since 1.2
* @deprecated since 2.2.0 in favor of {@link MongoIndexedSessionRepository}.
*/
@Deprecated
public class MongoOperationsSessionRepository extends MongoIndexedSessionRepository {
public MongoOperationsSessionRepository(MongoOperations mongoOperations) {
super(mongoOperations);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2022 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.
@@ -27,6 +27,7 @@ import java.util.UUID;
import java.util.stream.Collectors;
import org.springframework.lang.Nullable;
import org.springframework.session.MapSession;
import org.springframework.session.Session;
/**
@@ -36,13 +37,20 @@ import org.springframework.session.Session;
* @author Greg Turnquist
* @since 1.2
*/
public class MongoSession implements Session {
class MongoSession implements Session {
/**
* Mongo doesn't support {@literal dot} in field names. We replace it with a very
* rarely used character
* Mongo doesn't support {@literal dot} in field names. We replace it with a unicode
* character from the Private Use Area.
* <p>
* NOTE: This was originally stored in unicode format. Delomboking the code caused it
* to get converted to another encoding, which isn't supported on all systems, so we
* migrated back to unicode. The same character is being represented ensuring binary
* compatibility.
*
* See https://www.compart.com/en/unicode/U+F607
*/
private static final char DOT_COVER_CHAR = '';
private static final char DOT_COVER_CHAR = '\uF607';
private String id;
@@ -58,15 +66,15 @@ public class MongoSession implements Session {
private Map<String, Object> attrs = new HashMap<>();
public MongoSession() {
this(MongoIndexedSessionRepository.DEFAULT_INACTIVE_INTERVAL);
MongoSession() {
this(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
}
public MongoSession(long maxInactiveIntervalInSeconds) {
MongoSession(long maxInactiveIntervalInSeconds) {
this(UUID.randomUUID().toString(), maxInactiveIntervalInSeconds);
}
public MongoSession(String id, long maxInactiveIntervalInSeconds) {
MongoSession(String id, long maxInactiveIntervalInSeconds) {
this.id = id;
this.originalSessionId = id;
@@ -122,7 +130,7 @@ public class MongoSession implements Session {
return Instant.ofEpochMilli(this.createdMillis);
}
public void setCreationTime(long created) {
void setCreationTime(long created) {
this.createdMillis = created;
}
@@ -176,11 +184,11 @@ public class MongoSession implements Session {
return this.id;
}
public Date getExpireAt() {
Date getExpireAt() {
return this.expireAt;
}
public void setExpireAt(final Date expireAt) {
void setExpireAt(final Date expireAt) {
this.expireAt = expireAt;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2014-2022 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.
@@ -27,7 +27,7 @@ import org.springframework.lang.Nullable;
*
* @author Greg Turnquist
*/
public final class MongoSessionUtils {
final class MongoSessionUtils {
private MongoSessionUtils() {
}

View File

@@ -1,36 +0,0 @@
/*
* 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 org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.session.ReactiveSessionRepository;
/**
* This {@link ReactiveSessionRepository} implementation is kept to support migration to
* {@link ReactiveMongoSessionRepository} in a backwards compatible manner.
*
* @author Greg Turnquist
* @deprecated since 2.2.0 in favor of {@link ReactiveMongoSessionRepository}.
*/
@Deprecated
public class ReactiveMongoOperationsSessionRepository extends ReactiveMongoSessionRepository {
public ReactiveMongoOperationsSessionRepository(ReactiveMongoOperations mongoOperations) {
super(mongoOperations);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -32,14 +32,17 @@ import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.session.MapSession;
import org.springframework.session.ReactiveSessionRepository;
import org.springframework.session.events.SessionCreatedEvent;
import org.springframework.session.events.SessionDeletedEvent;
import org.springframework.util.Assert;
/**
* A {@link ReactiveSessionRepository} implementation that uses Spring Data MongoDB.
*
* @author Greg Turnquist
* @author Vedran Pavic
* @since 2.2.0
*/
public class ReactiveMongoSessionRepository
@@ -47,8 +50,11 @@ public class ReactiveMongoSessionRepository
/**
* The default time period in seconds in which a session will expire.
* @deprecated since 3.0.0 in favor of
* {@link MapSession#DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS}
*/
public static final int DEFAULT_INACTIVE_INTERVAL = 1800;
@Deprecated
public static final int DEFAULT_INACTIVE_INTERVAL = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
/**
* The default collection name for storing session.
@@ -59,12 +65,12 @@ public class ReactiveMongoSessionRepository
private final ReactiveMongoOperations mongoOperations;
private Integer maxInactiveIntervalInSeconds = DEFAULT_INACTIVE_INTERVAL;
private Duration defaultMaxInactiveInterval = Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
private String collectionName = DEFAULT_COLLECTION_NAME;
private AbstractMongoSessionConverter mongoSessionConverter = new JdkMongoSessionConverter(
Duration.ofSeconds(this.maxInactiveIntervalInSeconds));
this.defaultMaxInactiveInterval);
private MongoOperations blockingMongoOperations;
@@ -88,7 +94,7 @@ public class ReactiveMongoSessionRepository
@Override
public Mono<MongoSession> createSession() {
return Mono.justOrEmpty(this.maxInactiveIntervalInSeconds) //
return Mono.justOrEmpty(this.defaultMaxInactiveInterval.toSeconds()) //
.map(MongoSession::new) //
.doOnNext((mongoSession) -> publishEvent(new SessionCreatedEvent(this, mongoSession))) //
.switchIfEmpty(Mono.just(new MongoSession()));
@@ -170,12 +176,28 @@ public class ReactiveMongoSessionRepository
}
}
public Integer getMaxInactiveIntervalInSeconds() {
return this.maxInactiveIntervalInSeconds;
/**
* Set the maximum inactive interval in seconds between requests before newly created
* sessions will be invalidated. A negative time indicates that the session will never
* time out. The default is 30 minutes.
* @param defaultMaxInactiveInterval the default maxInactiveInterval
*/
public void setDefaultMaxInactiveInterval(Duration defaultMaxInactiveInterval) {
Assert.notNull(defaultMaxInactiveInterval, "defaultMaxInactiveInterval must not be null");
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
}
public void setMaxInactiveIntervalInSeconds(final Integer maxInactiveIntervalInSeconds) {
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
/**
* Set the maximum inactive interval in seconds between requests before newly created
* sessions will be invalidated. A negative time indicates that the session will never
* time out. The default is 1800 (30 minutes).
* @param defaultMaxInactiveInterval the default maxInactiveInterval in seconds
* @deprecated since 3.0.0, in favor of
* {@link #setDefaultMaxInactiveInterval(Duration)}
*/
@Deprecated(since = "3.0.0")
public void setMaxInactiveIntervalInSeconds(Integer defaultMaxInactiveInterval) {
setDefaultMaxInactiveInterval(Duration.ofSeconds(defaultMaxInactiveInterval));
}
public String getCollectionName() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2022 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.
@@ -22,8 +22,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.session.MapSession;
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
/**
@@ -34,6 +34,7 @@ import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
*
* <pre>
* <code>
* {@literal @Configuration(proxyBeanMethods = false)}
* {@literal @EnableMongoHttpSession}
* public class MongoHttpSessionConfig {
*
@@ -52,14 +53,13 @@ import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
@Target(ElementType.TYPE)
@Documented
@Import(MongoHttpSessionConfiguration.class)
@Configuration(proxyBeanMethods = false)
public @interface EnableMongoHttpSession {
/**
* The maximum time a session will be kept if it is inactive.
* @return default max inactive interval in seconds
*/
int maxInactiveIntervalInSeconds() default MongoIndexedSessionRepository.DEFAULT_INACTIVE_INTERVAL;
int maxInactiveIntervalInSeconds() default MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
/**
* The collection name to use.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2022 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.
@@ -26,6 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportAware;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.serializer.support.DeserializingConverter;
@@ -33,12 +34,13 @@ import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.session.IndexResolver;
import org.springframework.session.MapSession;
import org.springframework.session.Session;
import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
import org.springframework.session.data.mongo.JdkMongoSessionConverter;
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
import org.springframework.session.data.mongo.MongoSession;
import org.springframework.util.StringUtils;
import org.springframework.util.StringValueResolver;
@@ -51,12 +53,12 @@ import org.springframework.util.StringValueResolver;
* @since 1.2
*/
@Configuration(proxyBeanMethods = false)
public class MongoHttpSessionConfiguration extends SpringHttpSessionConfiguration
implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware {
@Import(SpringHttpSessionConfiguration.class)
public class MongoHttpSessionConfiguration implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware {
private AbstractMongoSessionConverter mongoSessionConverter;
private Integer maxInactiveIntervalInSeconds;
private Duration maxInactiveInterval = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL;
private String collectionName;
@@ -66,13 +68,13 @@ public class MongoHttpSessionConfiguration extends SpringHttpSessionConfiguratio
private ClassLoader classLoader;
private IndexResolver<MongoSession> indexResolver;
private IndexResolver<Session> indexResolver;
@Bean
public MongoIndexedSessionRepository mongoSessionRepository(MongoOperations mongoOperations) {
MongoIndexedSessionRepository repository = new MongoIndexedSessionRepository(mongoOperations);
repository.setMaxInactiveIntervalInSeconds(this.maxInactiveIntervalInSeconds);
repository.setDefaultMaxInactiveInterval(this.maxInactiveInterval);
if (this.mongoSessionConverter != null) {
repository.setMongoSessionConverter(this.mongoSessionConverter);
@@ -84,7 +86,7 @@ public class MongoHttpSessionConfiguration extends SpringHttpSessionConfiguratio
else {
JdkMongoSessionConverter mongoSessionConverter = new JdkMongoSessionConverter(new SerializingConverter(),
new DeserializingConverter(this.classLoader),
Duration.ofSeconds(MongoIndexedSessionRepository.DEFAULT_INACTIVE_INTERVAL));
Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
if (this.indexResolver != null) {
mongoSessionConverter.setIndexResolver(this.indexResolver);
@@ -107,8 +109,13 @@ public class MongoHttpSessionConfiguration extends SpringHttpSessionConfiguratio
this.collectionName = collectionName;
}
public void setMaxInactiveInterval(Duration maxInactiveInterval) {
this.maxInactiveInterval = maxInactiveInterval;
}
@Deprecated
public void setMaxInactiveIntervalInSeconds(Integer maxInactiveIntervalInSeconds) {
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
setMaxInactiveInterval(Duration.ofSeconds(maxInactiveIntervalInSeconds));
}
public void setImportMetadata(AnnotationMetadata importMetadata) {
@@ -117,10 +124,8 @@ public class MongoHttpSessionConfiguration extends SpringHttpSessionConfiguratio
.fromMap(importMetadata.getAnnotationAttributes(EnableMongoHttpSession.class.getName()));
if (attributes != null) {
this.maxInactiveIntervalInSeconds = attributes.getNumber("maxInactiveIntervalInSeconds");
}
else {
this.maxInactiveIntervalInSeconds = MongoIndexedSessionRepository.DEFAULT_INACTIVE_INTERVAL;
this.maxInactiveInterval = Duration
.ofSeconds(attributes.<Integer>getNumber("maxInactiveIntervalInSeconds"));
}
String collectionNameValue = (attributes != null) ? attributes.getString("collectionName") : "";
@@ -151,7 +156,7 @@ public class MongoHttpSessionConfiguration extends SpringHttpSessionConfiguratio
}
@Autowired(required = false)
public void setIndexResolver(IndexResolver<MongoSession> indexResolver) {
public void setIndexResolver(IndexResolver<Session> indexResolver) {
this.indexResolver = indexResolver;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2014-2022 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.
@@ -20,8 +20,8 @@ import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.session.MapSession;
import org.springframework.session.data.mongo.ReactiveMongoSessionRepository;
/**
@@ -32,7 +32,7 @@ import org.springframework.session.data.mongo.ReactiveMongoSessionRepository;
*
* <pre>
* <code>
* {@literal @Configuration}
* {@literal @Configuration(proxyBeanMethods = false)}
* {@literal @EnableMongoWebSession}
* public class SpringWebFluxConfig {
*
@@ -45,21 +45,20 @@ import org.springframework.session.data.mongo.ReactiveMongoSessionRepository;
* </code> </pre>
*
* @author Greg Turnquist
* @author Vedran Pavić
* @author Vedran Pavic
* @since 2.0
*/
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({ java.lang.annotation.ElementType.TYPE })
@Documented
@Import(ReactiveMongoWebSessionConfiguration.class)
@Configuration(proxyBeanMethods = false)
public @interface EnableMongoWebSession {
/**
* The maximum time a session will be kept if it is inactive.
* @return default max inactive interval in seconds
*/
int maxInactiveIntervalInSeconds() default ReactiveMongoSessionRepository.DEFAULT_INACTIVE_INTERVAL;
int maxInactiveIntervalInSeconds() default MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
/**
* The collection name to use.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2016-2022 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.
@@ -26,6 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportAware;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.serializer.support.DeserializingConverter;
@@ -34,11 +35,12 @@ import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.session.IndexResolver;
import org.springframework.session.MapSession;
import org.springframework.session.Session;
import org.springframework.session.config.ReactiveSessionRepositoryCustomizer;
import org.springframework.session.config.annotation.web.server.SpringWebSessionConfiguration;
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
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.StringUtils;
import org.springframework.util.StringValueResolver;
@@ -48,15 +50,16 @@ import org.springframework.util.StringValueResolver;
* {@link ReactiveMongoOperations}.
*
* @author Greg Turnquist
* @author Vedran Pavić
* @author Vedran Pavic
*/
@Configuration(proxyBeanMethods = false)
public class ReactiveMongoWebSessionConfiguration extends SpringWebSessionConfiguration
@Import(SpringWebSessionConfiguration.class)
public class ReactiveMongoWebSessionConfiguration
implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware {
private AbstractMongoSessionConverter mongoSessionConverter;
private Integer maxInactiveIntervalInSeconds;
private Duration maxInactiveInterval = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL;
private String collectionName;
@@ -69,7 +72,7 @@ public class ReactiveMongoWebSessionConfiguration extends SpringWebSessionConfig
private ClassLoader classLoader;
private IndexResolver<MongoSession> indexResolver;
private IndexResolver<Session> indexResolver;
@Bean
public ReactiveMongoSessionRepository reactiveMongoSessionRepository(ReactiveMongoOperations operations) {
@@ -87,7 +90,7 @@ public class ReactiveMongoWebSessionConfiguration extends SpringWebSessionConfig
else {
JdkMongoSessionConverter mongoSessionConverter = new JdkMongoSessionConverter(new SerializingConverter(),
new DeserializingConverter(this.classLoader),
Duration.ofSeconds(ReactiveMongoSessionRepository.DEFAULT_INACTIVE_INTERVAL));
Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
if (this.indexResolver != null) {
mongoSessionConverter.setIndexResolver(this.indexResolver);
@@ -96,9 +99,7 @@ public class ReactiveMongoWebSessionConfiguration extends SpringWebSessionConfig
repository.setMongoSessionConverter(mongoSessionConverter);
}
if (this.maxInactiveIntervalInSeconds != null) {
repository.setMaxInactiveIntervalInSeconds(this.maxInactiveIntervalInSeconds);
}
repository.setDefaultMaxInactiveInterval(this.maxInactiveInterval);
if (this.collectionName != null) {
repository.setCollectionName(this.collectionName);
@@ -126,10 +127,8 @@ public class ReactiveMongoWebSessionConfiguration extends SpringWebSessionConfig
.fromMap(importMetadata.getAnnotationAttributes(EnableMongoWebSession.class.getName()));
if (attributes != null) {
this.maxInactiveIntervalInSeconds = attributes.getNumber("maxInactiveIntervalInSeconds");
}
else {
this.maxInactiveIntervalInSeconds = ReactiveMongoSessionRepository.DEFAULT_INACTIVE_INTERVAL;
this.maxInactiveInterval = Duration
.ofSeconds(attributes.<Integer>getNumber("maxInactiveIntervalInSeconds"));
}
String collectionNameValue = (attributes != null) ? attributes.getString("collectionName") : "";
@@ -149,12 +148,17 @@ public class ReactiveMongoWebSessionConfiguration extends SpringWebSessionConfig
this.embeddedValueResolver = embeddedValueResolver;
}
public Integer getMaxInactiveIntervalInSeconds() {
return this.maxInactiveIntervalInSeconds;
public Duration getMaxInactiveInterval() {
return this.maxInactiveInterval;
}
public void setMaxInactiveInterval(Duration maxInactiveInterval) {
this.maxInactiveInterval = maxInactiveInterval;
}
@Deprecated
public void setMaxInactiveIntervalInSeconds(Integer maxInactiveIntervalInSeconds) {
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
setMaxInactiveInterval(Duration.ofSeconds(maxInactiveIntervalInSeconds));
}
public String getCollectionName() {
@@ -172,7 +176,7 @@ public class ReactiveMongoWebSessionConfiguration extends SpringWebSessionConfig
}
@Autowired(required = false)
public void setIndexResolver(IndexResolver<MongoSession> indexResolver) {
public void setIndexResolver(IndexResolver<Session> indexResolver) {
this.indexResolver = indexResolver;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2014-2022 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.
@@ -49,7 +49,7 @@ public abstract class AbstractMongoSessionConverterTest {
MongoSession deserialized = convertToSession(dbObject);
// then
assertThat(deserialized).isEqualToComparingFieldByField(toSerialize);
assertThat(deserialized).usingRecursiveComparison().isEqualTo(toSerialize);
}
@Test
@@ -67,14 +67,12 @@ public abstract class AbstractMongoSessionConverterTest {
MongoSession deserialized = convertToSession(serialized);
// then
assertThat(deserialized).isEqualToComparingOnlyGivenFields(toSerialize, "id", "createdMillis", "accessedMillis",
"intervalSeconds", "expireAt");
assertThat(deserialized).usingRecursiveComparison().isEqualTo(toSerialize);
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(springSecurityContextBefore).usingRecursiveComparison().isEqualTo(springSecurityContextAfter);
assertThat(springSecurityContextAfter.getAuthentication().getPrincipal()).isEqualTo("john_the_springer");
assertThat(springSecurityContextAfter.getAuthentication().getCredentials()).isNull();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2022 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.
@@ -33,6 +33,7 @@ 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 org.springframework.session.MapSession;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -76,20 +77,7 @@ public class MongoIndexedSessionRepositoryTest {
// 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);
.isEqualTo(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
}
@Test
@@ -164,8 +152,7 @@ public class MongoIndexedSessionRepositoryTest {
Document sessionDocument = new Document();
sessionDocument.put("id", sessionId);
MongoSession mongoSession = new MongoSession(sessionId,
MongoIndexedSessionRepository.DEFAULT_INACTIVE_INTERVAL);
MongoSession mongoSession = new MongoSession(sessionId, MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
given(this.converter.convert(sessionDocument, TypeDescriptor.valueOf(Document.class),
TypeDescriptor.valueOf(MongoSession.class))).willReturn(mongoSession);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2022 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.
@@ -16,6 +16,7 @@
package org.springframework.session.data.mongo;
import java.time.Duration;
import java.util.UUID;
import com.mongodb.BasicDBObject;
@@ -35,6 +36,7 @@ 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.MapSession;
import org.springframework.session.events.SessionDeletedEvent;
import static org.assertj.core.api.Assertions.assertThat;
@@ -84,26 +86,8 @@ public class ReactiveMongoSessionRepositoryTest {
.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);
assertThat(mongoSession.getMaxInactiveInterval())
.isEqualTo(Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
return true;
}) //
.verifyComplete();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2022 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.
@@ -17,6 +17,7 @@
package org.springframework.session.data.mongo.config.annotation.web.http;
import java.net.UnknownHostException;
import java.time.Duration;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Order;
@@ -32,11 +33,11 @@ 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.Session;
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;
@@ -112,9 +113,8 @@ public class MongoHttpSessionConfigurationTest {
MongoIndexedSessionRepository repository = this.context.getBean(MongoIndexedSessionRepository.class);
assertThat(repository).isNotNull();
assertThat(ReflectionTestUtils.getField(repository, "maxInactiveIntervalInSeconds"))
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
assertThat(repository).extracting("defaultMaxInactiveInterval")
.isEqualTo(Duration.ofSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS));
}
@Test
@@ -124,9 +124,8 @@ public class MongoHttpSessionConfigurationTest {
MongoIndexedSessionRepository repository = this.context.getBean(MongoIndexedSessionRepository.class);
assertThat(repository).isNotNull();
assertThat(ReflectionTestUtils.getField(repository, "maxInactiveIntervalInSeconds"))
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
assertThat(repository).extracting("defaultMaxInactiveInterval")
.isEqualTo(Duration.ofSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS));
}
@Test
@@ -161,7 +160,7 @@ public class MongoHttpSessionConfigurationTest {
MongoIndexedSessionRepository sessionRepository = this.context.getBean(MongoIndexedSessionRepository.class);
assertThat(sessionRepository).hasFieldOrPropertyWithValue("maxInactiveIntervalInSeconds", 10000);
assertThat(sessionRepository).extracting("defaultMaxInactiveInterval").isEqualTo(Duration.ofSeconds(10000));
}
@Test
@@ -171,7 +170,7 @@ public class MongoHttpSessionConfigurationTest {
CustomIndexResolverConfigurationWithDefaultMongoSessionConverter.class);
MongoIndexedSessionRepository repository = this.context.getBean(MongoIndexedSessionRepository.class);
IndexResolver<MongoSession> indexResolver = this.context.getBean(IndexResolver.class);
IndexResolver<Session> indexResolver = this.context.getBean(IndexResolver.class);
assertThat(repository).isNotNull();
assertThat(indexResolver).isNotNull();
@@ -186,7 +185,7 @@ public class MongoHttpSessionConfigurationTest {
CustomIndexResolverConfigurationWithProvidedMongoSessionConverter.class);
MongoIndexedSessionRepository repository = this.context.getBean(MongoIndexedSessionRepository.class);
IndexResolver<MongoSession> indexResolver = this.context.getBean(IndexResolver.class);
IndexResolver<Session> indexResolver = this.context.getBean(IndexResolver.class);
assertThat(repository).isNotNull();
assertThat(indexResolver).isNotNull();
@@ -194,6 +193,13 @@ public class MongoHttpSessionConfigurationTest {
indexResolver);
}
@Test
void importConfigAndCustomize() {
registerAndRefresh(ImportConfigAndCustomizeConfiguration.class);
MongoIndexedSessionRepository sessionRepository = this.context.getBean(MongoIndexedSessionRepository.class);
assertThat(sessionRepository).extracting("defaultMaxInactiveInterval").isEqualTo(Duration.ZERO);
}
private void registerAndRefresh(Class<?>... annotatedClasses) {
this.context.register(annotatedClasses);
@@ -259,7 +265,7 @@ public class MongoHttpSessionConfigurationTest {
static class CustomMaxInactiveIntervalInSecondsSetConfiguration extends MongoHttpSessionConfiguration {
CustomMaxInactiveIntervalInSecondsSetConfiguration() {
setMaxInactiveIntervalInSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS);
setMaxInactiveInterval(Duration.ofSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS));
}
}
@@ -286,19 +292,20 @@ public class MongoHttpSessionConfigurationTest {
}
@Configuration(proxyBeanMethods = false)
@EnableMongoHttpSession
static class SessionRepositoryCustomizerConfiguration {
@Bean
@Order(0)
SessionRepositoryCustomizer<MongoIndexedSessionRepository> sessionRepositoryCustomizerOne() {
return (sessionRepository) -> sessionRepository.setMaxInactiveIntervalInSeconds(0);
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(Duration.ZERO);
}
@Bean
@Order(1)
SessionRepositoryCustomizer<MongoIndexedSessionRepository> sessionRepositoryCustomizerTwo() {
return (sessionRepository) -> sessionRepository.setMaxInactiveIntervalInSeconds(10000);
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(Duration.ofSeconds(10000));
}
}
@@ -309,7 +316,7 @@ public class MongoHttpSessionConfigurationTest {
@Bean
@SuppressWarnings("unchecked")
IndexResolver<MongoSession> indexResolver() {
IndexResolver<Session> indexResolver() {
return mock(IndexResolver.class);
}
@@ -326,10 +333,21 @@ public class MongoHttpSessionConfigurationTest {
@Bean
@SuppressWarnings("unchecked")
IndexResolver<MongoSession> indexResolver() {
IndexResolver<Session> indexResolver() {
return mock(IndexResolver.class);
}
}
@Configuration(proxyBeanMethods = false)
@Import(MongoHttpSessionConfiguration.class)
static class ImportConfigAndCustomizeConfiguration extends BaseConfiguration {
@Bean
SessionRepositoryCustomizer<MongoIndexedSessionRepository> sessionRepositoryCustomizer() {
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(Duration.ZERO);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2014-2022 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.
@@ -17,6 +17,7 @@
package org.springframework.session.data.mongo.config.annotation.web.reactive;
import java.lang.reflect.Field;
import java.time.Duration;
import java.util.Collections;
import org.junit.jupiter.api.AfterEach;
@@ -26,17 +27,19 @@ 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.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.Session;
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;
@@ -54,7 +57,7 @@ import static org.mockito.BDDMockito.verify;
* Verify various configurations through {@link EnableSpringWebSession}.
*
* @author Greg Turnquist
* @author Vedran Pavić
* @author Vedran Pavic
*/
public class ReactiveMongoWebSessionConfigurationTest {
@@ -126,7 +129,7 @@ public class ReactiveMongoWebSessionConfigurationTest {
}
@Test
void overridingIntervalAndCollectionNameThroughAnnotationShouldWork() throws IllegalAccessException {
void overridingIntervalAndCollectionNameThroughAnnotationShouldWork() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(OverrideMongoParametersConfig.class);
@@ -134,17 +137,8 @@ public class ReactiveMongoWebSessionConfigurationTest {
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");
assertThat(repository).extracting("defaultMaxInactiveInterval").isEqualTo(Duration.ofSeconds(123));
assertThat(repository).extracting("collectionName").isEqualTo("test-case");
}
@Test
@@ -172,7 +166,7 @@ public class ReactiveMongoWebSessionConfigurationTest {
ReactiveMongoSessionRepository repository = this.context.getBean(ReactiveMongoSessionRepository.class);
assertThat(repository.getCollectionName()).isEqualTo("custom-collection");
assertThat(repository.getMaxInactiveIntervalInSeconds()).isEqualTo(123);
assertThat(repository).extracting("defaultMaxInactiveInterval").isEqualTo(Duration.ofSeconds(123));
}
@Test
@@ -184,7 +178,7 @@ public class ReactiveMongoWebSessionConfigurationTest {
ReactiveMongoSessionRepository repository = this.context.getBean(ReactiveMongoSessionRepository.class);
assertThat(repository).hasFieldOrPropertyWithValue("maxInactiveIntervalInSeconds", 10000);
assertThat(repository).extracting("defaultMaxInactiveInterval").isEqualTo(Duration.ofSeconds(10000));
}
@Test
@@ -195,7 +189,7 @@ public class ReactiveMongoWebSessionConfigurationTest {
this.context.refresh();
ReactiveMongoSessionRepository repository = this.context.getBean(ReactiveMongoSessionRepository.class);
IndexResolver<MongoSession> indexResolver = this.context.getBean(IndexResolver.class);
IndexResolver<Session> indexResolver = this.context.getBean(IndexResolver.class);
assertThat(repository).isNotNull();
assertThat(indexResolver).isNotNull();
@@ -211,7 +205,7 @@ public class ReactiveMongoWebSessionConfigurationTest {
this.context.refresh();
ReactiveMongoSessionRepository repository = this.context.getBean(ReactiveMongoSessionRepository.class);
IndexResolver<MongoSession> indexResolver = this.context.getBean(IndexResolver.class);
IndexResolver<Session> indexResolver = this.context.getBean(IndexResolver.class);
assertThat(repository).isNotNull();
assertThat(indexResolver).isNotNull();
@@ -219,6 +213,15 @@ public class ReactiveMongoWebSessionConfigurationTest {
indexResolver);
}
@Test
void importConfigAndCustomize() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(ImportConfigAndCustomizeConfiguration.class);
this.context.refresh();
ReactiveMongoSessionRepository sessionRepository = this.context.getBean(ReactiveMongoSessionRepository.class);
assertThat(sessionRepository).extracting("defaultMaxInactiveInterval").isEqualTo(Duration.ZERO);
}
/**
* Reflectively extract the {@link AbstractMongoSessionConverter} from the
* {@link ReactiveMongoSessionRepository}. This is to avoid expanding the surface area
@@ -239,6 +242,7 @@ public class ReactiveMongoWebSessionConfigurationTest {
/**
* A configuration with all the right parts.
*/
@Configuration(proxyBeanMethods = false)
@EnableMongoWebSession
static class GoodConfig {
@@ -252,11 +256,13 @@ public class ReactiveMongoWebSessionConfigurationTest {
/**
* A configuration where no {@link ReactiveMongoOperations} is defined. It's BAD!
*/
@Configuration(proxyBeanMethods = false)
@EnableMongoWebSession
static class BadConfig {
}
@Configuration(proxyBeanMethods = false)
@EnableMongoWebSession
static class OverrideSessionConverterConfig {
@@ -272,6 +278,7 @@ public class ReactiveMongoWebSessionConfigurationTest {
}
@Configuration(proxyBeanMethods = false)
@EnableMongoWebSession(maxInactiveIntervalInSeconds = 123, collectionName = "test-case")
static class OverrideMongoParametersConfig {
@@ -282,6 +289,7 @@ public class ReactiveMongoWebSessionConfigurationTest {
}
@Configuration(proxyBeanMethods = false)
@EnableMongoWebSession
static class ConfigWithReactiveAndImperativeMongoOperations {
@@ -308,13 +316,14 @@ public class ReactiveMongoWebSessionConfigurationTest {
}
@Configuration(proxyBeanMethods = false)
@EnableSpringWebSession
static class CustomizedReactiveConfiguration extends ReactiveMongoWebSessionConfiguration {
CustomizedReactiveConfiguration() {
this.setCollectionName("custom-collection");
this.setMaxInactiveIntervalInSeconds(123);
this.setMaxInactiveInterval(Duration.ofSeconds(123));
}
@Bean
@@ -324,6 +333,7 @@ public class ReactiveMongoWebSessionConfigurationTest {
}
@Configuration(proxyBeanMethods = false)
@EnableMongoWebSession
static class SessionRepositoryCustomizerConfiguration {
@@ -335,17 +345,18 @@ public class ReactiveMongoWebSessionConfigurationTest {
@Bean
@Order(0)
ReactiveSessionRepositoryCustomizer<ReactiveMongoSessionRepository> sessionRepositoryCustomizerOne() {
return (sessionRepository) -> sessionRepository.setMaxInactiveIntervalInSeconds(0);
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(Duration.ZERO);
}
@Bean
@Order(1)
ReactiveSessionRepositoryCustomizer<ReactiveMongoSessionRepository> sessionRepositoryCustomizerTwo() {
return (sessionRepository) -> sessionRepository.setMaxInactiveIntervalInSeconds(10000);
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(Duration.ofSeconds(10000));
}
}
@Configuration(proxyBeanMethods = false)
@EnableMongoWebSession
static class CustomIndexResolverConfigurationWithDefaultMongoSessionConverter {
@@ -356,12 +367,13 @@ public class ReactiveMongoWebSessionConfigurationTest {
@Bean
@SuppressWarnings("unchecked")
IndexResolver<MongoSession> indexResolver() {
IndexResolver<Session> indexResolver() {
return mock(IndexResolver.class);
}
}
@Configuration(proxyBeanMethods = false)
@EnableMongoWebSession
static class CustomIndexResolverConfigurationWithProvidedtMongoSessionConverter {
@@ -377,10 +389,26 @@ public class ReactiveMongoWebSessionConfigurationTest {
@Bean
@SuppressWarnings("unchecked")
IndexResolver<MongoSession> indexResolver() {
IndexResolver<Session> indexResolver() {
return mock(IndexResolver.class);
}
}
@Configuration(proxyBeanMethods = false)
@Import(ReactiveMongoWebSessionConfiguration.class)
static class ImportConfigAndCustomizeConfiguration {
@Bean
ReactiveMongoOperations operations() {
return mock(ReactiveMongoOperations.class);
}
@Bean
ReactiveSessionRepositoryCustomizer<ReactiveMongoSessionRepository> sessionRepositoryCustomizer() {
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(Duration.ZERO);
}
}
}

View File

@@ -13,6 +13,7 @@ dependencies {
testImplementation "org.assertj:assertj-core"
testImplementation "org.mockito:mockito-core"
testImplementation "org.mockito:mockito-junit-jupiter"
testImplementation "org.springframework:spring-test"
testImplementation "io.projectreactor:reactor-test"
testImplementation "jakarta.servlet:jakarta.servlet-api"

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -29,7 +29,7 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
*/
public abstract class AbstractRedisITests {
private static final String DOCKER_IMAGE = "redis:5.0.10";
private static final String DOCKER_IMAGE = "redis:7.0.4-alpine";
protected static class BaseConfig {
@@ -42,8 +42,8 @@ public abstract class AbstractRedisITests {
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(
redisContainer().getContainerIpAddress(), redisContainer().getFirstMappedPort());
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(redisContainer().getHost(),
redisContainer().getFirstMappedPort());
return new LettuceConnectionFactory(configuration);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2021 the original author or authors.
* Copyright 2014-2022 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.
@@ -39,7 +39,7 @@ import org.springframework.session.Session;
import org.springframework.session.data.SessionEventRegistry;
import org.springframework.session.data.redis.RedisIndexedSessionRepository.RedisSession;
import org.springframework.session.data.redis.config.annotation.SpringSessionRedisOperations;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisIndexedHttpSession;
import org.springframework.session.events.SessionCreatedEvent;
import org.springframework.session.events.SessionDestroyedEvent;
import org.springframework.test.context.ContextConfiguration;
@@ -111,10 +111,10 @@ class RedisIndexedSessionRepositoryITests extends AbstractRedisITests {
this.repository.save(toSave);
assertThat(this.registry.receivedEvent(toSave.getId())).isTrue();
assertThat(this.registry.<SessionCreatedEvent>getEvent(toSave.getId())).isInstanceOf(SessionCreatedEvent.class);
assertThat(this.redis.boundSetOps(usernameSessionKey).members()).contains(toSave.getId());
Session session = this.repository.findById(toSave.getId());
SessionCreatedEvent createdEvent = this.registry.getEvent(toSave.getId());
Session session = createdEvent.getSession();
assertThat(session.getId()).isEqualTo(toSave.getId());
assertThat(session.getAttributeNames()).isEqualTo(toSave.getAttributeNames());
@@ -527,6 +527,30 @@ class RedisIndexedSessionRepositoryITests extends AbstractRedisITests {
assertThat(findByPrincipalName.keySet()).containsOnly(changeSessionId);
}
@Test // gh-1987
void changeSessionIdWhenPrincipalNameChangesFromNullThenIndexShouldNotBeCreated() {
String principalName = null;
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
this.repository.save(toSave);
RedisSession findById = this.repository.findById(toSave.getId());
String changeSessionId = findById.changeSessionId();
findById.setAttribute(INDEX_NAME, principalNameChanged);
this.repository.save(findById);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(changeSessionId);
}
@Test
void changeSessionIdWhenOnlyChangeId() {
String attrName = "changeSessionId";
@@ -667,7 +691,7 @@ class RedisIndexedSessionRepositoryITests extends AbstractRedisITests {
}
@Configuration
@EnableRedisHttpSession(redisNamespace = "RedisIndexedSessionRepositoryITests")
@EnableRedisIndexedHttpSession(redisNamespace = "RedisIndexedSessionRepositoryITests")
static class Config extends BaseConfig {
@Bean

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -26,13 +26,10 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.session.MapSession;
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
import org.springframework.session.data.redis.RedisSessionRepository.RedisSession;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
@@ -223,17 +220,9 @@ class RedisSessionRepositoryITests extends AbstractRedisITests {
}
@Configuration
@EnableSpringHttpSession
@EnableRedisHttpSession
static class Config extends BaseConfig {
@Bean
RedisSessionRepository sessionRepository(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.afterPropertiesSet();
return new RedisSessionRepository(redisTemplate);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -44,7 +44,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session> extends AbstractRedisITests {
class EnableRedisIndexedHttpSessionExpireSessionDestroyedTests<S extends Session> extends AbstractRedisITests {
@Autowired
private SessionRepository<S> repository;
@@ -113,7 +113,7 @@ class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session> exten
}
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1)
@EnableRedisIndexedHttpSession(maxInactiveIntervalInSeconds = 1)
static class Config extends BaseConfig {
@Bean

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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.
@@ -32,7 +32,7 @@ import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.session.data.redis.AbstractRedisITests;
import org.springframework.session.data.redis.config.annotation.SpringSessionRedisOperations;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisIndexedHttpSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
@@ -101,7 +101,7 @@ class RedisListenerContainerTaskExecutorITests extends AbstractRedisITests {
}
@Configuration
@EnableRedisHttpSession(redisNamespace = "RedisListenerContainerTaskExecutorITests")
@EnableRedisIndexedHttpSession(redisNamespace = "RedisListenerContainerTaskExecutorITests")
static class Config extends BaseConfig {
@Bean

View File

@@ -1,54 +0,0 @@
/*
* Copyright 2014-2019 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.redis;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.session.ReactiveSessionRepository;
import org.springframework.util.Assert;
/**
* This {@link ReactiveSessionRepository} implementation is kept in order to support
* migration to {@link ReactiveRedisSessionRepository} in a backwards compatible manner.
*
* @author Vedran Pavic
* @since 2.0.0
* @deprecated since 2.2.0 in favor of {@link ReactiveRedisSessionRepository}
*/
@Deprecated
public class ReactiveRedisOperationsSessionRepository extends ReactiveRedisSessionRepository {
/**
* Create a new {@link ReactiveRedisOperationsSessionRepository} instance.
* @param sessionRedisOperations the {@link ReactiveRedisOperations} to use for
* managing sessions
* @see ReactiveRedisSessionRepository#ReactiveRedisSessionRepository(ReactiveRedisOperations)
*/
public ReactiveRedisOperationsSessionRepository(ReactiveRedisOperations<String, Object> sessionRedisOperations) {
super(sessionRedisOperations);
}
/**
* Sets the redis flush mode. Default flush mode is {@link RedisFlushMode#ON_SAVE}.
* @param redisFlushMode the new redis flush mode
* @deprecated since 2.2.0 as support {@code IMMEDIATE} is removed
*/
@Deprecated
public void setRedisFlushMode(RedisFlushMode redisFlushMode) {
Assert.notNull(redisFlushMode, "redisFlushMode cannot be null");
}
}

Some files were not shown because too many files have changed in this diff Show More