Files
spring-boot-demo/actuator-in-production/docs/02-boot-4-changes.md
Ankur Mhatre 958b401f0f Spring Boot startup time: bean-by-bean diagnosis, and one directory per post
Adds spring-boot-startup-time/, the companion project for BLOG-618: a runnable
Spring Boot 4.1.1 application on JDK 25 that installs BufferingApplicationStartup
and FlightRecorderApplicationStartup behind a system property, and a /diag/startup
endpoint that computes step self time -- the number /actuator/startup does not give
you and the one that names the actual culprits.

Captured under docs/output/: the step tree sorted both ways, the same startup as JFR
events, a +5000-class experiment putting 0.11 ms per scanned class on the classpath
scan tax, the silent truncation a 2048-step buffer performs, and JDK 25 AOT cache
timings (6.93 s to 4.82 s). Post body and metadata live in post/.

Moves the existing Actuator project into actuator-in-production/ so the repository
holds one directory per article; the root README is now an index.
2026-09-05 00:17:37 +05:30

108 lines
4.4 KiB
Markdown

[← 01 What Actuator exposes](01-what-actuator-exposes.md) · **02 · What changed in Spring Boot 4** · [03 The endpoint catalogue →](03-endpoint-catalogue.md)
# 02 — What changed in Spring Boot 4
Every claim below was checked against the 4.1.1 jars with `javap`, or against the 3.5.16 jars
for the "before" side. None of it came from a migration blog.
## `HealthIndicator` moved module and package
This is the one that breaks every custom health indicator ever written.
```
Boot 3.5.16 org.springframework.boot.actuate.health.HealthIndicator (spring-boot-actuator)
Boot 4.1.1 org.springframework.boot.health.contributor.HealthIndicator (spring-boot-health)
```
`org.springframework.boot.actuate.health` does not exist in Boot 4.1.1 at all — not deprecated,
absent. `Health`, `Status`, `AbstractHealthIndicator`, `HealthContributor` and the composites
all moved with it, into a new `spring-boot-health` module.
Two neighbouring packages in the same new module are worth knowing:
- `org.springframework.boot.health.application``DiskSpaceHealthIndicator`,
`LivenessStateHealthIndicator`, `ReadinessStateHealthIndicator`, `SslHealthIndicator`
- `org.springframework.boot.health.registry``HealthContributorRegistry`, which is how
[`DiagnosticsEndpoint`](../src/main/java/com/ankurm/actuator/web/DiagnosticsEndpoint.java)
enumerates contributors at runtime
## The interface method was renamed
```java
// Boot 3.5.16
public interface HealthIndicator extends HealthContributor {
default Health getHealth(boolean includeDetails);
Health health();
}
// Boot 4.1.1
public interface HealthIndicator extends HealthContributor {
default Health health(boolean includeDetails);
Health health();
}
```
If you overrode `getHealth(boolean)` — which people do to control detail rendering — it now
silently stops being an override. Add `@Override` and let the compiler find it.
`Health` also stopped extending `HealthComponent`; that class is gone from Boot 4.1.1 entirely.
## `EndpointRequest` moved too
```
Boot 3.5.16 org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest
Boot 4.1.1 org.springframework.boot.security.autoconfigure.actuate.web.servlet.EndpointRequest
```
Same class, same static methods (`toAnyEndpoint()`, `to(Class...)`, `to(String...)`,
`toLinks()`, `toAdditionalPaths(...)`), new package, and it now ships in `spring-boot-security`
rather than `spring-boot-actuator-autoconfigure`. The reactive variant made the equivalent move.
## `RestClient` is not in the web starter any more
Boot 4 split the framework into fine-grained modules, and `RestClient` auto-configuration went
with it. Adding `spring-boot-starter-webmvc` and injecting `RestClient.Builder` fails at
startup:
```
Parameter 0 of constructor in com.ankurm.actuator.health.ExternalApiHealthIndicator
required a bean of type 'org.springframework.web.client.RestClient$Builder' that could not be found.
```
The fix is one dependency:
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-restclient</artifactId>
</dependency>
```
This cost a startup cycle while building this repository, which is why it is documented here
rather than glossed over.
## Liveness and readiness probes are on by default
From the 4.0 migration guide, and confirmed by running the app with no configuration at all —
`/actuator/health` reports `"groups":["liveness","readiness"]` out of the box. Turn them off
with `management.endpoint.health.probes.enabled=false` if you genuinely do not want them.
## Nullability annotations
Actuator endpoint parameters can no longer use `org.springframework.lang.Nullable` to mark a
parameter optional. Migrate to `org.jspecify.annotations.Nullable`.
## There is no Micrometer 2
Several migration write-ups claim Boot 4 replaces "legacy Actuator endpoints" with a
"Micrometer 2 observability stack". Spring Boot 4.1.1 resolves **Micrometer 1.17.1**
(`docs/output/00-versions.txt`), and `maven-metadata.xml` for `micrometer-core` shows 1.17.1 as
the newest GA with 1.18.0-M1 as a milestone. Metrics *did* move to their own module
(`spring-boot-micrometer-metrics`, which `spring-boot-starter-actuator` still pulls in), and
there is a new `spring-boot-starter-opentelemetry`. Neither of those is a major Micrometer
release.
---
[← 01](01-what-actuator-exposes.md) · **02** · [03 The endpoint catalogue →](03-endpoint-catalogue.md)