Spring Boot 4 & Spring Framework 7: Key Features, Code Samples, and Upgrade Guide
This article reviews the major enhancements in Spring Boot 4 and Spring Framework 7, covering baseline requirements, performance boosts, native image support, modularization, new annotations, API versioning, declarative HTTP clients, resilient method support, multiple TaskDecorators, and null‑safety improvements, with practical code examples to help developers plan their migration.
At the end of 2022 Spring Boot 3 and Spring Framework 6 were released, marking the biggest overhaul of the Spring ecosystem since its inception: Java 17 became the minimum version, the old javax.* packages were replaced by jakarta.*, and GraalVM native images received initial support.
Fast‑forward to 2025, the next generation – Spring Boot 4 and Spring Framework 7 – is about to arrive, continuing the push toward a modernized ecosystem. They adopt the latest Java language features, align tightly with Jakarta EE 11, and provide out‑of‑the‑box support for building resilient applications without extra effort.
The following sections outline the core highlights of these two versions, supplemented with explanations and code snippets.
Baseline Upgrade
Java 17 remains the minimum required JDK, but the Spring team strongly recommends Java 21 or even Java 25 to take advantage of virtual threads and other new JVM capabilities.
Spring Framework 7 fully supports Jakarta EE 11, meaning the underlying standards have been upgraded to Servlet 6.1, JPA 3.2, and Bean Validation 3.1.
Kotlin 2.2+ is now supported, making coroutine‑based and reactive code feel more natural.
Spring Boot 4
Spring Boot 4 brings several practical improvements: faster performance, easier monitoring, reduced maintenance overhead, and stronger configuration support, solidifying its role as the foundation for modern cloud‑native Java applications.
Native Image Support Gets Stronger
Spring Boot 4 pushes GraalVM native‑image support further, now fully aligned with GraalVM 24. The ahead‑of‑time (AOT) compilation capability has been optimized, resulting in quicker compilation and lower memory consumption at startup.
For example, Spring Data adds an AOT repository feature that converts query methods into source code during AOT processing, improving runtime efficiency.
Monitoring Made Simpler: Micrometer 2 + OpenTelemetry
Observability is crucial for cloud‑native apps. Spring Boot 4 upgrades to Micrometer 2 and integrates an OpenTelemetry starter, allowing seamless collection of trace logs, regular logs, and metrics without additional wiring.
SSL Certificate Expiration Visibility
The new expiringChains entry shows certificates that are about to expire, replacing the old WILL_EXPIRE_SOON status. Expiring certificates are now marked as VALID, reducing false alarms during production monitoring.
Modularization of Core Code
Spring Boot 4 encourages a more modular codebase. Previously, core modules such as auto‑configuration and starter dependencies were bundled into large artifacts, leading to messy dependency management and slower class‑path scanning. Now, auto‑configuration and support code are split into smaller modules, offering three main benefits:
Faster native‑image builds: unnecessary metadata is omitted during GraalVM AOT processing.
Cleaner dependency management: optional features like Micrometer and OpenTelemetry are packaged separately.
Easier maintenance for the Spring team and contributors.
For developers, the change is mostly invisible when using starter dependencies. Adding JPA support, for instance, only requires the following Maven dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>Under the hood, JPA auto‑configuration, Hibernate integration, and validation settings are now loaded from distinct modules, allowing the framework to load only the necessary configuration at runtime or during AOT compilation.
New @ConfigurationPropertiesSource Annotation
A new @ConfigurationPropertiesSource annotation helps with cross‑module configuration. It does not change runtime property binding but signals the spring-boot-configuration-processor during build time to generate complete metadata for classes that lack @ConfigurationProperties, preventing missing property descriptions or default values in modular projects.
Spring Framework 7
Spring Framework 7 adds many long‑awaited features and refines testing, API design, and core fundamentals, making the framework more modern and reducing boilerplate code.
More Flexible Testing
The framework now supports “test‑context pause” – cached application contexts can be paused and resumed, saving memory and speeding up large test suites, especially for JMS listeners and scheduled tasks. It also introduces a RestTestClient for convenient REST‑API testing without requiring reactive infrastructure.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class HelloWorldApiIntegrationTest {
RestTestClient client;
@BeforeEach
void setUp(WebApplicationContext context) {
client = RestTestClient.bindToApplicationContext(context).build();
}
@Test
void shouldFetchHelloV1() {
client.get()
.uri("/api/v1/hello")
.exchange()
.expectStatus().isOk()
.expectHeader().contentTypeCompatibleWith(MediaType.TEXT_PLAIN)
.expectBody(String.class)
.consumeWith(message -> assertThat(message.getResponseBody()).containsIgnoringCase("hello"));
}
}API Versioning as a First‑Class Feature
Spring now provides built‑in API versioning. Adding a version attribute to @GetMapping (or to the controller level) enables versioned endpoints without custom routing logic. Four mapping strategies are supported: path segment, query parameter, request header, and media‑type header.
@RestController
@RequestMapping("/hello")
public class HelloWorldController {
@GetMapping(version = "1", produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHelloV1() { return "Hello World"; }
@GetMapping(version = "2", produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHelloV2() { return "Hi World"; }
}
@Configuration
public class ApiConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer.usePathSegment(1);
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix("/api/v{version}", HandlerTypePredicate.forAnnotation(RestController.class));
}
}Declarative HTTP Client: @HttpServiceClient
Spring Framework 7 introduces a lightweight, Feign‑inspired declarative HTTP client. Annotate an interface with @HttpServiceClient and define request methods with @GetExchange (or other exchange annotations). The client can be injected like any other Spring bean.
@HttpServiceClient("christmasJoy")
public interface ChristmasJoyClient {
@GetExchange("/greetings?random")
String getRandomGreeting();
}
@Configuration
@Import(HttpClientConfig.HelloWorldClientHttpServiceRegistrar.class)
public class HttpClientConfig {
static class HelloWorldClientHttpServiceRegistrar extends AbstractClientHttpServiceRegistrar {
@Override
protected void registerHttpServices(GroupRegistry registry, AnnotationMetadata metadata) {
findAndRegisterHttpServiceClients(registry, List.of("com.baeldung.spring.mvc"));
}
}
@Bean
RestClientHttpServiceGroupConfigurer christmasJoyServiceGroupConfigurer() {
return groups -> groups.filterByName("christmasJoy")
.forEachClient((group, clientBuilder) -> clientBuilder.baseUrl("https://christmasjoy.dev/api"));
}
}
@RestController
@RequestMapping(path = "/hello", version = "4")
@RequiredArgsConstructor
public class HelloWorldV4Controller {
private final ChristmasJoyClient christmasJoy;
@GetMapping(produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHello() {
return this.christmasJoy.getRandomGreeting();
}
}Built‑in Resilience Annotations
Spring Retry is now part of the core framework. Adding @Retryable or @ConcurrencyLimit to methods (including those in declarative HTTP clients) enables retry and rate‑limiting without external libraries. Enable the feature with @EnableResilientMethods on a configuration class.
@HttpServiceClient("christmasJoy")
public interface ChristmasJoyClient {
@GetExchange("/greetings?random")
@Retryable(maxAttempts = 3, delay = 100, multiplier = 2, maxDelay = 1000)
@ConcurrencyLimit(3)
String getRandomGreeting();
}
@Configuration
@EnableResilientMethods
public class ResilienceConfig { }Multiple TaskDecorator Support
Spring 7 allows declaring multiple TaskDecorator beans. The framework chains them in order (or by @Order), enabling composable concerns such as logging, timing, security context propagation, etc., without writing a custom composite decorator.
@Configuration
@Slf4j
public class TaskDecoratorConfiguration {
@Bean
@Order(2)
TaskDecorator loggingTaskConfigurator() {
return runnable -> () -> {
log.info("Running Task: {}", runnable);
try { runnable.run(); } finally { log.info("Finished Task: {}", runnable); }
};
}
@Bean
@Order(1)
TaskDecorator measuringTaskConfigurator() {
return runnable -> () -> {
long start = System.currentTimeMillis();
try { runnable.run(); } finally {
long end = System.currentTimeMillis();
log.info("Finished within {}ms (Task: {})", end - start, runnable);
}
};
}
}JSpecify Null‑Safety
Spring Framework 7 adopts JSpecify as the standard for null‑safety annotations, replacing the myriad of @Nullable/@NonNull annotations in the ecosystem. This improves IDE support, Kotlin inter‑op, and reduces the risk of NullPointerExceptions in large codebases.
Conclusion
API versioning and built‑in resilience annotations make upgrades smoother and applications more robust.
JSpecify null‑safety and Kotlin support dramatically cut runtime null‑pointer errors.
Declarative HTTP clients eliminate boilerplate when services call each other.
Enhanced native‑image support and observability tooling streamline cloud deployments.
As with any major version upgrade, early testing is essential—especially for dependency upgrades and API replacements. The effort pays off with higher developer productivity, better performance, and easier maintenance.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
