or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application.mdconfiguration.mdcontext.mdconversion.mdindex.mdjson.mdlogging.mdweb.md

context.mddocs/

0

# Context Lifecycle

1

2

Spring Boot provides a comprehensive application context lifecycle with events for monitoring startup, shutdown, and availability states. This includes application lifecycle events, availability probes, and failure analysis.

3

4

## Capabilities

5

6

### Application Lifecycle Events

7

8

Events published during different phases of the Spring Boot application lifecycle.

9

10

```java { .api }

11

/**

12

* Event published as early as conceivably possible as soon as a SpringApplication

13

* has been started - before the Environment or ApplicationContext is available

14

*/

15

public class ApplicationStartingEvent extends SpringApplicationEvent {

16

17

/**

18

* Create a new ApplicationStartingEvent instance

19

* @param application the current application

20

* @param args the arguments the application is running with

21

*/

22

public ApplicationStartingEvent(SpringApplication application, String[] args);

23

24

/**

25

* Return the SpringApplication

26

* @return the application

27

*/

28

public SpringApplication getSpringApplication();

29

30

/**

31

* Return the application arguments

32

* @return the arguments

33

*/

34

public String[] getArgs();

35

}

36

37

/**

38

* Event published when a SpringApplication is starting up and the Environment is

39

* first available for inspection and modification

40

*/

41

public class ApplicationEnvironmentPreparedEvent extends SpringApplicationEvent {

42

43

/**

44

* Create a new ApplicationEnvironmentPreparedEvent instance

45

* @param application the current application

46

* @param args the arguments the application is running with

47

* @param environment the environment that was just prepared

48

*/

49

public ApplicationEnvironmentPreparedEvent(SpringApplication application, String[] args,

50

ConfigurableEnvironment environment);

51

52

/**

53

* Return the environment

54

* @return the environment

55

*/

56

public ConfigurableEnvironment getEnvironment();

57

}

58

59

/**

60

* Event published once the ApplicationContext has been created and prepared, but

61

* before sources have been loaded

62

*/

63

public class ApplicationContextInitializedEvent extends SpringApplicationEvent {

64

65

/**

66

* Create a new ApplicationContextInitializedEvent instance

67

* @param application the current application

68

* @param args the arguments the application is running with

69

* @param context the context that has been initialized

70

*/

71

public ApplicationContextInitializedEvent(SpringApplication application, String[] args,

72

ConfigurableApplicationContext context);

73

74

/**

75

* Return the application context

76

* @return the application context

77

*/

78

public ConfigurableApplicationContext getApplicationContext();

79

}

80

81

/**

82

* Event published as late as conceivably possible to indicate that the application

83

* is ready to service requests. The source of the event is the SpringApplication itself

84

*/

85

public class ApplicationPreparedEvent extends SpringApplicationEvent {

86

87

/**

88

* Create a new ApplicationPreparedEvent instance

89

* @param application the current application

90

* @param args the arguments the application is running with

91

* @param context the ApplicationContext about to be refreshed

92

*/

93

public ApplicationPreparedEvent(SpringApplication application, String[] args,

94

ConfigurableApplicationContext context);

95

96

/**

97

* Return the application context

98

* @return the application context

99

*/

100

public ConfigurableApplicationContext getApplicationContext();

101

}

102

103

/**

104

* Event published once the application context has been refreshed but before any

105

* application and command line runners have been called

106

*/

107

public class ApplicationStartedEvent extends SpringApplicationEvent {

108

109

/**

110

* Create a new ApplicationStartedEvent instance

111

* @param application the current application

112

* @param args the arguments the application is running with

113

* @param context the ApplicationContext that was started

114

* @param timeTaken the time taken to start the application or null if unknown

115

*/

116

public ApplicationStartedEvent(SpringApplication application, String[] args,

117

ConfigurableApplicationContext context, Duration timeTaken);

118

119

/**

120

* Return the application context

121

* @return the application context

122

*/

123

public ConfigurableApplicationContext getApplicationContext();

124

125

/**

126

* Return the time taken for the application to be ready or null if unknown

127

* @return the startup time

128

*/

129

public Duration getTimeTaken();

130

}

131

132

/**

133

* Event published as late as conceivably possible to indicate that the application

134

* is ready to service requests. The source of the event is the SpringApplication itself

135

*/

136

public class ApplicationReadyEvent extends SpringApplicationEvent {

137

138

/**

139

* Create a new ApplicationReadyEvent instance

140

* @param application the current application

141

* @param args the arguments the application is running with

142

* @param context the ApplicationContext that is ready

143

* @param timeTaken the time taken for the application to be ready or null if unknown

144

*/

145

public ApplicationReadyEvent(SpringApplication application, String[] args,

146

ConfigurableApplicationContext context, Duration timeTaken);

147

148

/**

149

* Return the application context

150

* @return the application context

151

*/

152

public ConfigurableApplicationContext getApplicationContext();

153

154

/**

155

* Return the time taken for the application to be ready or null if unknown

156

* @return the startup time

157

*/

158

public Duration getTimeTaken();

159

}

160

161

/**

162

* Event published when a SpringApplication fails to start

163

*/

164

public class ApplicationFailedEvent extends SpringApplicationEvent {

165

166

/**

167

* Create a new ApplicationFailedEvent instance

168

* @param application the current application

169

* @param args the arguments the application was running with

170

* @param context the context that was being created (may be null)

171

* @param exception the exception that caused the failure

172

*/

173

public ApplicationFailedEvent(SpringApplication application, String[] args,

174

ConfigurableApplicationContext context, Throwable exception);

175

176

/**

177

* Return the application context

178

* @return the application context

179

*/

180

public ConfigurableApplicationContext getApplicationContext();

181

182

/**

183

* Return the exception that caused the failure

184

* @return the exception

185

*/

186

public Throwable getException();

187

}

188

```

