0
# Endpoint Framework
1
2
The Spring Boot Actuator endpoint framework provides a unified, annotation-based system for creating management endpoints that can be exposed over multiple transports (HTTP, JMX, etc.). It supports both built-in and custom endpoints with flexible access control and operation definitions.
3
4
## Capabilities
5
6
### Core Endpoint Annotation
7
8
Primary annotation for defining actuator endpoints with configurable access control.
9
10
```java { .api }
11
/**
12
* Annotation for identifying a type as an actuator endpoint
13
*/
14
@Target(ElementType.TYPE)
15
@Retention(RetentionPolicy.RUNTIME)
16
@Documented
17
public @interface Endpoint {
18
19
/**
20
* The id of the endpoint (must be unique)
21
* @return the endpoint id
22
*/
23
String id();
24
25
/**
26
* The default access level for the endpoint
27
* @return the default access level
28
*/
29
Access defaultAccess() default Access.RESTRICTED;
30
31
/**
32
* Whether this endpoint should be enabled by default
33
* @return true if enabled by default
34
* @deprecated since 3.4.0 in favor of defaultAccess()
35
*/
36
@Deprecated(since = "3.4.0")
37
boolean enableByDefault() default true;
38
}
39
```
40
41
### Operation Annotations
42
43
Annotations for defining different types of endpoint operations.
44
45
```java { .api }
46
/**
47
* Annotation for read-only endpoint operations (HTTP GET)
48
*/
49
@Target(ElementType.METHOD)
50
@Retention(RetentionPolicy.RUNTIME)
51
@Documented
52
public @interface ReadOperation {
53
54
/**
55
* The media types produced by the operation
56
* @return the produced media types
57
*/
58
String[] produces() default {};
59
60
/**
61
* The media types produced by the operation, as an enum
62
* @return the produced media types
63
*/
64
WebEndpointHttpMethod[] producesFrom() default {};
65
}
66
67
/**
68
* Annotation for write endpoint operations (HTTP POST)
69
*/
70
@Target(ElementType.METHOD)
71
@Retention(RetentionPolicy.RUNTIME)
72
@Documented
73
public @interface WriteOperation {
74
75
/**
76
* The media types produced by the operation
77
* @return the produced media types
78
*/
79
String[] produces() default {};
80
81
/**
82
* The media types produced by the operation, as an enum
83
* @return the produced media types
84
*/
85
WebEndpointHttpMethod[] producesFrom() default {};
86
}
87
88
/**
89
* Annotation for delete endpoint operations (HTTP DELETE)
90
*/
91
@Target(ElementType.METHOD)
92
@Retention(RetentionPolicy.RUNTIME)
93
@Documented
94
public @interface DeleteOperation {
95
96
/**
97
* The media types produced by the operation
98
* @return the produced media types
99
*/
100
String[] produces() default {};
101
102
/**
103
* The media types produced by the operation, as an enum
104
* @return the produced media types
105
*/
106
WebEndpointHttpMethod[] producesFrom() default {};
107
}
108
109
/**
110
* Annotation for method parameters that should be treated as path selectors
111
*/
112
@Target(ElementType.PARAMETER)
113
@Retention(RetentionPolicy.RUNTIME)
114
@Documented
115
public @interface Selector {
116
// Marker annotation - no properties
117
}
118
```
119
120
### Web Extensions
121
122
Annotations for creating web-specific endpoint extensions and controllers.
123
124
```java { .api }
125
/**
126
* Annotation for web-specific endpoint extensions
127
*/
128
@Target(ElementType.TYPE)
129
@Retention(RetentionPolicy.RUNTIME)
130
@Documented
131
public @interface EndpointWebExtension {
132
133
/**
134
* The endpoint class this extension targets
135
* @return the endpoint class
136
*/
137
Class<?> endpoint();
138
}
139
140
/**
141
* Annotation for controller-based endpoints (DEPRECATED)
142
* @deprecated since 3.3.0 in favor of @Endpoint and @EndpointWebExtension
143
*/
144
@Target(ElementType.TYPE)
145
@Retention(RetentionPolicy.RUNTIME)
146
@Documented
147
@Deprecated(since = "3.3.0")
148
public @interface ControllerEndpoint {
149
150
/**
151
* The id of the endpoint (must be unique)
152
* @return the endpoint id
153
*/
154
String id();
155
}
156
```
157
158
### Core Framework Interfaces
159
160
Base interfaces that define the endpoint framework structure.
161
162
```java { .api }
163
/**
164
* Interface for endpoints that can be exposed
165
*/
166
public interface ExposableEndpoint<O extends Operation> {
167
168
/**
169
* Return the endpoint ID
170
* @return the endpoint ID
171
*/
172
EndpointId getEndpointId();
173
174
/**
175
* Return true if the endpoint is enabled by default
176
* @return true if enabled by default
177
*/
178
boolean isEnableByDefault();
179
180
/**
181
* Return the operations for this endpoint
182
* @return the operations
183
*/
184
Collection<O> getOperations();
185
}
186
187
/**
188
* A single operation that can be performed on an endpoint
189
*/
190
public interface Operation {
191
192
/**
193
* Return the operation type
194
* @return the operation type
195
*/
196
OperationType getType();
197
198
/**
199
* Invoke the operation
200
* @param context the invocation context
201
* @return the operation result
202
*/
203
Object invoke(InvocationContext context);
204
}
205
206
/**
207
* Filter for endpoints
208
*/
209
@FunctionalInterface
210
public interface EndpointFilter<E extends ExposableEndpoint<?>> {
211
212
/**
213
* Return true if the endpoint matches the filter
214
* @param endpoint the endpoint to test
215
* @return true if the endpoint matches
216
*/
217
boolean match(E endpoint);
218
}
219
```
220
221
### Endpoint Identification
222
223
Value objects for endpoint identification and access control.
224
225
```java { .api }
226
/**
227
* An endpoint ID
228
*/
229
public final class EndpointId {
230
231
/**
232
* Create an endpoint ID from a string
233
* @param value the endpoint ID value
234
* @return the endpoint ID
235
*/
236
public static EndpointId of(String value) { /* ... */ }
237
238
/**
239
* Get the endpoint ID value
240
* @return the endpoint ID value
241
*/
242
public String toLowerCaseString() { /* ... */ }
243
244
/**
245
* Get the endpoint ID value
246
* @return the endpoint ID value
247
*/
248
@Override
249
public String toString() { /* ... */ }
250
}
251
252
/**
253
* Access control levels for endpoints
254
*/
255
public enum Access {
256
257
/**
258
* Access is unrestricted
259
*/
260
UNRESTRICTED,
261
262
/**
263
* Access is restricted
264
*/
265
RESTRICTED
266
}
267
```
268
269
### Security Context
270
271
Security integration for endpoint access control.
272
273
```java { .api }
274
/**
275
* Security context for endpoint operations
276
*/
277
public interface SecurityContext {
278
279
/**
280
* Return the principal
281
* @return the principal or null
282
*/
283
Principal getPrincipal();
284
285
/**
286
* Return true if the user is in the specified role
287
* @param role the role to check
288
* @return true if the user is in the role
289
*/
290
boolean isUserInRole(String role);
291
}
292
```
293
294
## Usage Examples
295
296
### Creating a Custom Endpoint
297
298
```java
299
@Endpoint(id = "custom", defaultAccess = Access.UNRESTRICTED)
300
@Component
301
public class CustomEndpoint {
302
303
private final CustomService customService;
304
305
public CustomEndpoint(CustomService customService) {
306
this.customService = customService;
307
}
308
309
@ReadOperation
310
public Map<String, Object> info() {
311
return Map.of(
312
"status", "operational",
313
"version", "1.0.0",
314
"uptime", System.currentTimeMillis()
315
);
316
}
317
318
@ReadOperation
319
public Map<String, Object> detailsForId(@Selector String id) {
320
return customService.getDetailsFor(id);
321
}
322
323
@WriteOperation
324
public Map<String, Object> updateConfig(@Nullable String key, @Nullable String value) {
325
if (key != null && value != null) {
326
customService.updateConfig(key, value);
327
return Map.of("status", "updated", "key", key);
328
}
329
return Map.of("status", "no-change");
330
}
331
332
@DeleteOperation
333
public Map<String, Object> clearCache() {
334
customService.clearCache();
335
return Map.of("status", "cache-cleared");
336
}
337
}
338
```
339
340
### Web-Specific Endpoint Extension
341
342
```java
343
@EndpointWebExtension(endpoint = CustomEndpoint.class)
344
@Component
345
public class CustomWebEndpointExtension {
346
347
private final CustomEndpoint delegate;
348
349
public CustomWebEndpointExtension(CustomEndpoint delegate) {
350
this.delegate = delegate;
351
}
352
353
@ReadOperation
354
public ResponseEntity<Map<String, Object>> infoWithHeaders() {
355
Map<String, Object> info = delegate.info();
356
357
HttpHeaders headers = new HttpHeaders();
358
headers.add("X-Custom-Header", "custom-value");
359
headers.add("Cache-Control", "no-cache");
360
361
return ResponseEntity.ok()
362
.headers(headers)
363
.body(info);
364
}
365
366
@WriteOperation
367
public ResponseEntity<Map<String, Object>> uploadFile(
368
@RequestParam("file") MultipartFile file) {
369
370
if (file.isEmpty()) {
371
return ResponseEntity.badRequest()
372
.body(Map.of("error", "File is required"));
373
}
374
375
// Process file upload
376
Map<String, Object> result = processFileUpload(file);
377
378
return ResponseEntity.ok(result);
379
}
380
}
381
```
382
383
### Conditional Endpoint
384
385
```java
386
@Endpoint(id = "debug", defaultAccess = Access.RESTRICTED)
387
@ConditionalOnProperty(name = "management.endpoint.debug.enabled", havingValue = "true")
388
@Component
389
public class DebugEndpoint {
390
391
private final ApplicationContext applicationContext;
392
393
public DebugEndpoint(ApplicationContext applicationContext) {
394
this.applicationContext = applicationContext;
395
}
396
397
@ReadOperation
398
public Map<String, Object> debugInfo() {
399
return Map.of(
400
"active-profiles", Arrays.asList(applicationContext.getEnvironment().getActiveProfiles()),
401
"bean-count", applicationContext.getBeanDefinitionCount(),
402
"startup-date", new Date(applicationContext.getStartupDate())
403
);
404
}
405
406
@ReadOperation
407
public Object beanInfo(@Selector String beanName) {
408
try {
409
Object bean = applicationContext.getBean(beanName);
410
return Map.of(
411
"class", bean.getClass().getName(),
412
"singleton", applicationContext.isSingleton(beanName),
413
"prototype", applicationContext.isPrototype(beanName)
414
);
415
} catch (NoSuchBeanDefinitionException e) {
416
return Map.of("error", "Bean not found: " + beanName);
417
}
418
}
419
}
420
```
421
422
### Security-Aware Endpoint
423
424
```java
425
@Endpoint(id = "secure", defaultAccess = Access.RESTRICTED)
426
@Component
427
public class SecureEndpoint {
428
429
@ReadOperation
430
public Map<String, Object> publicInfo() {
431
return Map.of("public", "information");
432
}
433
434
@ReadOperation
435
public Map<String, Object> sensitiveInfo(SecurityContext securityContext) {
436
if (securityContext.isUserInRole("ADMIN")) {
437
return Map.of(
438
"sensitive", "admin-only-data",
439
"principal", securityContext.getPrincipal().getName()
440
);
441
}
442
return Map.of("error", "Access denied");
443
}
444
}
445
```
446
447
### Endpoint Filter
448
449
```java
450
@Component
451
public class CustomEndpointFilter implements EndpointFilter<ExposableWebEndpoint> {
452
453
@Override
454
public boolean match(ExposableWebEndpoint endpoint) {
455
// Filter out debug endpoints in production
456
if (isProductionEnvironment() && "debug".equals(endpoint.getEndpointId().toString())) {
457
return false;
458
}
459
return true;
460
}
461
462
private boolean isProductionEnvironment() {
463
// Implementation to check environment
464
return "production".equals(System.getProperty("spring.profiles.active"));
465
}
466
}
467
```
468
469
## Built-in Operation Types
470
471
The framework supports several operation types:
472
473
```java { .api }
474
/**
475
* Types of endpoint operations
476
*/
477
public enum OperationType {
478
479
/**
480
* Read operation (HTTP GET)
481
*/
482
READ,
483
484
/**
485
* Write operation (HTTP POST)
486
*/
487
WRITE,
488
489
/**
490
* Delete operation (HTTP DELETE)
491
*/
492
DELETE
493
}
494
```
495
496
## Configuration
497
498
Endpoint framework behavior can be configured through application properties:
499
500
```properties
501
# Endpoint exposure
502
management.endpoints.web.exposure.include=health,info,custom
503
management.endpoints.web.exposure.exclude=
504
505
# Base path for web endpoints
506
management.endpoints.web.base-path=/actuator
507
508
# Path mapping for specific endpoints
509
management.endpoints.web.path-mapping.custom=my-custom-endpoint
510
511
# CORS configuration
512
management.endpoints.web.cors.allowed-origins=*
513
management.endpoints.web.cors.allowed-methods=GET,POST
514
515
# JMX exposure
516
management.endpoints.jmx.exposure.include=*
517
518
# Endpoint specific configuration
519
management.endpoint.custom.enabled=true
520
management.endpoint.custom.cache.time-to-live=10s
521
```