0
# Endpoint Framework
1
2
The Spring Boot Actuator endpoint framework provides a consistent way to create custom monitoring and management endpoints that can be exposed via HTTP and JMX.
3
4
## Capabilities
5
6
### Core Endpoint Creation
7
8
Define custom endpoints using the `@Endpoint` annotation with operations for read, write, and delete actions.
9
10
```java { .api }
11
/**
12
* Marks a class as an actuator endpoint
13
*/
14
@Target(ElementType.TYPE)
15
@Retention(RetentionPolicy.RUNTIME)
16
@Documented
17
public @interface Endpoint {
18
/**
19
* The unique identifier for this endpoint (must follow EndpointId rules)
20
*/
21
String id() default "";
22
23
/**
24
* Whether this endpoint is enabled by default
25
* @deprecated since 3.4.0 for removal in 4.0.0 in favor of defaultAccess()
26
*/
27
@Deprecated(since = "3.4.0", forRemoval = true)
28
boolean enableByDefault() default true;
29
30
/**
31
* Level of access to the endpoint that is permitted by default
32
* @since 3.4.0
33
*/
34
Access defaultAccess() default Access.UNRESTRICTED;
35
}
36
37
/**
38
* Marks a method as a read operation (GET/query)
39
*/
40
@Target(ElementType.METHOD)
41
@Retention(RetentionPolicy.RUNTIME)
42
@Documented
43
public @interface ReadOperation {
44
String[] produces() default {};
45
Class<? extends Producible> producesFrom() default Producible.class;
46
}
47
48
/**
49
* Marks a method as a write operation (POST/update)
50
*/
51
@Target(ElementType.METHOD)
52
@Retention(RetentionPolicy.RUNTIME)
53
@Documented
54
public @interface WriteOperation {
55
String[] produces() default {};
56
Class<? extends Producible> producesFrom() default Producible.class;
57
}
58
59
/**
60
* Marks a method as a delete operation (DELETE)
61
*/
62
@Target(ElementType.METHOD)
63
@Retention(RetentionPolicy.RUNTIME)
64
@Documented
65
public @interface DeleteOperation {
66
String[] produces() default {};
67
Class<? extends Producible> producesFrom() default Producible.class;
68
}
69
```
70
71
**Usage Example:**
72
73
```java
74
@Endpoint(id = "system-status")
75
@Component
76
public class SystemStatusEndpoint {
77
78
@ReadOperation
79
public Map<String, Object> getSystemStatus() {
80
return Map.of(
81
"cpu", getCpuUsage(),
82
"memory", getMemoryInfo(),
83
"disk", getDiskInfo()
84
);
85
}
86
87
@ReadOperation
88
public Map<String, Object> getSpecificMetric(@Selector String metric) {
89
return Map.of("metric", metric, "value", getMetricValue(metric));
90
}
91
92
@WriteOperation
93
public void updateConfiguration(@Selector String key, String value) {
94
updateSystemConfig(key, value);
95
}
96
97
@DeleteOperation
98
public void clearCache(@Selector String cacheName) {
99
clearSpecificCache(cacheName);
100
}
101
}
102
```
103
104
### Web-Specific Endpoints
105
106
Create endpoints that are specifically designed for HTTP access with enhanced web features.
107
108
```java { .api }
109
/**
110
* Marks a class as a web-specific actuator endpoint
111
*/
112
@Target(ElementType.TYPE)
113
@Retention(RetentionPolicy.RUNTIME)
114
@Documented
115
public @interface WebEndpoint {
116
String id();
117
boolean enableByDefault() default true;
118
}
119
120
/**
121
* HTTP response wrapper for web endpoints
122
*/
123
public final class WebEndpointResponse<T> {
124
public WebEndpointResponse(T body, int status);
125
public WebEndpointResponse(T body, int status, Map<String, String> headers);
126
127
public T getBody();
128
public int getStatus();
129
public Map<String, String> getHeaders();
130
}
131
132
/**
133
* Represents a web operation with HTTP-specific details
134
*/
135
public interface WebOperation extends Operation {
136
String getRequestPredicate();
137
String getId();
138
boolean isBlocking();
139
}
140
```
141
142
**Usage Example:**
143
144
```java
145
@WebEndpoint(id = "api-status")
146
@Component
147
public class ApiStatusEndpoint {
148
149
@ReadOperation
150
public WebEndpointResponse<Map<String, Object>> getApiStatus() {
151
Map<String, Object> status = getApiHealthStatus();
152
int httpStatus = (boolean) status.get("healthy") ? 200 : 503;
153
154
return new WebEndpointResponse<>(status, httpStatus);
155
}
156
157
@ReadOperation
158
public WebEndpointResponse<String> downloadReport() {
159
String report = generateStatusReport();
160
Map<String, String> headers = Map.of(
161
"Content-Type", "text/plain",
162
"Content-Disposition", "attachment; filename=status-report.txt"
163
);
164
165
return new WebEndpointResponse<>(report, 200, headers);
166
}
167
}
168
```
169
170
### JMX-Specific Endpoints
171
172
Create endpoints specifically for JMX (Java Management Extensions) access.
173
174
```java { .api }
175
/**
176
* Marks a class as a JMX-specific actuator endpoint
177
*/
178
@Target(ElementType.TYPE)
179
@Retention(RetentionPolicy.RUNTIME)
180
@Documented
181
public @interface JmxEndpoint {
182
String id();
183
boolean enableByDefault() default true;
184
}
185
186
/**
187
* Represents a JMX operation
188
*/
189
public interface JmxOperation extends Operation {
190
String getName();
191
String getDescription();
192
String[] getParameterNames();
193
Class<?>[] getParameterTypes();
194
Class<?> getReturnType();
195
}
196
```
197
198
### Operation Parameters and Selectors
199
200
Handle parameters and path variables in endpoint operations.
201
202
```java { .api }
203
/**
204
* Marks a parameter as a path selector (path variable)
205
*/
206
@Target(ElementType.PARAMETER)
207
@Retention(RetentionPolicy.RUNTIME)
208
@Documented
209
public @interface Selector { }
210
211
/**
212
* Marks a parameter as nullable
213
*/
214
@Target(ElementType.PARAMETER)
215
@Retention(RetentionPolicy.RUNTIME)
216
@Documented
217
public @interface Nullable { }
218
```
219
220
**Usage Example:**
221
222
```java
223
@Endpoint(id = "cache-management")
224
@Component
225
public class CacheManagementEndpoint {
226
227
@ReadOperation
228
public Map<String, Object> getAllCaches() {
229
return cacheManager.getCacheNames().stream()
230
.collect(Collectors.toMap(
231
name -> name,
232
name -> getCacheStats(name)
233
));
234
}
235
236
@ReadOperation
237
public Map<String, Object> getCache(@Selector String cacheName) {
238
return getCacheStats(cacheName);
239
}
240
241
@WriteOperation
242
public void evictCache(@Selector String cacheName, @Nullable String key) {
243
if (key != null) {
244
cacheManager.getCache(cacheName).evict(key);
245
} else {
246
cacheManager.getCache(cacheName).clear();
247
}
248
}
249
250
@DeleteOperation
251
public void deleteCache(@Selector String cacheName) {
252
// Remove cache entirely
253
cacheManager.destroyCache(cacheName);
254
}
255
}
256
```
257
258
### Security Context
259
260
Access security information within endpoint operations.
261
262
```java { .api }
263
/**
264
* Security context providing access to authentication details
265
*/
266
public final class SecurityContext {
267
public static SecurityContext of(Principal principal, String... roles);
268
public static SecurityContext of(Map<String, Object> details);
269
270
public Principal getPrincipal();
271
public boolean isUserInRole(String role);
272
public boolean hasRole(String role);
273
public Map<String, Object> getDetails();
274
}
275
```
276
277
**Usage Example:**
278
279
```java
280
@Endpoint(id = "secure-admin")
281
@Component
282
public class SecureAdminEndpoint {
283
284
@ReadOperation
285
public Map<String, Object> getAdminInfo(SecurityContext securityContext) {
286
if (!securityContext.isUserInRole("ADMIN")) {
287
throw new IllegalAccessException("Admin role required");
288
}
289
290
return Map.of(
291
"user", securityContext.getPrincipal().getName(),
292
"adminData", getAdminSpecificData()
293
);
294
}
295
296
@WriteOperation
297
public void performAdminAction(@Selector String action,
298
String parameter,
299
SecurityContext securityContext) {
300
if (!securityContext.hasRole("ADMIN")) {
301
throw new IllegalAccessException("Admin role required");
302
}
303
304
executeAdminAction(action, parameter);
305
}
306
}
307
```
308
309
### Endpoint Identifier and Mapping
310
311
Handle endpoint identification and URL mapping.
312
313
```java { .api }
314
/**
315
* Represents an endpoint identifier
316
*/
317
public final class EndpointId {
318
public static EndpointId of(String value);
319
public static EndpointId fromPropertyValue(String value);
320
321
public String getValue();
322
public String toLowercaseString();
323
324
@Override
325
public boolean equals(Object obj);
326
327
@Override
328
public int hashCode();
329
330
@Override
331
public String toString();
332
}
333
334
/**
335
* Maps endpoint paths for web access
336
*/
337
public interface PathMapper {
338
String getRootPath(EndpointId endpointId);
339
String getPath(EndpointId endpointId, String operationId);
340
}
341
342
/**
343
* Endpoint mapping configuration
344
*/
345
public final class EndpointMapping {
346
public EndpointMapping(String path);
347
public String getPath();
348
public boolean matches(String path);
349
}
350
```
351
352
### Operation Invoker
353
354
Interface for invoking endpoint operations programmatically.
355
356
```java { .api }
357
/**
358
* Interface for invoking endpoint operations
359
*/
360
public interface OperationInvoker {
361
Object invoke(InvocationContext context);
362
}
363
364
/**
365
* Context for operation invocation
366
*/
367
public interface InvocationContext {
368
Map<String, Object> getArguments();
369
SecurityContext getSecurityContext();
370
Object getArgument(String name);
371
boolean canAccess(Object target);
372
}
373
374
/**
375
* Represents an endpoint operation
376
*/
377
public interface Operation {
378
String getId();
379
String getType();
380
boolean isBlocking();
381
OperationInvoker getInvoker();
382
}
383
```
384
385
**Usage Example:**
386
387
```java
388
@Component
389
public class CustomOperationInvoker implements OperationInvoker {
390
391
@Override
392
public Object invoke(InvocationContext context) {
393
// Custom invocation logic with logging, validation, etc.
394
logInvocation(context);
395
validateArguments(context.getArguments());
396
397
try {
398
return invokeActualOperation(context);
399
} catch (Exception e) {
400
logError(context, e);
401
throw e;
402
}
403
}
404
405
private Object invokeActualOperation(InvocationContext context) {
406
// Actual operation logic
407
return null;
408
}
409
}
410
```