189

190

**Usage Examples:**

191

192

```java

193

@Component

194

public class ApplicationLifecycleListener {

195

196

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

197

198

@EventListener

199

public void handleApplicationStarting(ApplicationStartingEvent event) {

200

logger.info("Application starting with args: {}", Arrays.toString(event.getArgs()));

201

}

202

203

@EventListener

204

public void handleEnvironmentPrepared(ApplicationEnvironmentPreparedEvent event) {

205

ConfigurableEnvironment env = event.getEnvironment();

206

logger.info("Environment prepared. Active profiles: {}",

207

Arrays.toString(env.getActiveProfiles()));

208

}

209

210

@EventListener

211

public void handleContextInitialized(ApplicationContextInitializedEvent event) {

212

logger.info("Application context initialized: {}",

213

event.getApplicationContext().getClass().getSimpleName());

214

}

215

216

@EventListener

217

public void handleApplicationPrepared(ApplicationPreparedEvent event) {

218

ConfigurableApplicationContext context = event.getApplicationContext();

219

logger.info("Application prepared. Bean count: {}", context.getBeanDefinitionCount());

220

}

221

222

@EventListener

223

public void handleApplicationStarted(ApplicationStartedEvent event) {

224

Duration timeTaken = event.getTimeTaken();

225

logger.info("Application started successfully in {} seconds",

226

timeTaken != null ? timeTaken.toSeconds() : "unknown");

227

}

228

229

@EventListener

230

public void handleApplicationReady(ApplicationReadyEvent event) {

231

Duration timeTaken = event.getTimeTaken();

232

logger.info("Application ready to service requests in {} seconds",

233

timeTaken != null ? timeTaken.toSeconds() : "unknown");

234

}

235

236

@EventListener

237

public void handleApplicationFailed(ApplicationFailedEvent event) {

238

Throwable exception = event.getException();

239

logger.error("Application failed to start", exception);

240

}

241

}

242

```

243

244

### Application Availability

245

246

Application availability states for health monitoring and readiness probes.

247

248

