Skip to content

Commit 6e3d4ed

Browse files
committed
Use ReactiveFindByIndexNameSessionRepository
See gh-32046
1 parent de76ef1 commit 6e3d4ed

File tree

9 files changed

+241
-107
lines changed

9 files changed

+241
-107
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/session/SessionsEndpointAutoConfiguration.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2022 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@
3131
import org.springframework.context.annotation.Bean;
3232
import org.springframework.context.annotation.Configuration;
3333
import org.springframework.session.FindByIndexNameSessionRepository;
34+
import org.springframework.session.ReactiveFindByIndexNameSessionRepository;
3435
import org.springframework.session.ReactiveSessionRepository;
3536
import org.springframework.session.Session;
3637
import org.springframework.session.SessionRepository;
@@ -67,8 +68,9 @@ static class ReactiveSessionEndpointConfiguration {
6768

6869
@Bean
6970
@ConditionalOnMissingBean
70-
ReactiveSessionsEndpoint sessionsEndpoint(ReactiveSessionRepository<? extends Session> sessionRepository) {
71-
return new ReactiveSessionsEndpoint(sessionRepository);
71+
ReactiveSessionsEndpoint sessionsEndpoint(ReactiveSessionRepository<? extends Session> sessionRepository,
72+
ObjectProvider<ReactiveFindByIndexNameSessionRepository<? extends Session>> indexedSessionRepository) {
73+
return new ReactiveSessionsEndpoint(sessionRepository, indexedSessionRepository.getIfAvailable());
7274
}
7375

7476
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/session/SessionsEndpointAutoConfigurationTests.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.context.annotation.Bean;
2828
import org.springframework.context.annotation.Configuration;
2929
import org.springframework.session.FindByIndexNameSessionRepository;
30+
import org.springframework.session.ReactiveFindByIndexNameSessionRepository;
3031
import org.springframework.session.ReactiveSessionRepository;
3132
import org.springframework.session.SessionRepository;
3233

@@ -37,6 +38,7 @@
3738
* Tests for {@link SessionsEndpointAutoConfiguration}.
3839
*
3940
* @author Vedran Pavic
41+
* @author Moritz Halbritter
4042
*/
4143
class SessionsEndpointAutoConfigurationTests {
4244

@@ -100,14 +102,24 @@ class ReactiveSessionEndpointConfigurationTests {
100102

101103
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
102104
.withConfiguration(AutoConfigurations.of(SessionsEndpointAutoConfiguration.class))
103-
.withUserConfiguration(ReactiveSessionRepositoryConfiguration.class);
105+
.withUserConfiguration(ReactiveSessionRepositoryConfiguration.class,
106+
ReactiveIndexedSessionRepositoryConfiguration.class);
104107

105108
@Test
106109
void runShouldHaveEndpointBean() {
107110
this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include=sessions")
108111
.run((context) -> assertThat(context).hasSingleBean(ReactiveSessionsEndpoint.class));
109112
}
110113

114+
@Test
115+
void runWhenNoIndexedSessionRepositoryShouldHaveEndpointBean() {
116+
new ReactiveWebApplicationContextRunner()
117+
.withConfiguration(AutoConfigurations.of(SessionsEndpointAutoConfiguration.class))
118+
.withUserConfiguration(ReactiveSessionRepositoryConfiguration.class)
119+
.withPropertyValues("management.endpoints.web.exposure.include=sessions")
120+
.run((context) -> assertThat(context).hasSingleBean(ReactiveSessionsEndpoint.class));
121+
}
122+
111123
@Test
112124
void runWhenNotExposedShouldNotHaveEndpointBean() {
113125
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(ReactiveSessionsEndpoint.class));
@@ -119,6 +131,16 @@ void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
119131
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveSessionsEndpoint.class));
120132
}
121133

134+
@Configuration(proxyBeanMethods = false)
135+
static class ReactiveIndexedSessionRepositoryConfiguration {
136+
137+
@Bean
138+
ReactiveFindByIndexNameSessionRepository<?> indexedSessionRepository() {
139+
return mock(ReactiveFindByIndexNameSessionRepository.class);
140+
}
141+
142+
}
143+
122144
@Configuration(proxyBeanMethods = false)
123145
static class ReactiveSessionRepositoryConfiguration {
124146

spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/session/ReactiveSessionsEndpoint.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2022 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@
2222
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
2323
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
2424
import org.springframework.boot.actuate.endpoint.annotation.Selector;
25+
import org.springframework.boot.actuate.session.SessionsDescriptor.SessionDescriptor;
26+
import org.springframework.session.ReactiveFindByIndexNameSessionRepository;
2527
import org.springframework.session.ReactiveSessionRepository;
2628
import org.springframework.session.Session;
2729
import org.springframework.util.Assert;
@@ -31,20 +33,34 @@
3133
* reactive stack.
3234
*
3335
* @author Vedran Pavic
34-
* @since 3.0.0
36+
* @author Moritz Halbritter
37+
* @since 3.3.0
3538
*/
3639
@Endpoint(id = "sessions")
3740
public class ReactiveSessionsEndpoint {
3841

3942
private final ReactiveSessionRepository<? extends Session> sessionRepository;
4043

44+
private final ReactiveFindByIndexNameSessionRepository<? extends Session> indexedSessionRepository;
45+
4146
/**
4247
* Create a new {@link ReactiveSessionsEndpoint} instance.
4348
* @param sessionRepository the session repository
49+
* @param indexedSessionRepository the indexed session repository
4450
*/
45-
public ReactiveSessionsEndpoint(ReactiveSessionRepository<? extends Session> sessionRepository) {
51+
public ReactiveSessionsEndpoint(ReactiveSessionRepository<? extends Session> sessionRepository,
52+
ReactiveFindByIndexNameSessionRepository<? extends Session> indexedSessionRepository) {
4653
Assert.notNull(sessionRepository, "ReactiveSessionRepository must not be null");
4754
this.sessionRepository = sessionRepository;
55+
this.indexedSessionRepository = indexedSessionRepository;
56+
}
57+
58+
@ReadOperation
59+
public Mono<SessionsDescriptor> sessionsForUsername(String username) {
60+
if (this.indexedSessionRepository == null) {
61+
return Mono.empty();
62+
}
63+
return this.indexedSessionRepository.findByPrincipalName(username).map(SessionsDescriptor::new);
4864
}
4965

5066
@ReadOperation

spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/session/SessionDescriptor.java

Lines changed: 0 additions & 78 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.session;
18+
19+
import java.time.Instant;
20+
import java.util.List;
21+
import java.util.Map;
22+
import java.util.Set;
23+
24+
import org.springframework.boot.actuate.endpoint.OperationResponseBody;
25+
import org.springframework.session.Session;
26+
27+
/**
28+
* Description of user's {@link Session sessions}.
29+
*
30+
* @author Moritz Halbritter
31+
* @since 3.3.0
32+
*/
33+
public final class SessionsDescriptor implements OperationResponseBody {
34+
35+
private final List<SessionDescriptor> sessions;
36+
37+
public SessionsDescriptor(Map<String, ? extends Session> sessions) {
38+
this.sessions = sessions.values().stream().map(SessionDescriptor::new).toList();
39+
}
40+
41+
public List<SessionDescriptor> getSessions() {
42+
return this.sessions;
43+
}
44+
45+
/**
46+
* A description of user's {@link Session session} exposed by {@code sessions}
47+
* endpoint. Primarily intended for serialization to JSON.
48+
*/
49+
public static final class SessionDescriptor {
50+
51+
private final String id;
52+
53+
private final Set<String> attributeNames;
54+
55+
private final Instant creationTime;
56+
57+
private final Instant lastAccessedTime;
58+
59+
private final long maxInactiveInterval;
60+
61+
private final boolean expired;
62+
63+
SessionDescriptor(Session session) {
64+
this.id = session.getId();
65+
this.attributeNames = session.getAttributeNames();
66+
this.creationTime = session.getCreationTime();
67+
this.lastAccessedTime = session.getLastAccessedTime();
68+
this.maxInactiveInterval = session.getMaxInactiveInterval().getSeconds();
69+
this.expired = session.isExpired();
70+
}
71+
72+
public String getId() {
73+
return this.id;
74+
}
75+
76+
public Set<String> getAttributeNames() {
77+
return this.attributeNames;
78+
}
79+
80+
public Instant getCreationTime() {
81+
return this.creationTime;
82+
}
83+
84+
public Instant getLastAccessedTime() {
85+
return this.lastAccessedTime;
86+
}
87+
88+
public long getMaxInactiveInterval() {
89+
return this.maxInactiveInterval;
90+
}
91+
92+
public boolean isExpired() {
93+
return this.expired;
94+
}
95+
96+
}
97+
98+
}

spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/session/SessionsEndpoint.java

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,13 @@
1616

1717
package org.springframework.boot.actuate.session;
1818

19-
import java.util.List;
2019
import java.util.Map;
2120

22-
import org.springframework.boot.actuate.endpoint.OperationResponseBody;
2321
import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation;
2422
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
2523
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
2624
import org.springframework.boot.actuate.endpoint.annotation.Selector;
25+
import org.springframework.boot.actuate.session.SessionsDescriptor.SessionDescriptor;
2726
import org.springframework.session.FindByIndexNameSessionRepository;
2827
import org.springframework.session.Session;
2928
import org.springframework.session.SessionRepository;
@@ -43,10 +42,22 @@ public class SessionsEndpoint {
4342

4443
private final FindByIndexNameSessionRepository<? extends Session> indexedSessionRepository;
4544

45+
/**
46+
* Create a new {@link SessionsEndpoint} instance.
47+
* @param sessionRepository the session repository
48+
* @deprecated since 3.3.0 for removal in 3.5.0 in favor of
49+
* {@link #SessionsEndpoint(SessionRepository, FindByIndexNameSessionRepository)}
50+
*/
51+
@Deprecated(since = "3.3.0", forRemoval = true)
52+
public SessionsEndpoint(FindByIndexNameSessionRepository<? extends Session> sessionRepository) {
53+
this(sessionRepository, sessionRepository);
54+
}
55+
4656
/**
4757
* Create a new {@link SessionsEndpoint} instance.
4858
* @param sessionRepository the session repository
4959
* @param indexedSessionRepository the indexed session repository
60+
* @since 3.3.0
5061
*/
5162
public SessionsEndpoint(SessionRepository<? extends Session> sessionRepository,
5263
FindByIndexNameSessionRepository<? extends Session> indexedSessionRepository) {
@@ -78,21 +89,4 @@ public void deleteSession(@Selector String sessionId) {
7889
this.sessionRepository.deleteById(sessionId);
7990
}
8091

81-
/**
82-
* Description of user's {@link Session sessions}.
83-
*/
84-
public static final class SessionsDescriptor implements OperationResponseBody {
85-
86-
private final List<SessionDescriptor> sessions;
87-
88-
public SessionsDescriptor(Map<String, ? extends Session> sessions) {
89-
this.sessions = sessions.values().stream().map(SessionDescriptor::new).toList();
90-
}
91-
92-
public List<SessionDescriptor> getSessions() {
93-
return this.sessions;
94-
}
95-
96-
}
97-
9892
}

0 commit comments

Comments
 (0)