or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

builtin-endpoints.mdconfiguration-properties.mdendpoint-framework.mdhealth-system.mdindex.mdmetrics-system.md

endpoint-framework.mddocs/

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

```