```java { .api }

249

/**

250

* Provides availability information for the application

251

*/

252

public interface ApplicationAvailability {

253

254

/**

255

* Return the AvailabilityState of the application for the given StateType

256

* @param stateType the state type

257

* @return the availability state (never null)

258

*/

259

<S extends AvailabilityState> S getState(Class<S> stateType);

260

261

/**

262

* Return the AvailabilityState of the application for the given StateType

263

* @param stateType the state type

264

* @param defaultState the default state to return if no state of the given

265

* type has been published yet

266

* @return the availability state (never null)

267

*/

268

<S extends AvailabilityState> S getState(Class<S> stateType, S defaultState);

269

270

/**

271

* Return the last AvailabilityChangeEvent received for a given state type

272

* @param stateType the state type

273

* @return the last change event or null

274

*/

275

<S extends AvailabilityState> AvailabilityChangeEvent<S> getLastChangeEvent(Class<S> stateType);

276

}

277

278

/**

279

* "Liveness" state of the application

280

*/

281

public enum LivenessState implements AvailabilityState {

282

283

/**

284

* The application is running and its internal state is correct

285

*/

286

CORRECT,

287

288

/**

289

* The application is running but its internal state is broken

290

*/

291

BROKEN

292

}

293

294

/**

295

* "Readiness" state of the application

296

*/

297

public enum ReadinessState implements AvailabilityState {

298

299

/**

300

* The application is ready to receive traffic

301

*/

302

ACCEPTING_TRAFFIC,

303

304

/**

305

* The application is not willing to receive traffic

306

*/

307

REFUSING_TRAFFIC

308

}

309

310

/**

311

* Base interface for availability states

312

*/

313

public interface AvailabilityState {

314

}

315

316

/**

317

* Application event fired when the AvailabilityState of the application changes

318

*/

319

public class AvailabilityChangeEvent<S extends AvailabilityState> extends ApplicationEvent {

320

321

/**

322

* Create a new AvailabilityChangeEvent instance

323

* @param source the source of the event

324

* @param state the availability state

325

*/

326

public AvailabilityChangeEvent(Object source, S state);

327

328

/**

329

* Return the new availability state

330

* @return the availability state

331

*/

332

public S getState();

333

334

/**

335

* Convenience method that can be used to publish an AvailabilityChangeEvent to the

336

* given application context

337

* @param context the context to publish the event to

338

* @param state the changed state

339

*/

340

public static <S extends AvailabilityState> void publish(ApplicationContext context, S state);

341

342

/**

343

* Convenience method that can be used to publish an AvailabilityChangeEvent to the

344

* given application context

345

* @param context the context to publish the event to

346

* @param source the source of the event

347

* @param state the changed state

348

*/

349

public static <S extends AvailabilityState> void publish(ApplicationContext context, Object source, S state);

350

}

351

```

352

353

**Usage Examples:**

354

355

```java

356

@Component

357

public class HealthMonitor {

358

359

@Autowired

360

private ApplicationAvailability applicationAvailability;

361

362

@Autowired

363

private ApplicationContext applicationContext;

364

365

@EventListener

366

public void handleAvailabilityChange(AvailabilityChangeEvent<?> event) {

367

AvailabilityState state = event.getState();

368

System.out.println("Availability changed to: " + state);

369

370

if (state == LivenessState.BROKEN) {

371

// Log critical error, notify monitoring systems

372

System.err.println("Application liveness is BROKEN!");

373

}

374

375

if (state == ReadinessState.REFUSING_TRAFFIC) {

376

// Application is not ready to handle requests

377

System.out.println("Application is not ready for traffic");

378

}

379

}

380

381

public void checkCurrentState() {

382

LivenessState liveness = applicationAvailability.getState(LivenessState.class);

383

ReadinessState readiness = applicationAvailability.getState(ReadinessState.class);

384

385

System.out.println("Current liveness: " + liveness);

386

System.out.println("Current readiness: " + readiness);

387

}

388

389

public void markApplicationAsReady() {

390

AvailabilityChangeEvent.publish(applicationContext, ReadinessState.ACCEPTING_TRAFFIC);

391

}

392

393

public void markApplicationAsBroken(Exception cause) {

394

System.err.println("Marking application as broken due to: " + cause.getMessage());

395

AvailabilityChangeEvent.publish(applicationContext, this, LivenessState.BROKEN);

396

}

397

}

398

399

// Custom availability indicator

400

@Component

401

public class DatabaseHealthIndicator implements ApplicationListener<ContextRefreshedEvent> {

402

403

@Autowired

404

private ApplicationContext applicationContext;

405

406

@Autowired

407

private DataSource dataSource;

408

409

@Override

410

public void onApplicationEvent(ContextRefreshedEvent event) {

411

// Check database connectivity on startup

412

try {

413

Connection connection = dataSource.getConnection();

414

connection.close();

415

// Database is healthy - application can accept traffic

416

AvailabilityChangeEvent.publish(applicationContext, ReadinessState.ACCEPTING_TRAFFIC);

417

} catch (SQLException e) {

418

// Database is unhealthy - refuse traffic

419

AvailabilityChangeEvent.publish(applicationContext, ReadinessState.REFUSING_TRAFFIC);

420

}

421

}

422

423

@Scheduled(fixedRate = 30000) // Check every 30 seconds

424

public void healthCheck() {

425

try {

426

Connection connection = dataSource.getConnection();

427

// Perform a simple query

428

PreparedStatement stmt = connection.prepareStatement("SELECT 1");

429

ResultSet rs = stmt.executeQuery();

430

rs.close();

431

stmt.close();

432

connection.close();

433

434

// Database is responsive

435

AvailabilityChangeEvent.publish(applicationContext, LivenessState.CORRECT);

436

} catch (SQLException e) {

437

// Database connection failed

438

AvailabilityChangeEvent.publish(applicationContext, LivenessState.BROKEN);

439

}

440

}

441

}

442

```

443

444

### Failure Analysis

445

446

System for analyzing and providing human-readable descriptions of application startup failures.

447

448

```java { .api }

449

/**

450

* A FailureAnalyzer is used to analyze a failure and provide diagnostic information

451

* that can be displayed to the user

452

*/

453

@FunctionalInterface

454

public interface FailureAnalyzer {

455

456

/**

457

* Returns an analysis of the given failure, or null if no analysis was possible

458

* @param failure the failure

459

* @return the analysis or null

460

*/

461

FailureAnalysis analyze(Throwable failure);

462

}

463

464

/**

465

* The result of performing failure analysis

466

*/

467

public class FailureAnalysis {

468

469

private final String description;

470

private final String action;

471

private final Throwable cause;

472

473

/**

474

* Creates a new FailureAnalysis with the given description and action

475

* @param description the description

476

* @param action the action

477

* @param cause the cause of the failure

478

*/

479

public FailureAnalysis(String description, String action, Throwable cause);

480

481

/**

482

* Returns a description of the failure

483

* @return the description

484

*/

485

public String getDescription();

486

487

/**

488

* Returns the action that the user should take to address the failure

489

* @return the action

490

*/

491

public String getAction();

492

493

/**

494

* Returns the cause of the failure

495

* @return the cause

496

*/

497

public Throwable getCause();

498

}

499

500

/**

501

* Abstract base class for most FailureAnalyzer implementations

502

*/

503

public abstract class AbstractFailureAnalyzer<T extends Throwable> implements FailureAnalyzer {

504

505

@Override

506

public final FailureAnalysis analyze(Throwable failure) {

507

T cause = findCause(failure, getCauseType());

508

if (cause != null) {

509

return analyze(failure, cause);

510

}

511

return null;

512

}

513

514

/**

515

* Returns the cause type that this analyzer handles

516

* @return the cause type

517

*/

518

protected abstract Class<T> getCauseType();

519

520

/**

521

* Returns an analysis of the given failure, or null if no analysis was possible

522

* @param rootFailure the root failure passed to the analyzer

523

* @param cause the actual found cause

524

* @return the analysis or null

525

*/

526

protected abstract FailureAnalysis analyze(Throwable rootFailure, T cause);

527

528

/**

529

* Find the cause of the specified type in the given failure

530

* @param failure the source failure

531

* @param type the type to find

532

* @return the cause or null

533

*/

534

protected final <E extends Throwable> E findCause(Throwable failure, Class<E> type) {

535

// Implementation details

536

return null;

537

}

538

}

539

```

540

541

**Usage Examples:**

542

543

