Spring Boot Actuator AutoConfigure module providing production-ready features to Spring Boot applications through auto-configuration
npx @tessl/cli install tessl/maven-org-springframework-boot--spring-boot-actuator-autoconfigure@4.0.0Spring Boot Actuator AutoConfigure provides automatic configuration for Spring Boot Actuator, enabling production-ready monitoring and management features. It auto-configures actuator endpoints based on classpath dependencies and application properties, following Spring Boot's convention-over-configuration philosophy. This module handles endpoint discovery, filtering, exposure (via HTTP and JMX), and management server configuration.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency># Expose all web endpoints
management.endpoints.web.exposure.include=*
# Expose specific endpoints
management.endpoints.web.exposure.include=health,info,metrics
# Change base path
management.endpoints.web.base-path=/actuator
# Separate management port
management.server.port=8081
# Endpoint access control
management.endpoint.health.show-details=always
management.endpoint.env.show-values=NEVER// Endpoint annotations
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
// Conditional annotations
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
import org.springframework.boot.actuate.autoconfigure.web.server.ConditionalOnManagementPort;
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextType;
// Core infrastructure
import org.springframework.boot.actuate.endpoint.EndpointAccessResolver;
import org.springframework.boot.actuate.endpoint.Access;
import org.springframework.boot.actuate.endpoint.EndpointId;
// Properties
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties;| Scenario | Same Port | Separate Port | Reason |
|---|---|---|---|
| Simple application | ✓ | Less complexity | |
| Production with network isolation needed | ✓ | Can restrict management access | |
| Docker/Kubernetes | ✓ | Liveness/readiness on main port | |
| Internal monitoring tools | ✓ | Separate security policies | |
| High-security requirements | ✓ | Firewall rules isolation |
| Environment | Web Exposure | JMX Exposure | Rationale |
|---|---|---|---|
| Development | * | * | Full visibility for debugging |
| Staging | health,info,metrics,loggers | * | Limited web, full internal |
| Production | health,info,metrics,prometheus | health,metrics | Minimal exposure |
| Environment | configprops | env | Rationale |
|---|---|---|---|
| Development | ALWAYS | ALWAYS | Full visibility |
| Staging | WHEN_AUTHORIZED | WHEN_AUTHORIZED | Role-based access |
| Production | NEVER | NEVER | Maximum security |
@Component
@Endpoint(id = "custom")
public class CustomEndpoint {
@ReadOperation
public Map<String, Object> getData() {
return Map.of("status", "ok", "timestamp", System.currentTimeMillis());
}
}Property required: management.endpoints.web.exposure.include=custom
// Endpoint class
@Endpoint(id = "custom")
public class CustomEndpoint {
@ReadOperation
public Map<String, Object> getData() {
return Map.of("status", "ok");
}
}
// Auto-configuration
@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = CustomEndpoint.class)
public class CustomEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public CustomEndpoint customEndpoint() {
return new CustomEndpoint();
}
}@Component
public class CustomInfoContributor implements InfoContributor {
@Override
public void contribute(Info.Builder builder) {
builder.withDetail("custom", Map.of("key", "value"));
}
}Property required: management.info.custom.enabled=true
@Endpoint(id = "cache")
public class CacheEndpoint {
@ReadOperation
public Map<String, Object> getCache(@Selector String cacheName) {
// GET /actuator/cache/{cacheName}
return cacheManager.getCache(cacheName).asMap();
}
@DeleteOperation
public void evictCache(@Selector String cacheName) {
// DELETE /actuator/cache/{cacheName}
cacheManager.getCache(cacheName).clear();
}
}// Register in META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports
@ManagementContextConfiguration(ManagementContextType.CHILD)
public class CustomManagementConfiguration {
@Bean
public CustomManagementBean customBean() {
return new CustomManagementBean();
}
}┌─────────────────────────────────────────────────────────┐
│ Endpoint Auto-Configuration Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Endpoint │ │ Endpoint │ │ Endpoint │ │
│ │ Discovery │→ │ Filtering │→ │ Exposure │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Exposure Technology Layer │
│ ┌──────────────────┐ ┌───────────────────┐ │
│ │ Web Endpoints │ │ JMX Endpoints │ │
│ │ (HTTP/JSON) │ │ (MBeans) │ │
│ └──────────────────┘ └───────────────────┘ │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Server Infrastructure Layer │
│ ┌──────────────────┐ ┌───────────────────┐ │
│ │ Same Server │ OR │ Separate Server │ │
│ │ (server.port) │ │ (mgmt.port) │ │
│ └──────────────────┘ └───────────────────┘ │
└─────────────────────────────────────────────────────────┘| Subsystem | Documentation | Key Classes | Primary Use |
|---|---|---|---|
| Core Infrastructure | core-infrastructure.md | EndpointAutoConfiguration, PropertiesEndpointAccessResolver | Endpoint parameter mapping, caching, access control |
| Management Endpoints | management-endpoints.md | BeansEndpoint, HealthEndpoint, InfoEndpoint, etc. | Individual endpoint implementations |
| Web Exposure | web-endpoints.md | WebEndpointAutoConfiguration, WebEndpointProperties | HTTP endpoint exposure, CORS, path mapping |
| JMX Exposure | jmx-endpoints.md | JmxEndpointAutoConfiguration, JmxEndpointProperties | JMX MBean endpoint exposure |
| Endpoint Properties | endpoint-properties.md | ConfigurationPropertiesReportEndpointProperties, EnvironmentEndpointProperties | Endpoint-specific configuration |
| Endpoint Filtering | endpoint-filtering.md | IncludeExcludeEndpointFilter, EndpointExposure | Include/exclude pattern filtering |
| Management Server | management-server.md | ManagementServerProperties, ManagementPortType | Separate management port configuration |
| Conditional Annotations | conditional-annotations.md | @ConditionalOnAvailableEndpoint, @ConditionalOnManagementPort | Conditional component registration |
| Endpoint ID | Path | HTTP Methods | Default Exposed | Purpose | Auto-Config Class |
|---|---|---|---|---|---|
health | /actuator/health | GET | Yes (web, jmx) | Application health status | (In spring-boot-health module) |
info | /actuator/info | GET | Yes (web) | Application information | InfoEndpointAutoConfiguration |
metrics | /actuator/metrics | GET | No | Application metrics | (In spring-boot-actuator-metrics module) |
beans | /actuator/beans | GET | No | All Spring beans | BeansEndpointAutoConfiguration |
conditions | /actuator/conditions | GET | No | Auto-configuration report | ConditionsReportEndpointAutoConfiguration |
configprops | /actuator/configprops | GET | No | Configuration properties | ConfigurationPropertiesReportEndpointAutoConfiguration |
env | /actuator/env | GET | No | Environment properties | EnvironmentEndpointAutoConfiguration |
loggers | /actuator/loggers | GET, POST | No | Logger levels (mutable) | LoggersEndpointAutoConfiguration |
heapdump | /actuator/heapdump | GET | No | Download heap dump | HeapDumpWebEndpointAutoConfiguration |
threaddump | /actuator/threaddump | GET | No | Thread dump | ThreadDumpEndpointAutoConfiguration |
shutdown | /actuator/shutdown | POST | No | Graceful shutdown | ShutdownEndpointAutoConfiguration |
mappings | /actuator/mappings | GET | No | Request mappings | MappingsEndpointAutoConfiguration |
scheduledtasks | /actuator/scheduledtasks | GET | No | Scheduled tasks | ScheduledTasksEndpointAutoConfiguration |
httpexchanges | /actuator/httpexchanges | GET | No | HTTP request/response log | HttpExchangesEndpointAutoConfiguration |
auditevents | /actuator/auditevents | GET | No | Security audit events | AuditEventsEndpointAutoConfiguration |
sbom | /actuator/sbom | GET | No | Software Bill of Materials | SbomEndpointAutoConfiguration |
startup | /actuator/startup | GET | No | Application startup info | StartupEndpointAutoConfiguration |
logfile | /actuator/logfile | GET | No | Download log file | LogFileWebEndpointAutoConfiguration |
# Default: health (both web and jmx)
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=shutdown
management.endpoints.jmx.exposure.include=*
management.endpoints.jmx.exposure.exclude=
# Base paths
management.endpoints.web.base-path=/actuator
management.server.base-path=# Access levels: UNRESTRICTED, READ_ONLY, NONE
management.endpoints.access.default=READ_ONLY
management.endpoints.access.max-permitted=UNRESTRICTED
management.endpoint.<id>.access=UNRESTRICTED# Port configuration
management.server.port=8081 # Separate port
management.server.port=-1 # Disable management
# (not set = same as server.port)
management.server.address=127.0.0.1 # Bind address
management.server.base-path=/admin # Additional base path# Health
management.endpoint.health.show-details=always|never|when-authorized
# Environment & ConfigProps
management.endpoint.env.show-values=NEVER|ALWAYS|WHEN_AUTHORIZED
management.endpoint.env.roles=ADMIN
management.endpoint.configprops.show-values=NEVER|ALWAYS|WHEN_AUTHORIZED
management.endpoint.configprops.roles=ADMIN
# Info Contributors
management.info.git.enabled=true
management.info.git.mode=SIMPLE|FULL
management.info.env.enabled=true
management.info.java.enabled=true
management.info.defaults.enabled=true
# HTTP Exchanges
management.httpexchanges.recording.include=TIME_TAKEN,REQUEST_HEADERS,RESPONSE_HEADERS
# Caching
management.endpoint.<id>.cache.time-to-live=10smanagement.endpoints.web.cors.allowed-origins=https://example.com
management.endpoints.web.cors.allowed-methods=GET,POST
management.endpoints.web.cors.allowed-headers=*
management.endpoints.web.cors.allow-credentials=true
management.endpoints.web.cors.max-age=3600Core infrastructure for endpoint discovery, filtering, parameter mapping, caching, and access control.
@AutoConfiguration
public final class EndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean
ParameterValueMapper endpointOperationParameterMapper(
@EndpointConverter ObjectProvider<Converter<?, ?>> converters,
@EndpointConverter ObjectProvider<GenericConverter> genericConverters
);
@Bean
@ConditionalOnMissingBean
CachingOperationInvokerAdvisor endpointCachingOperationInvokerAdvisor(Environment environment);
@Bean
@ConditionalOnMissingBean(EndpointAccessResolver.class)
PropertiesEndpointAccessResolver propertiesEndpointAccessResolver(Environment environment);
}
public class PropertiesEndpointAccessResolver implements EndpointAccessResolver {
public Access accessFor(EndpointId endpointId, Access defaultAccess);
}Configures JSON serialization for endpoint responses using Jackson.
/**
* Auto-configuration for endpoint JSON serialization (Jackson 3)
*/
@AutoConfiguration
@ConditionalOnClass(JsonMapper.class)
public final class JacksonEndpointAutoConfiguration {
/**
* Provides isolated JSON mapper for endpoint serialization
* Uses separate ObjectMapper instance to avoid conflicts with application JSON configuration
*/
@Bean
@ConditionalOnBooleanProperty(name = "management.endpoints.jackson.isolated-json-mapper", matchIfMissing = true)
EndpointJsonMapper endpointJsonMapper();
}
/**
* Auto-configuration for endpoint JSON serialization (Jackson 2 - DEPRECATED)
* @deprecated since 4.0.0, scheduled for removal in 4.2.0
* Use JacksonEndpointAutoConfiguration instead (Jackson 3)
*/
@Deprecated(since = "4.0.0", forRemoval = true)
@SuppressWarnings("removal")
@AutoConfiguration
@ConditionalOnClass({ ObjectMapper.class, Jackson2ObjectMapperBuilder.class })
public final class Jackson2EndpointAutoConfiguration {
/**
* Provides Jackson 2 based JSON mapper for endpoints
* @deprecated Use JacksonEndpointAutoConfiguration instead
*/
@Bean
@Deprecated(since = "4.0.0", forRemoval = true)
EndpointJackson2ObjectMapper jackson2EndpointJsonMapper();
}Properties:
# Jackson 3 - Enable/disable isolated JSON mapper (default: true)
management.endpoints.jackson.isolated-json-mapper=true
# Jackson 2 (deprecated) - Enable/disable isolated object mapper (default: true)
management.endpoints.jackson2.isolated-object-mapper=trueKey Features:
Migration Note: Applications using Jackson 2 should migrate to Jackson 3. Jackson2EndpointAutoConfiguration is deprecated since 4.0.0 and will be removed in 4.2.0.
Configures HTTP exposure of actuator endpoints, including path mapping, filtering, and CORS.
@AutoConfiguration
@ConditionalOnWebApplication
public final class WebEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean(WebEndpointsSupplier.class)
WebEndpointDiscoverer webEndpointDiscoverer(
ParameterValueMapper parameterValueMapper,
EndpointMediaTypes endpointMediaTypes,
ObjectProvider<PathMapper> endpointPathMappers,
ObjectProvider<AdditionalPathsMapper> additionalPathsMappers,
ObjectProvider<OperationInvokerAdvisor> invokerAdvisors,
ObjectProvider<EndpointFilter<ExposableWebEndpoint>> endpointFilters,
ObjectProvider<OperationFilter<WebOperation>> operationFilters
);
@Bean
PathMapper webEndpointPathMapper();
@Bean
PathMappedEndpoints pathMappedEndpoints(
Collection<EndpointsSupplier<?>> endpointSuppliers
);
}
@ConfigurationProperties("management.endpoints.web")
public class WebEndpointProperties {
private String basePath = "/actuator";
private Map<String, String> pathMapping = new LinkedHashMap<>();
private Exposure exposure = new Exposure();
private Discovery discovery = new Discovery();
public static class Exposure {
private Set<String> include = new LinkedHashSet<>();
private Set<String> exclude = new LinkedHashSet<>();
}
}
@ConfigurationProperties("management.endpoints.web.cors")
public class CorsEndpointProperties {
private List<String> allowedOrigins = new ArrayList<>();
private List<String> allowedOriginPatterns = new ArrayList<>();
private List<String> allowedMethods = new ArrayList<>();
private List<String> allowedHeaders = new ArrayList<>();
private List<String> exposedHeaders = new ArrayList<>();
private Boolean allowCredentials;
private Duration maxAge = Duration.ofSeconds(1800);
/**
* Converts to Spring CorsConfiguration
* @return CorsConfiguration or null if no origins/origin patterns configured
*/
public @Nullable CorsConfiguration toCorsConfiguration();
}Configures JMX MBean exposure of actuator endpoints.
@AutoConfiguration
@ConditionalOnBooleanProperty("spring.jmx.enabled")
public final class JmxEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean(JmxEndpointsSupplier.class)
JmxEndpointDiscoverer jmxAnnotationEndpointDiscoverer(
ParameterValueMapper parameterValueMapper,
ObjectProvider<OperationInvokerAdvisor> invokerAdvisors,
ObjectProvider<EndpointFilter<ExposableJmxEndpoint>> endpointFilters,
ObjectProvider<OperationFilter<JmxOperation>> operationFilters
);
@Bean
@ConditionalOnMissingBean(value = EndpointObjectNameFactory.class, search = SearchStrategy.CURRENT)
DefaultEndpointObjectNameFactory endpointObjectNameFactory(MBeanServer mBeanServer);
/**
* JmxEndpointExporter is configured in nested configuration classes
* See: JmxEndpointConfiguration and JmxEndpointDiscoveryConfiguration
*/
@Bean
JmxEndpointExporter jmxEndpointExporter(
JmxEndpointDiscoverer jmxEndpointDiscoverer,
EndpointObjectNameFactory endpointObjectNameFactory
);
}
@ConfigurationProperties("management.endpoints.jmx")
public class JmxEndpointProperties {
private String domain;
private Properties staticNames = new Properties();
private Exposure exposure = new Exposure();
public static class Exposure {
private Set<String> include = new LinkedHashSet<>();
private Set<String> exclude = new LinkedHashSet<>();
}
}Configures a separate management server on a different port with independent SSL configuration.
/**
* Auto-configuration for management context initialization
* Creates child management context when using separate management port
* Contains nested configurations for SAME and DIFFERENT management port types
*/
@AutoConfiguration
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
public final class ManagementContextAutoConfiguration {
/**
* Configuration for when management endpoints run on same port as application
* Validates that management-specific SSL and address are not configured
* Adds 'local.management.port' property alias
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnManagementPort(ManagementPortType.SAME)
static class SameManagementContextConfiguration implements SmartInitializingSingleton {
/**
* Constructor injecting environment for validation
* @param environment Spring environment
*/
SameManagementContextConfiguration(Environment environment);
/**
* Called after all singletons are instantiated
* Performs validation and property alias setup
*/
@Override
void afterSingletonsInstantiated();
/**
* Inner configuration that enables ManagementContextConfiguration imports
* for SAME context type
*/
@Configuration(proxyBeanMethods = false)
@EnableManagementContext(ManagementContextType.SAME)
static class EnableSameManagementContextConfiguration {
}
}
/**
* Configuration for when management endpoints run on different port
* Enables ManagementServerProperties and creates child context initializer
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnManagementPort(ManagementPortType.DIFFERENT)
@EnableConfigurationProperties(ManagementServerProperties.class)
static class DifferentManagementContextConfiguration {
/**
* Creates child management context initializer for separate management port
* ManagementContextFactory is injected as parameter (not created by this config)
* @param managementContextFactory Factory for creating management context
* @param parentContext The parent application context
* @return Child context initializer
*/
@Bean
static ChildManagementContextInitializer childManagementContextInitializer(
ManagementContextFactory managementContextFactory,
AbstractApplicationContext parentContext
);
}
}
@ConfigurationProperties("management.server")
public class ManagementServerProperties {
private Integer port;
private InetAddress address;
private String basePath = "";
/**
* SSL configuration for management server
* Type: org.springframework.boot.web.server.Ssl (from Spring Boot core)
* Only applies when using separate management port (ManagementPortType.DIFFERENT)
* Uses standard Spring Boot SSL configuration properties
*/
private Ssl ssl;
}
public enum ManagementPortType {
DISABLED, // management.server.port=-1
SAME, // port not specified or same as server.port
DIFFERENT; // different port specified
public static ManagementPortType get(Environment environment);
}Management Server Configuration
Custom Spring conditional annotations for endpoint availability and configuration.
import org.springframework.boot.actuate.autoconfigure.endpoint.expose.EndpointExposure;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Conditional(OnAvailableEndpointCondition.class)
public @interface ConditionalOnAvailableEndpoint {
Class<?> endpoint() default Void.class;
Class<?> value() default Void.class;
EndpointExposure[] exposure() default {};
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Conditional(OnEnabledInfoContributorCondition.class)
public @interface ConditionalOnEnabledInfoContributor {
String value();
InfoContributorFallback fallback() default InfoContributorFallback.USE_DEFAULTS_PROPERTY;
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Conditional(OnManagementPortCondition.class)
public @interface ConditionalOnManagementPort {
ManagementPortType value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Configuration(proxyBeanMethods = false)
public @interface ManagementContextConfiguration {
ManagementContextType value() default ManagementContextType.ANY;
boolean proxyBeanMethods() default true;
}Filters and discovers endpoints based on include/exclude patterns and access control.
public class IncludeExcludeEndpointFilter<E extends ExposableEndpoint<?>> implements EndpointFilter<E> {
public IncludeExcludeEndpointFilter(Class<E> endpointType, Environment environment, String prefix, String... defaultIncludes);
public IncludeExcludeEndpointFilter(Class<E> endpointType, Collection<String> include, Collection<String> exclude, String... defaultIncludes);
public boolean match(E endpoint);
public boolean match(EndpointId id);
}
public enum EndpointExposure {
JMX,
WEB;
public String[] getDefaultIncludes();
}
public interface EndpointExposureOutcomeContributor {
@Nullable
ConditionOutcome getExposureOutcome(
EndpointId endpointId,
Set<EndpointExposure> exposures,
ConditionMessage.Builder message
);
}Individual endpoint auto-configurations for monitoring, diagnostics, and application information.
Available Endpoints:
/auditevents) - Security audit event recording/beans) - Application context bean information/conditions) - Auto-configuration report/configprops) - @ConfigurationProperties beans/env) - Environment properties and property sources/heapdump) - Heap dump download/httpexchanges) - HTTP request/response recording/info) - Application information from contributors/logfile) - Log file download/loggers) - Logger levels (view and modify)/mappings) - Request mapping paths/sbom) - Software Bill of Materials/scheduledtasks) - Scheduled task information/shutdown) - Graceful application shutdown/startup) - Application startup information/threaddump) - Thread dump information// Example: Beans Endpoint
@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = BeansEndpoint.class)
public final class BeansEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean
BeansEndpoint beansEndpoint(ConfigurableApplicationContext applicationContext);
}
// Example: Conditions Report Endpoint
@Endpoint(id = "conditions")
public class ConditionsReportEndpoint {
@ReadOperation
public ConditionsDescriptor conditions();
public static final class ConditionsDescriptor implements OperationResponseBody {
private final Map<String, ContextConditionsDescriptor> contexts;
/**
* Creates a conditions descriptor
* Private constructor - used internally by the endpoint
* @param contexts Map of context ID to context conditions
*/
private ConditionsDescriptor(Map<@Nullable String, ContextConditionsDescriptor> contexts);
public Map<String, ContextConditionsDescriptor> getContexts();
}
@JsonInclude(Include.NON_EMPTY)
public static final class ContextConditionsDescriptor {
private final Map<String, List<MessageAndConditionDescriptor>> positiveMatches;
private final Map<String, MessageAndConditionsDescriptor> negativeMatches;
private final List<String> exclusions;
private final Set<String> unconditionalClasses;
private final @Nullable String parentId;
/**
* Creates a context conditions descriptor from application context
* @param context The application context to analyze
*/
public ContextConditionsDescriptor(ConfigurableApplicationContext context);
public Map<String, List<MessageAndConditionDescriptor>> getPositiveMatches();
public Map<String, MessageAndConditionsDescriptor> getNegativeMatches();
public List<String> getExclusions();
public Set<String> getUnconditionalClasses();
public @Nullable String getParentId();
}
@JsonPropertyOrder({ "notMatched", "matched" })
public static class MessageAndConditionsDescriptor {
private final List<MessageAndConditionDescriptor> notMatched;
private final List<MessageAndConditionDescriptor> matched;
/**
* Creates a descriptor from condition and outcomes
* @param conditionAndOutcomes The conditions and their evaluation outcomes
*/
public MessageAndConditionsDescriptor(ConditionAndOutcomes conditionAndOutcomes);
public List<MessageAndConditionDescriptor> getNotMatched();
public List<MessageAndConditionDescriptor> getMatched();
}
@JsonPropertyOrder({ "condition", "message" })
public static class MessageAndConditionDescriptor {
private final String condition;
private final String message;
/**
* Creates a descriptor from single condition and outcome
* @param conditionAndOutcome The condition and its evaluation outcome
*/
public MessageAndConditionDescriptor(ConditionAndOutcome conditionAndOutcome);
public String getCondition();
public String getMessage();
}
}
// Example: Info Endpoint with Contributors
@AutoConfiguration(after = InfoContributorAutoConfiguration.class)
@ConditionalOnAvailableEndpoint(endpoint = InfoEndpoint.class)
public final class InfoEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean
InfoEndpoint infoEndpoint(ObjectProvider<InfoContributor> infoContributors);
}
@AutoConfiguration(after = ProjectInfoAutoConfiguration.class)
@EnableConfigurationProperties(InfoContributorProperties.class)
public final class InfoContributorAutoConfiguration {
/**
* The default order for the core {@link InfoContributor} beans.
* Set to HIGHEST_PRECEDENCE + 10 to run before most other contributors.
*/
public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 10;
@Bean
@Order(DEFAULT_ORDER)
@ConditionalOnEnabledInfoContributor(value = "env", fallback = InfoContributorFallback.DISABLE)
public EnvironmentInfoContributor envInfoContributor(ConfigurableEnvironment environment);
@Bean
@ConditionalOnEnabledInfoContributor("git")
@ConditionalOnSingleCandidate(GitProperties.class)
@ConditionalOnMissingBean
@Order(DEFAULT_ORDER)
public GitInfoContributor gitInfoContributor(GitProperties gitProperties, InfoContributorProperties infoContributorProperties);
@Bean
@ConditionalOnEnabledInfoContributor("build")
@ConditionalOnSingleCandidate(BuildProperties.class)
@Order(DEFAULT_ORDER)
public InfoContributor buildInfoContributor(BuildProperties properties);
@Bean
@Order(DEFAULT_ORDER)
@ConditionalOnEnabledInfoContributor(value = "java", fallback = InfoContributorFallback.DISABLE)
public JavaInfoContributor javaInfoContributor();
@Bean
@Order(DEFAULT_ORDER)
@ConditionalOnEnabledInfoContributor(value = "os", fallback = InfoContributorFallback.DISABLE)
public OsInfoContributor osInfoContributor();
@Bean
@Order(DEFAULT_ORDER)
@ConditionalOnEnabledInfoContributor(value = "process", fallback = InfoContributorFallback.DISABLE)
public ProcessInfoContributor processInfoContributor();
@Bean
@Order(DEFAULT_ORDER)
@ConditionalOnEnabledInfoContributor(value = "ssl", fallback = InfoContributorFallback.DISABLE)
public SslInfoContributor sslInfoContributor(SslInfo sslInfo);
@Bean
@ConditionalOnMissingBean
public SslInfo sslInfo(SslBundles sslBundles);
}Typed configuration classes for endpoint-specific settings.
import org.springframework.boot.actuate.endpoint.Show;
@ConfigurationProperties("management.endpoint.configprops")
public class ConfigurationPropertiesReportEndpointProperties {
private Show showValues = Show.NEVER;
private Set<String> roles = new LinkedHashSet<>();
}
@ConfigurationProperties("management.endpoint.env")
public class EnvironmentEndpointProperties {
private Show showValues = Show.NEVER;
private Set<String> roles = new LinkedHashSet<>();
}
// Note: Show enum is defined in org.springframework.boot.actuate.endpoint.Show
// (spring-boot-actuator module). See Type System Reference section below.
@ConfigurationProperties("management.endpoint.logfile")
public class LogFileWebEndpointProperties {
private File externalFile;
}
@ConfigurationProperties("management.info")
public class InfoContributorProperties {
private Git git = new Git();
/**
* Gets the Git info contributor properties
* @return Git properties
*/
public Git getGit();
/**
* Git info contributor properties
*/
public static class Git {
/**
* Mode to use to expose git information
* Default: SIMPLE
*
* Note: GitInfoContributor.Mode is from org.springframework.boot.actuate.info
* (spring-boot-actuator module, not autoconfigure)
*/
private GitInfoContributor.Mode mode = GitInfoContributor.Mode.SIMPLE;
/**
* Gets the git info mode
* @return The git info mode
*/
public GitInfoContributor.Mode getMode();
/**
* Sets the git info mode
* @param mode The git info mode
*/
public void setMode(GitInfoContributor.Mode mode);
}
}
@ConfigurationProperties("management.httpexchanges")
public class HttpExchangesProperties {
private Recording recording = new Recording();
public static class Recording {
/**
* Items to be included in the exchange recording
* Defaults to TIME_TAKEN, REQUEST_HEADERS, and RESPONSE_HEADERS
* (excluding Authorization and Cookie headers)
*
* Note: Include enum is from org.springframework.boot.actuate.web.exchanges.Include
* (spring-boot-actuator module, not autoconfigure)
*/
private Set<Include> include = new HashSet<>(Include.defaultIncludes());
/**
* Include enum type - from spring-boot-actuator module
* Package: org.springframework.boot.actuate.web.exchanges
*/
public enum Include {
REQUEST_HEADERS,
RESPONSE_HEADERS,
COOKIE_HEADERS,
AUTHORIZATION_HEADER,
TIME_TAKEN,
PRINCIPAL,
REMOTE_ADDRESS,
SESSION_ID;
/**
* Returns the default includes: TIME_TAKEN, REQUEST_HEADERS, RESPONSE_HEADERS
*/
public static Set<Include> defaultIncludes();
}
}
}Endpoint Configuration Properties
management.endpoints.web.exposure.include=*
management.endpoint.env.show-values=ALWAYS
management.endpoint.configprops.show-values=ALWAYS
management.httpexchanges.recording.include=REQUEST_HEADERS,RESPONSE_HEADERS,TIME_TAKENmanagement.endpoints.web.exposure.include=health,info,metrics,prometheus
management.endpoints.web.exposure.exclude=shutdown,heapdump,threaddump
management.endpoint.env.show-values=NEVER
management.endpoint.configprops.show-values=NEVER
management.server.port=8081
management.server.address=127.0.0.1# Health checks on main port
management.endpoint.health.probes.enabled=true
server.port=8080
# Full actuator on separate internal port
management.server.port=8081
management.server.address=0.0.0.0
management.endpoints.web.exposure.include=*server.port=8080
management.server.port=8443
management.server.ssl.enabled=true
management.server.ssl.key-store=classpath:mgmt-keystore.p12
management.server.ssl.key-store-password=changeit
management.endpoints.web.exposure.include=health,info,metricsPossible causes:
management.endpoints.web.exposure.includemanagement.endpoint.<id>.access or .enabledmanagement.endpoints.web.base-path and path mappingsSolution:
# Debug exposure
management.endpoints.web.exposure.include=*
logging.level.org.springframework.boot.actuate=DEBUGPossible causes:
show-values set to ALWAYS in productionSolution:
management.endpoint.env.show-values=NEVER
management.endpoint.configprops.show-values=NEVER
management.endpoints.web.exposure.include=health,info,metricsSymptom: Address already in use on management port
Solution:
# Change management port or use same port
management.server.port=8082
# OR
management.server.port=${server.port}Possible causes:
@Component or @Bean registration@ConditionalOnAvailableEndpoint condition not metSolution:
// Ensure @Component or @Bean
@Component
@Endpoint(id = "custom")
public class CustomEndpoint { }# Ensure exposed
management.endpoint.custom.access=UNRESTRICTED
management.endpoints.web.exposure.include=customPossible causes:
info.* properties setgit.properties or build-info.propertiesSolution:
# Enable contributors
management.info.git.enabled=true
management.info.env.enabled=true
management.info.java.enabled=true
# Add custom info
info.app.name=My Application
info.app.version=1.0.0| Feature | Min Version | Notes |
|---|---|---|
| Jackson 3 support | 4.0.0 | Jackson 2 deprecated, removed in 4.2.0 |
access property (vs enabled) | 3.4.0 | enabled deprecated |
@ManagementContextConfiguration | 2.0.0 | For child context configuration |
EndpointExposureOutcomeContributor | 3.4.0 | SPI for custom exposure logic |
@ReadOperation methods should be fast (<1s typical)| Endpoint | Limitation | Workaround |
|---|---|---|
heapdump | Only works with HotSpot JVM | Not available on other JVMs |
threaddump | May impact performance under load | Use sampling profiler instead |
logfile | Requires file-based logging | Configure logging.file.name |
shutdown | Irreversible operation | Requires explicit enablement |
httpexchanges | In-memory only, limited capacity | Use dedicated APM tool for production |
auditevents | Requires AuditEventRepository bean | Implement custom repository |
startup | Requires BufferingApplicationStartup | Configure at application start |
# DON'T
management.endpoints.web.exposure.include=*Why: Exposes sensitive information and dangerous operations.
Do instead:
# DO
management.endpoints.web.exposure.include=health,info,metrics,prometheus# DON'T
management.endpoint.env.show-values=ALWAYS
management.endpoint.configprops.show-values=ALWAYSWhy: Exposes secrets, passwords, API keys.
Do instead:
# DO
management.endpoint.env.show-values=WHEN_AUTHORIZED
management.endpoint.env.roles=ADMIN// DON'T
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) {
http.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
return http.build();
}Do instead:
// DO
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) {
http.securityMatcher(EndpointRequest.toAnyEndpoint())
.authorizeHttpRequests(auth -> auth
.requestMatchers(EndpointRequest.to("health", "info")).permitAll()
.anyRequest().hasRole("ACTUATOR"));
return http.build();
}// DON'T
@Endpoint(id = "slow")
public class SlowEndpoint {
@ReadOperation
public String getData() throws InterruptedException {
Thread.sleep(30000); // Blocks for 30 seconds
return "data";
}
}Do instead:
// DO
@Endpoint(id = "fast")
public class FastEndpoint {
@ReadOperation
public String getData() {
return cache.get("data"); // Quick cache lookup
}
}/**
* Endpoint access levels
* Controls what operations can be performed on an endpoint
* @since 3.4.0
*/
public enum Access {
/**
* UNRESTRICTED - Full access to all operations
* Allows READ, WRITE, and DELETE operations
* Use for: Public endpoints like health, info
*/
UNRESTRICTED,
/**
* READ_ONLY - Read operations only
* Allows READ operations, blocks WRITE and DELETE
* Use for: Endpoints that should be monitored but not modified (beans, env, metrics)
*/
READ_ONLY,
/**
* NONE - Endpoint is disabled
* Blocks all operations, endpoint will not be exposed
* Use for: Disabling specific endpoints (shutdown, threaddump in production)
*/
NONE
}
/**
* Operation types for endpoints
*/
public enum OperationType {
READ, // Query operation (safe, idempotent) - maps to HTTP GET
WRITE, // Mutating operation - maps to HTTP POST/PUT
DELETE // Deletion operation - maps to HTTP DELETE
}
/**
* Endpoint exposure technologies
*/
public enum EndpointExposure {
JMX, // JMX MBean exposure
WEB; // HTTP/JSON exposure
/**
* Gets default includes for this exposure type
* @return Array of endpoint IDs to include by default
*/
public String[] getDefaultIncludes();
}
/**
* Management port types for @ConditionalOnManagementPort
*/
public enum ManagementPortType {
/**
* Management endpoints disabled (management.server.port=-1)
*/
DISABLED,
/**
* Management endpoints on same port as application
* Used when management.server.port is not set or same as server.port
*/
SAME,
/**
* Management endpoints on separate port
* Used when management.server.port is set to a different port
*/
DIFFERENT;
/**
* Determines the management port type from environment
* @param environment Spring environment
* @return The management port type
*/
public static ManagementPortType get(Environment environment);
}
/**
* Management context types for @ManagementContextConfiguration
* @since 2.0.0
*/
public enum ManagementContextType {
/**
* Management endpoints in same context as application
* Used when management.server.port is not set or same as server.port
*/
SAME,
/**
* Management endpoints in separate child context
* Used when management.server.port is set to a different port
*/
CHILD,
/**
* Configuration applies to any context type (default)
* Used for configurations that should be available in both SAME and CHILD contexts
*/
ANY
}
/**
* Controls when to show unsanitized property values in endpoints
* Used by ConfigurationPropertiesReportEndpointProperties and EnvironmentEndpointProperties
* Located in: org.springframework.boot.actuate.endpoint.Show (spring-boot-actuator module)
* @since 2.0.0
*/
public enum Show {
/**
* Never show unsanitized values (always sanitize sensitive data)
*/
NEVER,
/**
* Always show unsanitized values (not recommended in production)
*/
ALWAYS,
/**
* Show unsanitized values only when user has required roles
*/
WHEN_AUTHORIZED
}
/**
* Info contributor fallback behavior
*/
public enum InfoContributorFallback {
USE_DEFAULTS_PROPERTY, // Use management.info.defaults.enabled as fallback
DISABLE // Disable if specific property not set
}/**
* Filters endpoints based on custom criteria
* @param <E> Type of exposable endpoint
*/
@FunctionalInterface
public interface EndpointFilter<E extends ExposableEndpoint<?>> {
/**
* Tests if an endpoint should be included
* @param endpoint The endpoint to test
* @return true if endpoint should be included, false otherwise
*/
boolean match(E endpoint);
}
/**
* Resolves endpoint access levels from configuration
*/
public interface EndpointAccessResolver {
/**
* Determines the access level for an endpoint
* @param endpointId The endpoint identifier
* @param defaultAccess The default access level
* @return The resolved access level
*/
Access accessFor(EndpointId endpointId, Access defaultAccess);
}
/**
* Contributes information to the info endpoint
*/
public interface InfoContributor {
/**
* Contributes information to the info endpoint
* @param builder The info builder
*/
void contribute(Info.Builder builder);
}
/**
* Maps parameter values from strings to required types
* Used when invoking endpoint operations via web or JMX
*/
public interface ParameterValueMapper {
/**
* Maps a parameter value to the required type
* @param parameter Operation parameter metadata
* @param value String value from request (may be null)
* @return Converted value
* @throws ParameterMappingException if conversion fails
*/
Object mapParameterValue(OperationParameter parameter, @Nullable Object value)
throws ParameterMappingException;
}
/**
* Maps endpoint IDs to URL paths
*/
public interface PathMapper {
/**
* Gets the root path for an endpoint
* @param endpointId Endpoint ID
* @return Root path (e.g., "health" or "healthcheck")
*/
String getRootPath(EndpointId endpointId);
}
/**
* Invokes an endpoint operation
*/
@FunctionalInterface
public interface OperationInvoker {
/**
* Invokes the operation
* @param context The invocation context
* @return The operation result
*/
Object invoke(InvocationContext context);
}
/**
* Applies caching behavior to endpoint operations
*/
public interface CachingOperationInvokerAdvisor {
/**
* Applies caching to an operation invoker
* @param endpointId Endpoint ID
* @param operationType Operation type (READ, WRITE, DELETE)
* @param parameters Operation parameters
* @param invoker Original invoker
* @return Wrapped invoker with caching
*/
OperationInvoker apply(
EndpointId endpointId,
OperationType operationType,
OperationParameters parameters,
OperationInvoker invoker
);
}
/**
* Provides endpoint identifier
*/
public interface EndpointIdProvider {
/**
* Gets the endpoint ID
* @return The endpoint ID
*/
EndpointId getEndpointId();
}
/**
* Supplies a collection of endpoints
* @param <E> Type of exposable endpoint
*/
@FunctionalInterface
public interface EndpointsSupplier<E extends ExposableEndpoint<?>> {
/**
* Gets all endpoints
* @return Collection of endpoints
*/
Collection<E> getEndpoints();
}
/**
* Creates JMX object names for endpoints
*/
public interface EndpointObjectNameFactory {
/**
* Gets the JMX ObjectName for an endpoint
* @param endpoint The JMX endpoint
* @return The ObjectName
* @throws MalformedObjectNameException if the name is invalid
*/
ObjectName getObjectName(ExposableJmxEndpoint endpoint) throws MalformedObjectNameException;
}
/**
* Contributes to endpoint exposure outcome determination
* @since 3.4.0
*/
public interface EndpointExposureOutcomeContributor {
/**
* Gets the exposure outcome for an endpoint
* @param endpointId The endpoint ID
* @param exposures The exposure technologies
* @param message Message builder for logging
* @return The condition outcome, or null to continue evaluation
*/
@Nullable
ConditionOutcome getExposureOutcome(
EndpointId endpointId,
Set<EndpointExposure> exposures,
ConditionMessage.Builder message
);
}/**
* Represents an endpoint identifier
* Immutable, normalized representation of an endpoint ID
*/
public final class EndpointId {
/**
* Creates an endpoint ID from a string value
* @param value The endpoint ID value (e.g., "health", "custom-endpoint")
* @return The endpoint ID
* @throws IllegalArgumentException if value is invalid
*/
public static EndpointId of(String value);
/**
* Creates an endpoint ID from a property value
* Normalizes the value (e.g., converts kebab-case/snake_case to lowercase)
* @param value The property value
* @return The endpoint ID
*/
public static EndpointId fromPropertyValue(String value);
/**
* Returns the string representation of this endpoint ID
* @return The endpoint ID as a string
*/
@Override
public String toString();
/**
* Returns the lower-case string representation of this endpoint ID
* @return The endpoint ID as a lower-case string
*/
public String toLowerCaseString();
/**
* Compares this endpoint ID to another object
* @param obj The object to compare
* @return true if equal
*/
@Override
public boolean equals(Object obj);
/**
* Returns the hash code for this endpoint ID
* @return The hash code
*/
@Override
public int hashCode();
}
/**
* Context for operation invocation
*/
public interface InvocationContext {
/**
* Gets the operation arguments
* @return Map of argument names to values
*/
Map<String, Object> getArguments();
/**
* Gets the security context
* @return The security context
*/
SecurityContext getSecurityContext();
}
/**
* Exception thrown when parameter mapping fails
*/
public class ParameterMappingException extends RuntimeException {
public ParameterMappingException(String message, Throwable cause);
}
/**
* Media types supported by endpoints
*/
public class EndpointMediaTypes {
private final List<String> produced;
private final List<String> consumed;
/**
* Creates endpoint media types
* @param produced Media types produced by endpoints
* @param consumed Media types consumed by endpoints
*/
public EndpointMediaTypes(List<String> produced, List<String> consumed);
/**
* Gets media types produced by endpoints
* @return Produced media types
*/
public List<String> getProduced();
/**
* Gets media types consumed by endpoints
* @return Consumed media types
*/
public List<String> getConsumed();
}
/**
* Collection of all path-mapped endpoints
*/
public class PathMappedEndpoints implements Iterable<PathMappedEndpoint> {
/**
* Gets the base path for all endpoints
* @return Base path (e.g., "/actuator")
*/
public String getBasePath();
/**
* Gets root path for endpoint with given ID
* @param endpointId Endpoint ID
* @return Root path or null if not found
*/
public String getRootPath(EndpointId endpointId);
/**
* Gets full path for endpoint with given ID
* @param endpointId Endpoint ID
* @return Full path (base path + root path) or null if not found
*/
public String getPath(EndpointId endpointId);
/**
* Gets endpoint by ID
* @param endpointId Endpoint ID
* @return PathMappedEndpoint or null if not found
*/
public PathMappedEndpoint getEndpoint(EndpointId endpointId);
/**
* Gets all root paths (excluding additional paths)
* @return Collection of root paths
*/
public Collection<String> getAllRootPaths();
/**
* Gets all full paths (excluding additional paths)
* @return Collection of full paths
*/
public Collection<String> getAllPaths();
/**
* Gets additional paths for given endpoint
* @param webServerNamespace Web server namespace
* @param endpointId Endpoint ID
* @return Collection of additional paths
* @since 3.4.0
*/
public Collection<String> getAdditionalPaths(WebServerNamespace webServerNamespace, EndpointId endpointId);
/**
* Streams all path-mapped endpoints
* @return Stream of endpoints
*/
public Stream<PathMappedEndpoint> stream();
/**
* Returns an iterator over path-mapped endpoints
* @return Iterator of endpoints
*/
@Override
public Iterator<PathMappedEndpoint> iterator();
}
/**
* Web operation request predicate
*/
public class WebOperationRequestPredicate {
private final String path;
private final WebEndpointHttpMethod httpMethod;
private final Collection<String> consumes;
private final Collection<String> produces;
/**
* Gets the operation path
* @return The path
*/
public String getPath();
/**
* Gets the HTTP method
* @return The HTTP method
*/
public WebEndpointHttpMethod getHttpMethod();
/**
* Gets the consumed media types
* @return Consumed media types
*/
public Collection<String> getConsumes();
/**
* Gets the produced media types
* @return Produced media types
*/
public Collection<String> getProduces();
}
/**
* HTTP methods for web operations
*/
public enum WebEndpointHttpMethod {
GET,
POST,
DELETE
}@Configuration
public class ActuatorSecurityConfiguration {
@Bean
public SecurityFilterChain actuatorSecurity(HttpSecurity http) throws Exception {
http.securityMatcher(EndpointRequest.toAnyEndpoint())
.authorizeHttpRequests(auth -> auth
.requestMatchers(EndpointRequest.to("health", "info")).permitAll()
.requestMatchers(EndpointRequest.to("metrics", "prometheus")).hasRole("METRICS")
.anyRequest().hasRole("ACTUATOR"))
.httpBasic(Customizer.withDefaults());
return http.build();
}
}# Client configuration
spring.boot.admin.client.url=http://admin-server:8080
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=alwaysmanagement.endpoints.web.exposure.include=health,prometheus
management.metrics.export.prometheus.enabled=true@Configuration
public class MetricsConfiguration {
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config()
.commonTags("application", "my-app", "region", "us-east");
}
}Breaking changes:
Jackson 2 → Jackson 3: Update to Jackson 3 (Jackson 2 support deprecated)
<!-- Update dependency -->
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>enabled → access: Migrate from .enabled to .access properties
# OLD (deprecated)
management.endpoint.health.enabled=true
# NEW
management.endpoint.health.access=UNRESTRICTED@ControllerEndpoint/@ServletEndpoint: Migrate to @Endpoint with extensions
// OLD (deprecated since 3.3.0, scheduled for removal)
@ControllerEndpoint(id = "custom")
// NEW
@Endpoint(id = "custom")
@WebEndpoint@Bean
public EndpointFilter<ExposableWebEndpoint> customFilter() {
return endpoint -> {
// Custom filtering logic
return !endpoint.getEndpointId().toString().startsWith("internal");
};
}@Bean
public EndpointAccessResolver customAccessResolver() {
return (endpointId, defaultAccess) -> {
if (endpointId.toString().equals("shutdown")) {
return Access.NONE;
}
return defaultAccess;
};
}@Bean
public PathMapper customPathMapper() {
return endpointId -> {
String id = endpointId.toString();
return switch (id) {
case "health" -> "status";
case "info" -> "about";
default -> id;
};
};
}// Register in META-INF/spring/...EndpointExposureOutcomeContributor.imports
public class CustomExposureContributor implements EndpointExposureOutcomeContributor {
@Override
public ConditionOutcome getExposureOutcome(EndpointId id, Set<EndpointExposure> exposures, ConditionMessage.Builder message) {
// Custom exposure logic
return null; // or ConditionOutcome
}
}# Enable caching for expensive endpoints
management.endpoint.beans.cache.time-to-live=10s
management.endpoint.conditions.cache.time-to-live=30s
management.endpoint.mappings.cache.time-to-live=60s# Limit recording to reduce memory
management.httpexchanges.recording.include=TIME_TAKEN
# Default capacity: 100 entries
# Memory: ~1KB per exchangeWhen using separate management port:
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class CustomEndpointTest {
@LocalManagementPort
private int managementPort;
@Autowired
private TestRestTemplate restTemplate;
@Test
void customEndpointReturnsData() {
String url = "http://localhost:" + managementPort + "/actuator/custom";
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
}@SpringBootTest(properties = {
"management.endpoint.custom.access=UNRESTRICTED",
"management.endpoints.web.exposure.include=custom"
})
class EndpointAvailabilityTest {
@Autowired
private ApplicationContext context;
@Test
void customEndpointIsRegistered() {
assertThat(context.containsBean("customEndpoint")).isTrue();
}
}Understanding how the subsystems work together:
Application Startup
↓
1. Core Infrastructure Setup
→ [core-infrastructure.md](./core-infrastructure.md)
- EndpointAutoConfiguration creates parameter mappers, caching, access resolvers
- PropertiesEndpointAccessResolver reads access properties
↓
2. Endpoint Discovery & Registration
→ [management-endpoints.md](./management-endpoints.md)
- Individual endpoint auto-configurations register endpoint beans
- @ConditionalOnAvailableEndpoint checks exposure/access via [conditional-annotations.md](./conditional-annotations.md)
↓
3. Endpoint Filtering
→ [endpoint-filtering.md](./endpoint-filtering.md)
- IncludeExcludeEndpointFilter applies include/exclude patterns
- EndpointExposureOutcomeContributor (SPI) provides custom logic
↓
4. Exposure Configuration
→ [web-endpoints.md](./web-endpoints.md) | [jmx-endpoints.md](./jmx-endpoints.md)
- WebEndpointAutoConfiguration exposes via HTTP
- JmxEndpointAutoConfiguration exposes via JMX MBeans
- PathMapper maps endpoint IDs to URL paths
↓
5. Management Server Setup (Optional)
→ [management-server.md](./management-server.md)
- ManagementContextAutoConfiguration creates separate server if configured
- Separate port with independent SSL, thread pool, and context
↓
6. Endpoint Configuration
→ [endpoint-properties.md](./endpoint-properties.md)
- Endpoint-specific properties applied (show-values, roles, recording, etc.)
↓
7. Runtime Operation
- Incoming request → PathMappedEndpoints → WebOperation
- OperationFilter applies access control
- ParameterValueMapper converts parameters
- CachingOperationInvokerAdvisor caches if configured
- Operation invoked → Response returnedStarting Point → Related Documents → Purpose
| If You Need To... | Start Here | Then Check | Finally See |
|---|---|---|---|
| Configure endpoint exposure | web-endpoints.md | endpoint-filtering.md | conditional-annotations.md |
| Secure endpoints | core-infrastructure.md (Access Control) | endpoint-filtering.md (Filtering) | web-endpoints.md (CORS) |
| Create custom endpoint | management-endpoints.md (Examples) | core-infrastructure.md (Infrastructure) | web-endpoints.md (Exposure) |
| Separate management port | management-server.md | web-endpoints.md (Properties) | endpoint-properties.md (SSL Config) |
| Control access per-endpoint | core-infrastructure.md (Access Resolver) | endpoint-properties.md (Per-endpoint props) | endpoint-filtering.md (Operation filters) |
| Configure JMX exposure | jmx-endpoints.md | endpoint-filtering.md (Include/exclude) | conditional-annotations.md (@ConditionalOn...) |
| Debug why endpoint not available | endpoint-filtering.md (Filtering logic) | conditional-annotations.md (Conditions) | core-infrastructure.md (Access levels) |
| Configure CORS for endpoints | web-endpoints.md (CORS section) | endpoint-properties.md (Properties) | - |
Shows which documents cover interactions between components:
| Component A | Component B | Interaction Documented In |
|---|---|---|
| EndpointAutoConfiguration | WebEndpointAutoConfiguration | core-infrastructure.md, web-endpoints.md |
| IncludeExcludeEndpointFilter | @ConditionalOnAvailableEndpoint | endpoint-filtering.md, conditional-annotations.md |
| WebEndpointProperties | PathMapper | web-endpoints.md |
| ManagementServerProperties | ManagementContextAutoConfiguration | management-server.md |
| PropertiesEndpointAccessResolver | EndpointFilter | core-infrastructure.md, endpoint-filtering.md |
| Individual Endpoints | InfoContributor | management-endpoints.md |
| CorsEndpointProperties | WebEndpointAutoConfiguration | web-endpoints.md, endpoint-properties.md |
| Problem | Check These Docs (In Order) |
|---|---|
| Endpoint returns 404 | 1. endpoint-filtering.md (exposure)<br>2. web-endpoints.md (path mapping)<br>3. management-server.md (port) |
| Endpoint shows wrong values | 1. endpoint-properties.md (show-values)<br>2. management-endpoints.md (endpoint config) |
| Cannot write to endpoint | 1. core-infrastructure.md (access levels)<br>2. endpoint-filtering.md (operation filters) |
| CORS errors | 1. web-endpoints.md (CORS config)<br>2. endpoint-properties.md (properties) |
| Custom endpoint not registered | 1. conditional-annotations.md (conditions)<br>2. endpoint-filtering.md (filtering)<br>3. management-endpoints.md (registration) |
| Management port conflict | 1. management-server.md (port config)<br>2. web-endpoints.md (base path) |
Detailed subsystem documentation (see Subsystems Reference above):
Related Spring Boot and monitoring ecosystem: