From 6351eeaa4d2b3011a13eb16e95b3585814d6ad73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Sun, 17 Apr 2016 10:06:20 +1000 Subject: [PATCH] Add session endpoints --- spring-boot-actuator/pom.xml | 5 + .../EndpointAutoConfiguration.java | 15 ++ ...tWebMvcManagementContextConfiguration.java | 10 ++ .../actuate/endpoint/SessionEndpoint.java | 131 ++++++++++++++ .../endpoint/jmx/EndpointMBeanExporter.java | 4 + .../endpoint/jmx/SessionEndpointMBean.java | 62 +++++++ .../endpoint/mvc/SessionMvcEndpoint.java | 62 +++++++ .../SpringApplicationHierarchyTests.java | 4 +- .../endpoint/mvc/SessionMvcEndpointTests.java | 160 ++++++++++++++++++ .../appendix-application-properties.adoc | 3 + 10 files changed, 455 insertions(+), 1 deletion(-) create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/SessionEndpoint.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/SessionEndpointMBean.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/SessionMvcEndpoint.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/SessionMvcEndpointTests.java diff --git a/spring-boot-actuator/pom.xml b/spring-boot-actuator/pom.xml index cf323298cba4..10b6905d4a3d 100644 --- a/spring-boot-actuator/pom.xml +++ b/spring-boot-actuator/pom.xml @@ -213,6 +213,11 @@ spring-security-config true + + org.springframework.session + spring-session + true + org.apache.tomcat.embed tomcat-embed-core diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointAutoConfiguration.java index e52e2935684e..3ac5f16ab279 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointAutoConfiguration.java @@ -40,6 +40,7 @@ import org.springframework.boot.actuate.endpoint.MetricsEndpoint; import org.springframework.boot.actuate.endpoint.PublicMetrics; import org.springframework.boot.actuate.endpoint.RequestMappingEndpoint; +import org.springframework.boot.actuate.endpoint.SessionEndpoint; import org.springframework.boot.actuate.endpoint.ShutdownEndpoint; import org.springframework.boot.actuate.endpoint.TraceEndpoint; import org.springframework.boot.actuate.health.HealthAggregator; @@ -61,6 +62,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.session.FindByIndexNameSessionRepository; import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping; /** @@ -216,4 +218,17 @@ public RequestMappingEndpoint requestMappingEndpoint() { } + @Configuration + @ConditionalOnBean(FindByIndexNameSessionRepository.class) + @ConditionalOnClass(FindByIndexNameSessionRepository.class) + static class SessionEndpointConfiguration { + + @Bean + @ConditionalOnMissingBean + public SessionEndpoint sessionEndpoint() { + return new SessionEndpoint(); + } + + } + } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcManagementContextConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcManagementContextConfiguration.java index b3ac138bd1dd..75fc25911279 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcManagementContextConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcManagementContextConfiguration.java @@ -26,6 +26,7 @@ import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint; import org.springframework.boot.actuate.endpoint.HealthEndpoint; import org.springframework.boot.actuate.endpoint.MetricsEndpoint; +import org.springframework.boot.actuate.endpoint.SessionEndpoint; import org.springframework.boot.actuate.endpoint.ShutdownEndpoint; import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping; import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMappingCustomizer; @@ -35,6 +36,7 @@ import org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint; import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints; +import org.springframework.boot.actuate.endpoint.mvc.SessionMvcEndpoint; import org.springframework.boot.actuate.endpoint.mvc.ShutdownMvcEndpoint; import org.springframework.boot.autoconfigure.condition.ConditionOutcome; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -55,6 +57,7 @@ * Configuration to expose {@link Endpoint} instances over Spring MVC. * * @author Dave Syer + * @author Eddú Meléndez * @since 1.3.0 */ @ManagementContextConfiguration @@ -167,6 +170,13 @@ public ShutdownMvcEndpoint shutdownMvcEndpoint(ShutdownEndpoint delegate) { return new ShutdownMvcEndpoint(delegate); } + @Bean + @ConditionalOnBean(SessionEndpoint.class) + @ConditionalOnEnabledEndpoint(value = "session", enabledByDefault = false) + public SessionMvcEndpoint sessionMvcEndpoint(SessionEndpoint delegate) { + return new SessionMvcEndpoint(delegate); + } + private static class LogFileCondition extends SpringBootCondition { @Override diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/SessionEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/SessionEndpoint.java new file mode 100644 index 000000000000..3571003e013a --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/SessionEndpoint.java @@ -0,0 +1,131 @@ +/* + * Copyright 2012-2016 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 + * + * http://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.boot.actuate.endpoint; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.session.ExpiringSession; +import org.springframework.session.FindByIndexNameSessionRepository; + +/** + * {@link Endpoint} to manage web sessions. + * + * @author Eddú Meléndez + * @since 1.4.0 + */ +@ConfigurationProperties("endpoints.session") +public class SessionEndpoint implements Endpoint { + + @Autowired + private FindByIndexNameSessionRepository sessionRepository; + + /** + * Enable the endpoint. + */ + private boolean enabled = false; + + @Override + public String getId() { + return "session"; + } + + @Override + public boolean isEnabled() { + return this.enabled; + } + + @Override + public boolean isSensitive() { + return true; + } + + @Override + public Object invoke() { + return null; + } + + public Map result(String username) { + List sessions = new ArrayList(); + for (ExpiringSession session : this.sessionRepository.findByIndexNameAndIndexValue( + FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username) + .values()) { + sessions.add(new Session(session)); + } + Map sessionEntries = new HashMap(); + sessionEntries.put("sessions", sessions); + return Collections.unmodifiableMap(sessionEntries); + } + + public boolean delete(String sessionId) { + ExpiringSession session = this.sessionRepository.getSession(sessionId); + if (session != null) { + this.sessionRepository.delete(sessionId); + return true; + } + return false; + } + + /** + * Session properties. + */ + public static class Session { + + private String id; + + private long creationTime; + + private long lastAccessedTime; + + public Session(ExpiringSession session) { + this.id = session.getId(); + this.creationTime = session.getCreationTime(); + this.lastAccessedTime = session.getLastAccessedTime(); + } + + public String getId() { + return this.id; + } + + public void setId(String id) { + this.id = id; + } + + public long getCreationTime() { + return this.creationTime; + } + + public void setCreationTime(long creationTime) { + this.creationTime = creationTime; + } + + public long getLastAccessedTime() { + return this.lastAccessedTime; + } + + public void setLastAccessedTime(long lastAccessedTime) { + this.lastAccessedTime = lastAccessedTime; + } + + } + +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporter.java index 102eeaa3ab3a..d97d617f832b 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporter.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporter.java @@ -58,6 +58,7 @@ * * @author Christian Dupuis * @author Andy Wilkinson + * @author Eddú Meléndez */ public class EndpointMBeanExporter extends MBeanExporter implements SmartLifecycle, ApplicationContextAware { @@ -188,6 +189,9 @@ protected void registerEndpoint(String beanName, Endpoint endpoint) { } protected EndpointMBean getEndpointMBean(String beanName, Endpoint endpoint) { + if (endpoint instanceof SessionEndpointMBean) { + return new SessionEndpointMBean(beanName, endpoint, this.objectMapper); + } if (endpoint instanceof ShutdownEndpoint) { return new ShutdownEndpointMBean(beanName, endpoint, this.objectMapper); } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/SessionEndpointMBean.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/SessionEndpointMBean.java new file mode 100644 index 000000000000..336788200343 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/SessionEndpointMBean.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012-2016 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 + * + * http://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.boot.actuate.endpoint.jmx; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.springframework.boot.actuate.endpoint.Endpoint; +import org.springframework.boot.actuate.endpoint.SessionEndpoint; +import org.springframework.jmx.export.annotation.ManagedOperation; +import org.springframework.jmx.export.annotation.ManagedOperationParameter; +import org.springframework.jmx.export.annotation.ManagedResource; + +/** + * Special endpoint wrapper for {@link SessionEndpoint}. + * + * @author Eddú Meléndez + * @since 1.4.0 + */ +@ManagedResource +public class SessionEndpointMBean extends EndpointMBean { + + private SessionEndpoint sessionEndpoint; + + /** + * Create a new {@link SessionEndpointMBean} instance. + * + * @param beanName the bean name + * @param endpoint the endpoint to wrap + * @param objectMapper the {@link ObjectMapper} used to convert the payload + */ + public SessionEndpointMBean(String beanName, Endpoint endpoint, ObjectMapper objectMapper) { + super(beanName, endpoint, objectMapper); + this.sessionEndpoint = (SessionEndpoint) getEndpoint(); + } + + @ManagedOperation(description = "Find current user's sessions") + @ManagedOperationParameter(name = "username", description = "Application's username") + public Object findSessionsByUsername(String username) { + return convert(this.sessionEndpoint.result(username)); + } + + @ManagedOperation(description = "Delete session by id") + @ManagedOperationParameter(name = "sessionId", description = "Web session id") + public boolean deleteSessionBySessionId(String sessionId) { + return this.sessionEndpoint.delete(sessionId); + } + +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/SessionMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/SessionMvcEndpoint.java new file mode 100644 index 000000000000..109021e81e88 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/SessionMvcEndpoint.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012-2016 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 + * + * http://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.boot.actuate.endpoint.mvc; + +import java.util.Map; + +import org.springframework.boot.actuate.endpoint.Endpoint; +import org.springframework.boot.actuate.endpoint.SessionEndpoint; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * Adapter to expose {@link SessionEndpoint} as an {@link MvcEndpoint}. + * + * @author Eddú Meléndez + * @since 1.4.0 + */ +@ConfigurationProperties(prefix = "endpoints.session") +public class SessionMvcEndpoint extends AbstractEndpointMvcAdapter { + + /** + * Create a new {@link EndpointMvcAdapter}. + * + * @param delegate the underlying {@link Endpoint} to adapt. + */ + public SessionMvcEndpoint(SessionEndpoint delegate) { + super(delegate); + } + + @RequestMapping(method = RequestMethod.GET) + public Map result(@RequestParam String username) { + return getDelegate().result(username); + } + + @RequestMapping(path = "/{sessionId}", method = RequestMethod.DELETE) + public ResponseEntity delete(@PathVariable String sessionId) { + boolean deleted = getDelegate().delete(sessionId); + if (deleted) { + return ResponseEntity.ok().build(); + } + return ResponseEntity.notFound().build(); + } + +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/SpringApplicationHierarchyTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/SpringApplicationHierarchyTests.java index a821dc580ae4..26e5be93ecc5 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/SpringApplicationHierarchyTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/SpringApplicationHierarchyTests.java @@ -27,6 +27,7 @@ import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration; import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration; +import org.springframework.boot.autoconfigure.session.SessionAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.util.ApplicationContextTestUtils; import org.springframework.context.ConfigurableApplicationContext; @@ -65,7 +66,8 @@ public void testChild() { ElasticsearchRepositoriesAutoConfiguration.class, CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class, Neo4jAutoConfiguration.class, RedisAutoConfiguration.class, - RedisRepositoriesAutoConfiguration.class }, excludeName = { + RedisRepositoriesAutoConfiguration.class, + SessionAutoConfiguration.class }, excludeName = { "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" }) public static class Child { diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/SessionMvcEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/SessionMvcEndpointTests.java new file mode 100644 index 000000000000..d2761b147107 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/SessionMvcEndpointTests.java @@ -0,0 +1,160 @@ +/* + * Copyright 2012-2016 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 + * + * http://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.boot.actuate.endpoint.mvc; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.ManagementServerPropertiesAutoConfiguration; +import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration; +import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; +import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor; +import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; +import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.util.EnvironmentTestUtils; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.session.ExpiringSession; +import org.springframework.session.FindByIndexNameSessionRepository; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * Tests for {@link SessionMvcEndpoint} + * + * @author Eddú Meléndez + */ +public class SessionMvcEndpointTests { + + private AnnotationConfigEmbeddedWebApplicationContext context; + + @Before + public void setUp() { + this.context = new AnnotationConfigEmbeddedWebApplicationContext(); + } + + @After + public void close() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void endpointNotRegistered() throws Exception { + loadConfig(); + assertThat(this.context.getBeanNamesForType(SessionMvcEndpoint.class)).hasSize(0); + } + + @Test + public void endpointRegistered() throws Exception { + EnvironmentTestUtils.addEnvironment(this.context, "endpoints.session.enabled=true"); + loadConfig(); + assertThat(this.context.getBeanNamesForType(SessionMvcEndpoint.class)).hasSize(1); + } + + @Test + public void searchEndpointAvailable() throws Exception { + EnvironmentTestUtils.addEnvironment(this.context, "endpoints.session.enabled=true"); + loadConfig(); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); + mockMvc.perform((get("/session/?username=springuser"))) + .andExpect(status().isOk()); + } + + @Test + public void customizePath() throws Exception { + EnvironmentTestUtils.addEnvironment(this.context, "endpoints.session.enabled=true", + "endpoints.session.path=/mysession"); + loadConfig(); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); + mockMvc.perform((get("/mysession/?username=springuser"))) + .andExpect(status().isOk()); + } + + @Test + public void deleteSession() throws Exception { + EnvironmentTestUtils.addEnvironment(this.context, "endpoints.session.enabled=true"); + loadConfig(); + FindByIndexNameSessionRepository sessionRepository = this.context.getBean(FindByIndexNameSessionRepository.class); + given(sessionRepository.getSession("123")).willReturn(mock(ExpiringSession.class)); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); + mockMvc.perform(delete("/session/123")) + .andExpect(status().isOk()); + } + + @Test + public void deleteSessionDoNotExist() throws Exception { + EnvironmentTestUtils.addEnvironment(this.context, "endpoints.session.enabled=true"); + loadConfig(); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); + mockMvc.perform(delete("/session/12345")) + .andExpect(status().isNotFound()); + } + + private void loadConfig() { + this.context.register(Config.class, SessionRepositoryConfig.class, + EndpointAutoConfiguration.class, + WebMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); + this.context.refresh(); + } + + @Configuration + @EnableConfigurationProperties + @EnableWebMvc + @Import({ EndpointWebMvcAutoConfiguration.class, + ManagementServerPropertiesAutoConfiguration.class }) + public static class SessionRepositoryConfig { + + @Bean + public FindByIndexNameSessionRepository findByIndexNameSessionRepository() { + return mock(FindByIndexNameSessionRepository.class); + } + + } + + @Configuration + @EnableConfigurationProperties + protected static class Config { + + @Bean + public EmbeddedServletContainerFactory containerFactory() { + return new MockEmbeddedServletContainerFactory(); + } + + @Bean + public EmbeddedServletContainerCustomizerBeanPostProcessor embeddedServletContainerCustomizerBeanPostProcessor() { + return new EmbeddedServletContainerCustomizerBeanPostProcessor(); + } + + } + +} diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 4dfb9fb38c71..c74b9e4a0cf8 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -952,6 +952,9 @@ content into your application; rather pick only the properties that you need. endpoints.metrics.id= # Endpoint identifier. endpoints.metrics.path= # Endpoint path. endpoints.metrics.sensitive= # Mark if the endpoint exposes sensitive information. + endpoints.session.enabled= # Enable the endpoint + endpoints.session.id= # Endpoint identifier + endpoints.session.path= # Endpoint path endpoints.shutdown.enabled= # Enable the endpoint. endpoints.shutdown.id= # Endpoint identifier. endpoints.shutdown.path= # Endpoint path.