What's New in Spring Boot 4 & Spring Framework 7

🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.

▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube

▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube

Hi everyone, welcome back.

In late 2022, Spring Boot 3 and Spring Framework 6 delivered one of the biggest shifts we’d seen in the Spring ecosystem. They introduced a Java 17 baseline, migrated packages from javax.* to jakarta.*, and even brought early support for GraalVM native images.

Now, in 2025, the next generation is almost here: Spring Boot 4 and Spring Framework 7.

These releases continue the modernization journey. They adopt the latest Java features, align tightly with Jakarta EE 11, improve developer productivity, and add more resilient, cloud-ready support right out of the box.

Let’s dive into the key changes you need to know.


Baseline Upgrades

First, let’s talk baselines.

Java 17 remains the minimum requirement, thanks to its industry-wide adoption.

But if you want the newest JVM benefits like virtual threads and other language enhancements, Java 21 or Java 25 are strongly recommended.

With Spring Framework 7, Jakarta EE 11 is now fully adopted. That includes Servlet 6.1, JPA 3.2, and Bean Validation 3.1.

On the Kotlin side, version 2.2 and above is supported, bringing smoother coroutine integration and making reactive code even more natural.

These baselines ensure your applications are ready for the future while staying compatible with modern cloud environments.


Spring Boot 4 Highlights

Native Image Improvements

Spring Boot 4 pushes GraalVM native image support even further.

It’s fully aligned with GraalVM 24. Ahead-of-Time (AOT) processing has been enhanced, which means faster build times and a smaller startup memory footprint.

For example, Spring Data now introduces AOT Repositories — during AOT processing, query methods are turned into source code and compiled directly with your app. That makes native images start faster and use fewer resources.


Observability with Micrometer 2 and OpenTelemetry

Cloud-native apps need excellent observability.

Spring Boot 3 first introduced Spring Observability. Now, Spring Boot 4 upgrades to Micrometer 2 and integrates an OpenTelemetry starter.

This means your traces, logs, and metrics work seamlessly together — out of the box. Troubleshooting and performance monitoring become far simpler for modern distributed systems.


Improved SSL Health Reporting

SSL monitoring is now smarter.

If a certificate chain contains certificates that are expiring soon, you’ll now see them in a new expiringChains entry.

The previous WILL_EXPIRE_SOON status is gone. Instead, expiring certificates are reported as VALID, but flagged under expiringChains — reducing false alarms while keeping you informed about certificate health.


Modularization

One of the earliest milestones for Spring Boot 4 was refactoring its codebase into a more modular structure.

In Spring Boot 3, many core modules — like auto-configuration, starter dependencies, and build tools — were bundled into larger artifacts. This was convenient but sometimes made dependency management tricky and increased native-image footprints.

Starting with Spring Boot 4, auto-configurations and support code are split into smaller, more focused modules.

This modularization leads to: – Faster builds and native-image generation, because GraalVM doesn’t process unnecessary hints. – Cleaner dependency management, as optional integrations (Micrometer, OpenTelemetry, persistence tech) are now separate modules. – Better maintainability for the Spring team and contributors.

As developers, you might not notice the change if you’re using starter dependencies. For example, adding JPA with Hibernate is still as simple as:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

Under the hood, though, JPA auto-configuration, Hibernate integration, and validation setup are now in separate modules.

If you’re not using starter dependencies, you’ll need to review the new module structure — details are available on the Spring Boot GitHub Wiki.


New @ConfigurationPropertiesSource Annotation

Another feature improving modularization is the @ConfigurationPropertiesSource annotation.

This doesn’t change how configuration properties are bound at runtime. Instead, it’s a hint for the spring-boot-configuration-processor at build time.

In modular projects, property metadata could become incomplete if base classes or nested types lived in different modules.

By marking a class with @ConfigurationPropertiesSource, you ensure full metadata generation — even if the class itself isn’t directly annotated with @ConfigurationProperties.

This eliminates missing descriptions or default values in multi-module setups, making configuration processing more reliable and maintenance easier.


Spring Framework 7 Highlights

Testing Improvements