```java

544

// Custom failure analyzer for database connection issues

545

@Component

546

public class DatabaseConnectionFailureAnalyzer extends AbstractFailureAnalyzer<SQLException> {

547

548

@Override

549

protected Class<SQLException> getCauseType() {

550

return SQLException.class;

551

}

552

553

@Override

554

protected FailureAnalysis analyze(Throwable rootFailure, SQLException cause) {

555

String description = String.format(

556

"Failed to connect to database: %s (Error code: %d)",

557

cause.getMessage(),

558

cause.getErrorCode()

559

);

560

561

String action = buildActionMessage(cause);

562

563

return new FailureAnalysis(description, action, cause);

564

}

565

566

private String buildActionMessage(SQLException cause) {

567

switch (cause.getErrorCode()) {

568

case 1045: // Access denied

569

return "Check your database credentials in application.properties:\n" +

570

"spring.datasource.username=<username>\n" +

571

"spring.datasource.password=<password>";

572

case 1049: // Unknown database

573

return "Verify that the database exists and the name is correct:\n" +

574

"spring.datasource.url=jdbc:mysql://localhost:3306/<database-name>";

575

default:

576

return "Verify your database configuration and ensure the database server is running.";

577

}

578

}

579

}

580

581

// Custom failure analyzer for missing properties

582

@Component

583

public class ConfigurationPropertyFailureAnalyzer extends AbstractFailureAnalyzer<BindException> {

584

585

@Override

586

protected Class<BindException> getCauseType() {

587

return BindException.class;

588

}

589

590

@Override

591

protected FailureAnalysis analyze(Throwable rootFailure, BindException cause) {

592

StringBuilder description = new StringBuilder();

593

StringBuilder action = new StringBuilder();

594

595

description.append("Binding to target ")

596

.append(cause.getTarget().getClass().getSimpleName())

597

.append(" failed:");

598

599

action.append("Update your application configuration:\n\n");

600

601

cause.getFieldErrors().forEach(error -> {

602

description.append("\n Property: ").append(error.getField())

603

.append("\n Value: ").append(error.getRejectedValue())

604

.append("\n Reason: ").append(error.getDefaultMessage());

605

606

action.append("# ").append(error.getDefaultMessage()).append("\n")

607

.append(error.getField()).append("=<correct-value>\n\n");

608

});

609

610

return new FailureAnalysis(description.toString(), action.toString(), cause);

611

}

612

}

613

```

614

615

### Context Initializers and Listeners

616

617

Interfaces for customizing application context initialization and listening to events.

618

619

```java { .api }

620

/**

621

* Callback interface for initializing a Spring ConfigurableApplicationContext

622

* prior to being refreshed

623

*/

624

@FunctionalInterface

625

public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {

626

627

/**

628

* Initialize the given application context

629

* @param applicationContext the application to configure

630

*/

631

void initialize(C applicationContext);

632

}

633

634

/**

635

* Interface to be implemented by application event listeners

636

*/

637

@FunctionalInterface

638

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

639

640

/**

641

* Handle an application event

642

* @param event the event to respond to

643

*/

644

void onApplicationEvent(E event);

645

}

646

```

647

648

**Usage Examples:**

649

650

```java

651

// Custom application context initializer

652

public class CustomApplicationContextInitializer

653

implements ApplicationContextInitializer<ConfigurableApplicationContext> {

654

655

@Override

656

public void initialize(ConfigurableApplicationContext applicationContext) {

657

// Add custom property sources

658

ConfigurableEnvironment environment = applicationContext.getEnvironment();

659

MutablePropertySources propertySources = environment.getPropertySources();

660

661

Properties customProps = new Properties();

662

customProps.put("app.initialized-by", "CustomInitializer");

663

customProps.put("app.initialization-time", Instant.now().toString());

664

665

propertySources.addFirst(new PropertiesPropertySource("custom", customProps));

666

667

// Register custom beans programmatically

668

BeanDefinitionRegistry registry = (BeanDefinitionRegistry) applicationContext;

669

registry.registerBeanDefinition("customBean",

670

BeanDefinitionBuilder.genericBeanDefinition(CustomService.class).getBeanDefinition());

671

672

System.out.println("Custom application context initializer executed");

673

}

674

}

675

676

// Register the initializer

677

@SpringBootApplication

678

public class Application {

679

public static void main(String[] args) {

680

SpringApplication app = new SpringApplication(Application.class);

681

app.addInitializers(new CustomApplicationContextInitializer());

682

app.run(args);

683

}

684

}

685

```