or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotations.mdapplication-context.mdbean-definition.mdbean-factory.mdbean-processing.mdbean-providers.mdenvironment-config.mdevents.mdexceptions.mdindex.mdscoping.md

events.mddocs/

0

# Event System

1

2

Micronaut's event system provides a powerful mechanism for decoupled communication between components through application lifecycle events and custom business events. It supports both synchronous and asynchronous event processing.

3

4

## Core Interfaces

5

6

### ApplicationEventPublisher

7

8

Interface for publishing application events to registered listeners.

9

10

```java { .api }

11

public interface ApplicationEventPublisher<T> {

12

void publishEvent(T event);

13

Future<Void> publishEventAsync(T event);

14

}

15

```

16

17

### ApplicationEventListener

18

19

Interface for listening to application events.

20

21

```java { .api }

22

public interface ApplicationEventListener<E> {

23

void onApplicationEvent(E event);

24

default boolean supports(E event) { return true; }

25

}

26

```

27

28

### EventListener

29

30

Generic event listener interface for method-level event handling.

31

32

```java { .api }

33

@Target({METHOD})

34

@Retention(RUNTIME)

35

public @interface EventListener {

36

boolean async() default false;

37

}

38

```

39

40

## Built-in Application Events

41

42

### Startup Events

43

44

#### StartupEvent

45

46

Fired when the application context starts up.

47

48

```java { .api }

49

public class StartupEvent extends ApplicationEvent {

50

public StartupEvent(ApplicationContext source);

51

public ApplicationContext getSource();

52

}

53

```

54

55

#### ApplicationStartupEvent

56

57

More specific startup event with additional context.

58

59

```java { .api }

60

public class ApplicationStartupEvent extends ApplicationEvent {

61

public ApplicationStartupEvent(Application source);

62

public Application getSource();

63

}

64

```

65

66

### Shutdown Events

67

68

#### ShutdownEvent

69

70

Fired when the application context shuts down.

71

72

```java { .api }

73

public class ShutdownEvent extends ApplicationEvent {

74

public ShutdownEvent(ApplicationContext source);

75

public ApplicationContext getSource();

76

}

77

```

78

79

### Bean Lifecycle Events

80

81

#### BeanCreatedEvent

82

83

Fired when a bean is created.

84

85

```java { .api }

86

public class BeanCreatedEvent<T> extends ApplicationEvent {

87

public BeanCreatedEvent(BeanContext beanContext, BeanDefinition<T> beanDefinition, T bean);

88

public BeanDefinition<T> getBeanDefinition();

89

public T getBean();

90

}

91

```

92

93

#### BeanInitializedEvent

94

95

Fired when a bean is fully initialized.

96

97

```java { .api }

98

public class BeanInitializedEvent<T> extends ApplicationEvent {

99

public BeanInitializedEvent(BeanContext beanContext, BeanDefinition<T> beanDefinition, T bean);

100

public BeanDefinition<T> getBeanDefinition();

101

public T getBean();

102

}

103

```

104

105

#### BeanDestroyedEvent

106

107

Fired when a bean is destroyed.

108

109

```java { .api }

110

public class BeanDestroyedEvent<T> extends ApplicationEvent {

111

public BeanDestroyedEvent(BeanContext beanContext, BeanDefinition<T> beanDefinition, T bean);

112

public BeanDefinition<T> getBeanDefinition();

113

public T getBean();

114

}

115

```

116

117

## Event Publishing

118

119

### Publishing Events

120

121

```java

122

import io.micronaut.context.event.ApplicationEventPublisher;

123

import jakarta.inject.Singleton;

124

import jakarta.inject.Inject;

125

126

@Singleton

127

public class OrderService {

128

129

private final ApplicationEventPublisher<OrderEvent> eventPublisher;

130

131

@Inject

132

public OrderService(ApplicationEventPublisher<OrderEvent> eventPublisher) {

133

this.eventPublisher = eventPublisher;

134

}

135

136

public void createOrder(Order order) {

137

// Process order

138

order.setStatus(OrderStatus.CREATED);

139

140

// Publish event

141

OrderCreatedEvent event = new OrderCreatedEvent(order);

142

eventPublisher.publishEvent(event);

143

}

144

145

public void cancelOrder(String orderId) {

146

// Cancel order logic

147

Order order = findOrder(orderId);

148

order.setStatus(OrderStatus.CANCELLED);

149

150

// Publish cancellation event

151

OrderCancelledEvent event = new OrderCancelledEvent(order);

152

eventPublisher.publishEvent(event);

153

}

154

}

155

```

156

157

### Asynchronous Event Publishing

158

159

```java

160

import io.micronaut.context.event.ApplicationEventPublisher;

161

import jakarta.inject.Singleton;

162

import java.util.concurrent.Future;

163

164

@Singleton

165

public class NotificationService {

166

167

private final ApplicationEventPublisher<NotificationEvent> eventPublisher;

168

169

@Inject

170

public NotificationService(ApplicationEventPublisher<NotificationEvent> eventPublisher) {

171

this.eventPublisher = eventPublisher;

172

}

173

174

public void sendNotification(String message, String recipient) {

175

NotificationEvent event = new NotificationEvent(message, recipient);

176

177

// Publish asynchronously - doesn't block

178

Future<Void> future = eventPublisher.publishEventAsync(event);

179

180

// Optionally handle completion

181

future.thenRun(() -> {

182

System.out.println("Notification event published successfully");

183

}).exceptionally(throwable -> {

184

System.err.println("Failed to publish notification event: " + throwable.getMessage());

185

return null;

186

});

187

}

188

}

189

```

190

191

## Event Listening

192

193

### Interface-based Listeners

194

195

```java

196

import io.micronaut.context.event.ApplicationEventListener;

197

import jakarta.inject.Singleton;

198

199

@Singleton

200

public class OrderEventListener implements ApplicationEventListener<OrderCreatedEvent> {

201

202

@Override

203

public void onApplicationEvent(OrderCreatedEvent event) {

204

Order order = event.getOrder();

205

System.out.println("Order created: " + order.getId());

206

207

// Send confirmation email

208

sendConfirmationEmail(order);

209

210

// Update inventory

211

updateInventory(order);

212

}

213

214

@Override

215

public boolean supports(OrderCreatedEvent event) {

216

// Only handle events for orders over $100

217

return event.getOrder().getTotal().compareTo(new BigDecimal("100")) > 0;

218

}

219

220

private void sendConfirmationEmail(Order order) {

221

// Email sending logic

222

}

223

224

private void updateInventory(Order order) {

225

// Inventory update logic

226

}

227

}

228

```

229

230

### Method-based Listeners

231

232

```java

233

import io.micronaut.context.event.EventListener;

234

import jakarta.inject.Singleton;

235

236

@Singleton

237

public class ApplicationEventHandler {

238

239

@EventListener

240

public void onStartup(StartupEvent event) {

241

System.out.println("Application started: " + event.getSource());

242

// Initialize caches, warm up connections, etc.

243

}

244

245

@EventListener

246

public void onShutdown(ShutdownEvent event) {

247

System.out.println("Application shutting down: " + event.getSource());

248

// Cleanup resources, save state, etc.

249

}

250

251

@EventListener(async = true) // Asynchronous processing

252

public void onOrderCreated(OrderCreatedEvent event) {

253

// This runs in a separate thread

254

generateOrderReport(event.getOrder());

255

}

256

257

@EventListener

258

public void onBeanCreated(BeanCreatedEvent<?> event) {

259

if (event.getBean() instanceof DatabaseService) {

260

System.out.println("Database service bean created: " + event.getBeanDefinition().getBeanType());

261

}

262

}

263

}

264

```

265

266

### Generic Event Listeners

267

268

```java

269

import io.micronaut.context.event.ApplicationEventListener;

270

import jakarta.inject.Singleton;

271

272

@Singleton

273

public class GenericEventLogger implements ApplicationEventListener<ApplicationEvent> {

274

275

@Override

276

public void onApplicationEvent(ApplicationEvent event) {

277

System.out.println("Event received: " + event.getClass().getSimpleName() +

278

" at " + Instant.now());

279

}

280

281

@Override

282

public boolean supports(ApplicationEvent event) {

283

// Log all events except bean lifecycle events (too noisy)

284

return !(event instanceof BeanCreatedEvent ||

285

event instanceof BeanInitializedEvent ||

286

event instanceof BeanDestroyedEvent);

287

}

288

}

289

```

290

291

## Custom Events

292

293

### Creating Custom Events

294

295

```java

296

import io.micronaut.context.ApplicationEvent;

297

298

// Base order event

299

public abstract class OrderEvent extends ApplicationEvent {

300

private final Order order;

301

302

public OrderEvent(Order order) {

303

super(order);

304

this.order = order;

305

}

306

307

public Order getOrder() {

308

return order;

309

}

310

}

311

312

// Specific order events

313

public class OrderCreatedEvent extends OrderEvent {

314

public OrderCreatedEvent(Order order) {

315

super(order);

316

}

317

}

318

319

public class OrderCancelledEvent extends OrderEvent {

320

private final String reason;

321

322

public OrderCancelledEvent(Order order, String reason) {

323

super(order);

324

this.reason = reason;

325

}

326

327

public String getReason() {

328

return reason;

329

}

330

}

331

332

public class OrderShippedEvent extends OrderEvent {

333

private final String trackingNumber;

334

private final String carrier;

335

336

public OrderShippedEvent(Order order, String trackingNumber, String carrier) {

337

super(order);

338

this.trackingNumber = trackingNumber;

339

this.carrier = carrier;

340

}

341

342

public String getTrackingNumber() {

343

return trackingNumber;

344

}

345

346

public String getCarrier() {

347

return carrier;

348

}

349

}

350

```

351

352

### Business Event Examples

353

354

```java

355

// User events

356

public class UserRegisteredEvent extends ApplicationEvent {

357

private final User user;

358

359

public UserRegisteredEvent(User user) {

360

super(user);

361

this.user = user;

362

}

363

364

public User getUser() {

365

return user;

366

}

367

}

368

369

public class UserLoginEvent extends ApplicationEvent {

370

private final String username;

371

private final String ipAddress;

372

private final Instant loginTime;

373

374

public UserLoginEvent(String username, String ipAddress) {

375

super(username);

376

this.username = username;

377

this.ipAddress = ipAddress;

378

this.loginTime = Instant.now();

379

}

380

381

// Getters...

382

}

383

384

// Payment events

385

public class PaymentProcessedEvent extends ApplicationEvent {

386

private final Payment payment;

387

private final PaymentResult result;

388

389

public PaymentProcessedEvent(Payment payment, PaymentResult result) {

390

super(payment);

391

this.payment = payment;

392

this.result = result;

393

}

394

395

// Getters...

396

}

397

```

398

399

## Event Processing Patterns

400

401

### Event Aggregation

402

403

```java

404

import io.micronaut.context.event.EventListener;

405

import jakarta.inject.Singleton;

406

import java.util.concurrent.ConcurrentHashMap;

407

import java.util.concurrent.atomic.AtomicInteger;

408

409

@Singleton

410

public class EventAggregator {

411

412

private final Map<String, AtomicInteger> eventCounts = new ConcurrentHashMap<>();

413

414

@EventListener

415

public void onOrderEvent(OrderEvent event) {

416

String eventType = event.getClass().getSimpleName();

417

eventCounts.computeIfAbsent(eventType, k -> new AtomicInteger(0)).incrementAndGet();

418

}

419

420

@EventListener

421

public void onUserEvent(UserEvent event) {

422

String eventType = event.getClass().getSimpleName();

423

eventCounts.computeIfAbsent(eventType, k -> new AtomicInteger(0)).incrementAndGet();

424

}

425

426

public Map<String, Integer> getEventStats() {

427

return eventCounts.entrySet().stream()

428

.collect(Collectors.toMap(

429

Map.Entry::getKey,

430

e -> e.getValue().get()

431

));

432

}

433

}

434

```

435

436

### Event Chain Processing

437

438

```java

439

import io.micronaut.context.event.EventListener;

440

import io.micronaut.context.event.ApplicationEventPublisher;

441

import jakarta.inject.Singleton;

442

443

@Singleton

444

public class OrderProcessingChain {

445

446

private final ApplicationEventPublisher<OrderEvent> eventPublisher;

447

448

@Inject

449

public OrderProcessingChain(ApplicationEventPublisher<OrderEvent> eventPublisher) {

450

this.eventPublisher = eventPublisher;

451

}

452

453

@EventListener

454

public void onOrderCreated(OrderCreatedEvent event) {

455

Order order = event.getOrder();

456

457

// Validate order

458

if (validateOrder(order)) {

459

eventPublisher.publishEvent(new OrderValidatedEvent(order));

460

} else {

461

eventPublisher.publishEvent(new OrderRejectedEvent(order, "Validation failed"));

462

}

463

}

464

465

@EventListener

466

public void onOrderValidated(OrderValidatedEvent event) {

467

Order order = event.getOrder();

468

469

// Process payment

470

PaymentResult result = processPayment(order);

471

if (result.isSuccessful()) {

472

eventPublisher.publishEvent(new OrderPaymentCompletedEvent(order));

473

} else {

474

eventPublisher.publishEvent(new OrderPaymentFailedEvent(order, result.getError()));

475

}

476

}

477

478

@EventListener

479

public void onPaymentCompleted(OrderPaymentCompletedEvent event) {

480

Order order = event.getOrder();

481

482

// Ship order

483

String trackingNumber = shipOrder(order);

484

eventPublisher.publishEvent(new OrderShippedEvent(order, trackingNumber, "UPS"));

485

}

486

}

487

```

488

489

### Conditional Event Processing

490

491

```java

492

import io.micronaut.context.event.EventListener;

493

import io.micronaut.context.annotation.Requires;

494

import jakarta.inject.Singleton;

495

496

@Singleton

497

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

498

public class AnalyticsEventProcessor {

499

500

@EventListener

501

public void onUserAction(UserActionEvent event) {

502

// Only process if analytics is enabled

503

recordUserAction(event);

504

}

505

506

@EventListener

507

public void onOrderCompleted(OrderCompletedEvent event) {

508

recordSale(event.getOrder());

509

updateRevenueMetrics(event.getOrder());

510

}

511

}

512

513

@Singleton

514

@Requires(env = "prod")

515

public class ProductionEventMonitor {

516

517

@EventListener

518

public void onError(ErrorEvent event) {

519

// Only monitor errors in production

520

alertOpsTeam(event);

521

}

522

}

523

```

524

525

## Error Handling

526

527

### Event Processing Errors

528

529

```java

530

import io.micronaut.context.event.EventListener;

531

import jakarta.inject.Singleton;

532

533

@Singleton

534

public class RobustEventHandler {

535

536

@EventListener

537

public void onOrderEvent(OrderEvent event) {

538

try {

539

processOrder(event.getOrder());

540

} catch (PaymentException e) {

541

System.err.println("Payment processing failed for order: " + event.getOrder().getId());

542

handlePaymentFailure(event.getOrder(), e);

543

} catch (InventoryException e) {

544

System.err.println("Inventory update failed for order: " + event.getOrder().getId());

545

handleInventoryFailure(event.getOrder(), e);

546

} catch (Exception e) {

547

System.err.println("Unexpected error processing order event: " + e.getMessage());

548

handleGenericFailure(event.getOrder(), e);

549

}

550

}

551

552

private void handlePaymentFailure(Order order, PaymentException e) {

553

// Specific payment failure handling

554

}

555

556

private void handleInventoryFailure(Order order, InventoryException e) {

557

// Specific inventory failure handling

558

}

559

560

private void handleGenericFailure(Order order, Exception e) {

561

// Generic error handling

562

}

563

}

564

```

565

566

## Implementation Classes

567

568

### DefaultApplicationEventPublisher

569

570

Default implementation of ApplicationEventPublisher.

571

572

```java { .api }

573

public class DefaultApplicationEventPublisher<T> implements ApplicationEventPublisher<T> {

574

public DefaultApplicationEventPublisher(BeanContext beanContext);

575

576

@Override

577

public void publishEvent(T event);

578

579

@Override

580

public Future<Void> publishEventAsync(T event);

581

}

582

```

583

584

### ApplicationEvent

585

586

Base class for all application events.

587

588

```java { .api }

589

public abstract class ApplicationEvent extends EventObject {

590

private final long timestamp;

591

592

public ApplicationEvent(Object source);

593

public final long getTimestamp();

594

}

595

```