Spring uses context caching to balance test performance and isolation. But in previous versions, long-running integration tests could still consume resources while idle.

Spring Framework 7 introduces test context pausing. Now Spring can pause and resume contexts in the cache, saving memory and speeding up execution in large test suites. This is especially helpful for JMS listener containers or scheduled tasks that shouldn’t stay active when not needed.

Another addition is RestTestClient — a lightweight client for testing REST endpoints, similar to WebTestClient but without reactive dependencies.

Example:

@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(msg ->
                  assertThat(msg.getResponseBody()).containsIgnoringCase("hello"));
    }
}

API Versioning

One of the most requested features now arrives: first-class API versioning.

Instead of rolling your own versioning strategies, Spring now supports version attributes directly.

Example:

@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";
    }
}

You can also version at the controller level:

@RestController
@RequestMapping(path = "/hello", version = "3")
public class HelloWorldV3Controller {
    @GetMapping(produces = MediaType.TEXT_PLAIN_VALUE)
    public String sayHello() {
        return "Hey World";
    }
}

Supported strategies include: – Path-based mapping (/api/v1/hello) – Query-parameter mapping (/hello?version=1) – Request-header mapping (X-API-Version: 1) – Media-type header mapping (Accept: application/json; version=1)

Configuration example:

@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 Clients with @HttpServiceClient

Spring 7 now includes declarative HTTP client support, inspired by Feign but lighter and fully integrated.

Example interface:

@HttpServiceClient("christmasJoy")
public interface ChristmasJoyClient {

    @GetExchange("/greetings?random")
    String getRandomGreeting();
}

Register and configure:

@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, builder) ->
                      builder.baseUrl("https://christmasjoy.dev/api"));
        };
    }
}

The ChristmasJoyClient can then be injected into controllers or services as usual.


Built-In Resilience Annotations

Retry logic and concurrency limits are now first-class citizens.

You can annotate methods directly:

@GetExchange("/greetings?random")
@Retryable(maxAttempts = 3, delay = 100, multiplier = 2, maxDelay = 1000)
@ConcurrencyLimit(3)
String getRandomGreeting();

Enable them by adding @EnableResilientMethods to a configuration class. This simplifies resilience without third-party libraries, while still integrating well with tools like Resilience4j.


Multiple TaskDecorator Beans

In older versions, you could only register one TaskDecorator. Now, Spring 7 lets you declare multiple decorators, and Spring will chain them automatically.

Example decorators for logging and timing:

@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 ts1 = System.currentTimeMillis();
            try { runnable.run(); }
            finally {
                long ts2 = System.currentTimeMillis();
                log.info("Finished within {}ms (Task: {})", ts2 - ts1, runnable);
            }
        };
    }
}

This eliminates boilerplate composite decorators and simplifies async customization.


Null Safety with JSpecify

Spring adopts JSpecify for nullability annotations. Instead of a mix of @Nonnull, @Nullable, or @NotNull, you now get a single, modern standard.

Example:

@Override
public void configureApiVersioning(@NonNull ApiVersionConfigurer configurer) {
    configurer.usePathSegment(1);
}

This improves IDE tooling, Kotlin interop, and reduces the risk of NullPointerExceptions.


Deprecations and Removals

With modernization comes cleanup:

  • javax.* packages are removed — only Jakarta EE 11 is supported.
  • Jackson 2.x support is dropped — upgrade to Jackson 3.x.
  • Spring JCL (logging bridge) is gone in favor of Apache Commons Logging.
  • JUnit 4 support is deprecated — migrate to JUnit 5.

Plan these migrations early to avoid surprises.


Conclusion

Spring Boot 4 and Spring Framework 7 are not just incremental updates. They represent a modern, modular, cloud-native era for Java developers.

  • API versioning and resilience annotations make applications easier to evolve and harden.
  • JSpecify null safety and updated Kotlin support reduce runtime errors.
  • Declarative HTTP clients simplify service-to-service calls.
  • Native image improvements and observability tooling improve cloud readiness.

As always with major upgrades, start testing your apps early — especially around dependency updates and deprecated APIs.

But the benefits — better performance, cleaner architecture, and improved developer productivity — make the transition worthwhile.

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare