or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

events.mdindex.mdruntime.mdscheduling.mdscopes.mdserver.mdshutdown.md

events.mddocs/

0

# Event System

1

2

Reactive event publishing and listening system for decoupled communication between application components. Supports strongly-typed events, automatic event listener registration, and comprehensive application lifecycle events.

3

4

## Capabilities

5

6

### @EventListener Annotation

7

8

Declarative event listener registration for automatic event handling.

9

10

```java { .api }

11

/**

12

* Annotation for methods that should listen for application events

13

* Automatically registers the method as an ApplicationEventListener

14

*/

15

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})

16

@Retention(RetentionPolicy.RUNTIME)

17

@Adapter(ApplicationEventListener.class)

18

public @interface EventListener {

19

// Marker annotation - no attributes needed

20

// Event type is determined from method parameter type

21

}

22

```

23

24

**Usage Examples:**

25

26

```java

27

import io.micronaut.runtime.event.annotation.EventListener;

28

import io.micronaut.runtime.server.event.ServerStartupEvent;

29

import io.micronaut.runtime.server.event.ServerShutdownEvent;

30

import io.micronaut.context.event.StartupEvent;

31

import io.micronaut.context.event.ShutdownEvent;

32

import jakarta.inject.Singleton;

33

34

@Singleton

35

public class ApplicationEventListener {

36

37

@EventListener

38

public void onStartup(ServerStartupEvent event) {

39

EmbeddedServer server = event.getSource();

40

System.out.println("Server started on: " + server.getURL());

41

System.out.println("Application ready to handle requests");

42

}

43

44

@EventListener

45

public void onShutdown(ServerShutdownEvent event) {

46

System.out.println("Server shutting down");

47

// Cleanup resources, close connections, etc.

48

}

49

50

@EventListener

51

public void onApplicationStartup(StartupEvent event) {

52

ApplicationContext context = event.getSource();

53

System.out.println("Application context started");

54

}

55

56

@EventListener

57

public void onApplicationShutdown(ShutdownEvent event) {

58

System.out.println("Application context shutting down");

59

}

60

61

// Custom event listener

62

@EventListener

63

public void onCustomEvent(CustomBusinessEvent event) {

64

System.out.println("Business event: " + event.getData());

65

}

66

67

// Async event handling

68

@EventListener

69

@Async

70

public CompletableFuture<Void> onAsyncEvent(AsyncProcessingEvent event) {

71

return CompletableFuture.runAsync(() -> {

72

// Long-running event processing

73

processEventData(event.getData());

74

});

75

}

76

}

77

```

78

79

### Application Lifecycle Events

80

81

Built-in events for tracking application and server lifecycle.

82

83

```java { .api }

84

/**

85

* Base class for embedded application events

86

* Provides common functionality for application lifecycle events

87

*/

88

public abstract class AbstractEmbeddedApplicationEvent extends ApplicationEvent {

89

/**

90

* Create application event with embedded application source

91

* @param source The embedded application that generated the event

92

*/

93

public AbstractEmbeddedApplicationEvent(EmbeddedApplication<?> source);

94

95

/**

96

* Get the embedded application that generated this event

97

* @return EmbeddedApplication instance

98

*/

99

public EmbeddedApplication<?> getSource();

100

}

101

102

/**

103

* Event fired when EmbeddedApplication starts up

104

* Indicates the application context is ready and services are available

105

*/

106

public class ApplicationStartupEvent extends AbstractEmbeddedApplicationEvent {

107

/**

108

* Create startup event

109

* @param source The embedded application that started

110

*/

111

public ApplicationStartupEvent(EmbeddedApplication<?> source);

112

}

113

114

/**

115

* Event fired when EmbeddedApplication shuts down

116

* Last chance to perform cleanup before application termination

117

*/

118

public class ApplicationShutdownEvent extends AbstractEmbeddedApplicationEvent {

119

/**

120

* Create shutdown event

121

* @param source The embedded application that is shutting down

122

*/

123

public ApplicationShutdownEvent(EmbeddedApplication<?> source);

124

}

125

```

126

127

### Server Lifecycle Events

128

129

Events specific to embedded server lifecycle for web applications.

130

131

```java { .api }

132

/**

133

* Event fired when EmbeddedServer completes startup

134

* Server is ready to accept HTTP requests

135

*/

136

public class ServerStartupEvent extends ApplicationStartupEvent {

137

/**

138

* Create server startup event

139

* @param embeddedServer The server that started

140

*/

141

public ServerStartupEvent(EmbeddedServer embeddedServer);

142

143

/**

144

* Get the embedded server that started

145

* @return EmbeddedServer instance

146

*/

147

public EmbeddedServer getSource();

148

}

149

150

/**

151

* Event fired when EmbeddedServer shuts down

152

* Server will no longer accept new requests

153

*/

154

public class ServerShutdownEvent extends ApplicationEvent {

155

/**

156

* Create server shutdown event

157

* @param embeddedServer The server that is shutting down

158

*/

159

public ServerShutdownEvent(EmbeddedServer embeddedServer);

160

161

/**

162

* Get the embedded server that is shutting down

163

* @return EmbeddedServer instance

164

*/

165

public EmbeddedServer getSource();

166

}

167

```

168

169

**Usage Examples:**

170

171

```java

172

import io.micronaut.runtime.server.event.ServerStartupEvent;

173

import io.micronaut.runtime.server.event.ServerShutdownEvent;

174

import io.micronaut.runtime.event.annotation.EventListener;

175

176

@Singleton

177

public class ServerLifecycleListener {

178

179

@EventListener

180

public void onServerStartup(ServerStartupEvent event) {

181

EmbeddedServer server = event.getSource();

182

183

// Log server startup details

184

System.out.println("πŸš€ Server started successfully!");

185

System.out.println(" URL: " + server.getURL());

186

System.out.println(" Port: " + server.getPort());

187

System.out.println(" Host: " + server.getHost());

188

189

// Initialize external services

190

initializeExternalConnections();

191

192

// Register with service discovery

193

registerWithServiceRegistry(server);

194

}

195

196

@EventListener

197

public void onServerShutdown(ServerShutdownEvent event) {

198

System.out.println("πŸ›‘ Server shutting down...");

199

200

// Deregister from service discovery

201

deregisterFromServiceRegistry();

202

203

// Close external connections

204

closeExternalConnections();

205

206

System.out.println("βœ… Graceful shutdown completed");

207

}

208

}

209

```

210

211

### Event Publishing

212

213

Programmatic event publishing for custom business events.

214

215

```java { .api }

216

/**

217

* ApplicationEventPublisher interface for publishing events

218

* Automatically available as an injectable bean

219

*/

220

public interface ApplicationEventPublisher<T> {

221

/**

222

* Publish an event to all registered listeners

223

* Executes synchronously, blocking until all listeners complete

224

* @param event The event to publish

225

*/

226

void publishEvent(@NonNull T event);

227

228

/**

229

* Publish an event asynchronously

230

* @param event The event to publish

231

* @return Future representing the async operation

232

*/

233

@NonNull Future<Void> publishEventAsync(@NonNull T event);

234

235

/**

236

* Check whether this publisher is empty (has no listeners)

237

* @return true if there are no subscribers

238

*/

239

boolean isEmpty();

240

241

/**

242

* Returns a no-op instance of ApplicationEventPublisher

243

* @param <K> The event type

244

* @return no-op ApplicationEventPublisher instance

245

*/

246

static <K> ApplicationEventPublisher<K> noOp();

247

}

248

```

249

250

**Usage Examples:**

251

252

```java

253

import io.micronaut.context.event.ApplicationEventPublisher;

254

import jakarta.inject.Inject;

255

import jakarta.inject.Singleton;

256

257

// Custom business event

258

public class OrderProcessedEvent {

259

private final String orderId;

260

private final BigDecimal amount;

261

private final Instant processedAt;

262

263

public OrderProcessedEvent(String orderId, BigDecimal amount) {

264

this.orderId = orderId;

265

this.amount = amount;

266

this.processedAt = Instant.now();

267

}

268

269

// Getters...

270

public String getOrderId() { return orderId; }

271

public BigDecimal getAmount() { return amount; }

272

public Instant getProcessedAt() { return processedAt; }

273

}

274

275

@Singleton

276

public class OrderService {

277

278

@Inject

279

private ApplicationEventPublisher<OrderProcessedEvent> eventPublisher;

280

281

public void processOrder(Order order) {

282

// Process the order

283

doOrderProcessing(order);

284

285

// Publish event synchronously

286

OrderProcessedEvent event = new OrderProcessedEvent(

287

order.getId(),

288

order.getTotal()

289

);

290

eventPublisher.publishEvent(event);

291

}

292

293

public CompletableFuture<Void> processOrderAsync(Order order) {

294

return CompletableFuture.runAsync(() -> {

295

doOrderProcessing(order);

296

}).thenCompose(v -> {

297

// Publish event asynchronously

298

OrderProcessedEvent event = new OrderProcessedEvent(

299

order.getId(),

300

order.getTotal()

301

);

302

return eventPublisher.publishEventAsync(event);

303

});

304

}

305

}

306

307

// Event listeners for the custom event

308

@Singleton

309

public class OrderEventHandlers {

310

311

@EventListener

312

public void onOrderProcessed(OrderProcessedEvent event) {

313

System.out.println("Order processed: " + event.getOrderId());

314

315

// Send confirmation email

316

sendConfirmationEmail(event.getOrderId());

317

}

318

319

@EventListener

320

@Async

321

public CompletableFuture<Void> updateAnalytics(OrderProcessedEvent event) {

322

return CompletableFuture.runAsync(() -> {

323

// Update business analytics asynchronously

324

analyticsService.recordOrderProcessed(event);

325

});

326

}

327

328

@EventListener

329

public void auditOrderProcessing(OrderProcessedEvent event) {

330

auditService.log("ORDER_PROCESSED", event.getOrderId(), event.getAmount());

331

}

332

}

333

```

334

335

### Conditional Event Listeners

336

337

Event listeners with conditional execution based on application configuration.

338

339

```java { .api }

340

/**

341

* Conditional event listener execution

342

* Use @Requires annotation to control when listeners are active

343

*/

344

import io.micronaut.context.annotation.Requires;

345

346

@Singleton

347

@Requires(property = "app.monitoring.enabled", value = "true")

348

public class MonitoringEventListener {

349

350

@EventListener

351

public void onServerStartup(ServerStartupEvent event) {

352

// Only active when monitoring is enabled

353

startupMonitor.recordStartup(event);

354

}

355

}

356

357

@Singleton

358

@Requires(env = "production")

359

public class ProductionEventListener {

360

361

@EventListener

362

public void onApplicationStartup(ApplicationStartupEvent event) {

363

// Only active in production environment

364

productionMetrics.recordStartup();

365

}

366

}

367

```

368

369

### Error Handling in Event Listeners

370

371

Best practices for handling exceptions in event listeners.

372

373

```java { .api }

374

@Singleton

375

public class RobustEventListener {

376

377

private static final Logger logger = LoggerFactory.getLogger(RobustEventListener.class);

378

379

@EventListener

380

public void onServerStartup(ServerStartupEvent event) {

381

try {

382

// Event processing logic

383

performStartupOperations(event);

384

} catch (Exception e) {

385

// Log error but don't propagate to prevent disrupting other listeners

386

logger.error("Error processing server startup event", e);

387

388

// Optional: publish error event for monitoring

389

errorEventPublisher.publishEvent(new EventProcessingError(e));

390

}

391

}

392

393

@EventListener

394

@Retryable(attempts = "3", delay = "1s")

395

public void onRetryableEvent(CustomEvent event) {

396

// This listener will be retried up to 3 times with 1-second delay

397

riskyOperation(event);

398

}

399

}

400

```

401

402

## Custom Event Types

403

404

### Creating Custom Events

405

406

Guidelines for creating custom event types.

407

408

```java { .api }

409

/**

410

* Base pattern for custom business events

411

* Extend ApplicationEvent or create POJO with relevant data

412

*/

413

public class CustomBusinessEvent extends ApplicationEvent {

414

private final String businessData;

415

private final Instant timestamp;

416

417

public CustomBusinessEvent(Object source, String businessData) {

418

super(source);

419

this.businessData = businessData;

420

this.timestamp = Instant.now();

421

}

422

423

public String getBusinessData() { return businessData; }

424

public Instant getTimestamp() { return timestamp; }

425

}

426

427

// Alternative: Simple POJO event (recommended for most cases)

428

public class UserRegisteredEvent {

429

private final String userId;

430

private final String email;

431

private final Instant registeredAt;

432

433

public UserRegisteredEvent(String userId, String email) {

434

this.userId = userId;

435

this.email = email;

436

this.registeredAt = Instant.now();

437

}

438

439

// Getters...

440

}

441

```

442

443

**Complete Custom Event Example:**

444

445

```java

446

// Event definition

447

public class PaymentProcessedEvent {

448

private final String paymentId;

449

private final String customerId;

450

private final BigDecimal amount;

451

private final String currency;

452

private final PaymentStatus status;

453

private final Instant processedAt;

454

455

// Constructor and getters...

456

}

457

458

// Event publisher service

459

@Singleton

460

public class PaymentService {

461

462

@Inject

463

private ApplicationEventPublisher<PaymentProcessedEvent> eventPublisher;

464

465

public void processPayment(PaymentRequest request) {

466

// Process payment logic

467

PaymentResult result = processPaymentInternal(request);

468

469

// Publish event

470

PaymentProcessedEvent event = new PaymentProcessedEvent(

471

result.getPaymentId(),

472

request.getCustomerId(),

473

request.getAmount(),

474

request.getCurrency(),

475

result.getStatus()

476

);

477

478

eventPublisher.publishEvent(event);

479

}

480

}

481

482

// Multiple event listeners

483

@Singleton

484

public class PaymentEventHandlers {

485

486

@EventListener

487

public void onPaymentProcessed(PaymentProcessedEvent event) {

488

if (event.getStatus() == PaymentStatus.SUCCESS) {

489

// Send success notification

490

notificationService.sendPaymentConfirmation(event);

491

} else {

492

// Handle payment failure

493

alertService.notifyPaymentFailure(event);

494

}

495

}

496

497

@EventListener

498

@Async

499

public CompletableFuture<Void> updateCustomerBalance(PaymentProcessedEvent event) {

500

return CompletableFuture.runAsync(() -> {

501

customerService.updateBalance(event.getCustomerId(), event.getAmount());

502

});

503

}

504

505

@EventListener

506

public void auditPayment(PaymentProcessedEvent event) {

507

auditService.recordPayment(event);

508

}

509

}

510

```