Spring Framework 7 & Spring Boot 4: What’s New
The upcoming release of Spring Framework 7 and Spring Boot 4 is a major milestone in the Java ecosystem. Almost every modern Java project I work on uses Spring, so this release matters. While Spring regularly ships monthly bug fixes and introduces smaller features through minor version updates, new major versions typically arrive every 3–5 years.
Spring 6 and Spring Boot 3 aligned their release schedules in November 2022, and now Spring 7 and Boot 4 are expected in November 2025. These major releases focus on updated baselines, cleanup of deprecated features, and a handful of new capabilities.
Below, I’ll cover the baseline changes, deprecations, removals, and new features developers should be aware of, especially the powerful new API Versioning support.
Baseline Changes in Spring 7 / Spring Boot 4
Unlike past major versions, this release does not increase the Java baseline, though the Spring team strongly recommends using the latest LTS (currently JDK 25). Key baseline updates include:
- Servlet 6.1 → Requires Tomcat 11, Jetty 12.1, Undertow support pending.
- JPA 3.2 → A minor bump, but requires Hibernate ORM 7 (a major upgrade for most projects).
- Bean Validation 3.1 → Requires Hibernate Validator 9.
- Other Baseline Updates:
- GraalVM 24
- Netty 4.2
- JSONassert 2.0
- Kotlin 2.2 (significant jump from 1.9 → 2.2, with notable JPA gotchas improving release over release).
Removals and Deprecations
Major Removals
- Spring JCL → Removed in favor of Apache Commons Logging.
- javax support → Fully removed; replaced with Jakarta EE equivalents.
- Spring Security Path Mappings → Deprecated matchers now removed.
- OkHttp3 → Dropped; OkHttp4 is now the standard.
Key Deprecations
- Jackson 2.x → Deprecated in favor of Jackson 3.x (auto-config support for 2.x removed in Spring 7.1).
- JUnit 4 → Deprecated, with migration encouraged to JUnit 5.
- Spring JSR 305 Annotations → Deprecated in favor of JSpecify.
New Features in Spring 7 / Spring Boot 4
General Enhancements
- SpEL improvements (optional support, null-safe, Elvis operator).
- Class-File API support (Java 24+).
- JSpecify Annotations standardize nullability across the Java ecosystem.
Integrated Projects & Clients
- Spring Retry → Core: Now fully part of the Spring Framework.
- JmsClient: Auto-configured in Spring Boot 4, simplifying client development.
- Programmatic Bean Registration via the new BeanRegistrar interface.
- HTTP Interface Client Config: Easier setup for request/response configuration.
- Message Converters: Centralized configuration for WebMvc.
Deep Dive: API Versioning in Spring 7
Of all the new features, API Versioning is the one I’m most excited about. Versioning REST APIs has always been a pain point. Spring 7 introduces first-class support for API versioning directly in @RequestMapping annotations, letting you configure versions cleanly through:
- Path-based versioning (e.g., /api/v1/resource).
- Request parameter versioning.
- Header-based versioning (ideal for client-injected version control).
By default, API versioning is disabled—but enabling it in a WebMvcConfigurer is straightforward.
Path Index Example
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer
.useRequestHeader(“X-API-Version”)
.usePathSegment(2);
}
}
Here is an example of setting up manual configuration of the API versions being supported: You can see here a simple override in the WebMvcConfigurer to set up the API versioning.
Auto Detection is on by default so you can see here I disable detecting versions and setup everything manually, including a request param name to find a version and a default when one isn’t specified.
public class WebConfig implements WebMvcConfigurer {
// A more manual versioning configuration
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer
.addSupportedVersions(“1.0“, “1.1“, “2.0“) //Manually declare supported Versions
.detectSupportedVersions(false)
.setDefaultVersion(“2.0“)
.useRequestParam(“ApiVersion“); // Use a custom request param to specify the API version
}
}
Personally, I’ve never been a fan of using versioning in the URL path, as this typically means a controller for each version. Depending on the abstractions in play, this may still be necessary, as basic CRUD abstractions can be streamlined to create endpoints quickly and consistently. For myself personally, I’m expecting something similar to the following, where I can provide the API via headers so I can inject it on my client side and let the controllers handle the versioning from there:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer
.useRequestHeader(“X-API-Version“);
}
}
Since this is the setup that appeals to me, I’m going to deep dive into this, going over the results and adjustments I make to get this working as I would expect.
Early Testing Notes
While testing the header-based approach, I found a few quirks:
- A default version must be explicitly set (e.g., .setDefaultVersion(“1.0”)).
- Version ranges (1.1+) are not perfectly supported without customizing the ApiVersionConfigurer.
- Managing supported versions requires manual setup or writing a more advanced visitor.
Still, this represents a huge leap forward in API lifecycle management, especially for teams supporting multiple external or internal API versions.
@RestController
@RequestMapping(value = “/api/testing“)
public class TestController {
@GetMapping(“/hello”)
public String hello() {
return “Hello from API version 1.0“;
}
@GetMapping(value = “/hello“, version= “1.1+“)
public String helloV11() {
return “Hello from API version 1.1“;
}
@GetMapping(value = “/hello“, version= “2.0“)
public String helloV20() {
return “Hello from API version 2.0“;
}
@GetMapping(value = “/goodbye“)
public String goodbye() {
return “Goodbye from API version 1.0“;
}
}
My first test, of course, threw me for a loop. I started with the no header request, which I expected to leverage the default /hello endpoint. Instead, I got a 404. To achieve my expected results, I would need to add.setDefaultVersion(“1.0”) to ensure a version is set for the request. I added the additional configuration to the WebConfig and then continued the testing.
Most of the endpoints didn’t work as I would expect. If I sent a request with 1.0 version, I got a 400 response, which should have used the default version endpoint. If I sent a request with no version and let the default version be applied by the handler, I got the default endpoint response(1.0).
Sending an API version of 1.1 worked, but 1.2 gave me a bad request as well. The built-in version visitor drops the + and adds the base version to the supported versions list. The processing in the handler makes sure a version is in the supported versions list before attempting to send it to the handler. This means if using a default endpoint or version range endpoint, you may have to manually manage the supported versions list in the ApiVersionConfigurer. To make it so any version between 0.0 to 0.20, then 1.0 to 1.20, and additionally version 2.0 worked for the endpoint above, I ended up using a configuration like the following:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
Collection<String> versionList = new ArrayList<>();
IntStream.rangeClosed(0, 20)
.forEach(i ->
{
versionList.add(“0.“ + i);
versionList.add(“1.“ + i);
});
versionList.add(“2.0“);
configurer
.addSupportedVersions(versionList.toArray(new String[0]))
.useRequestHeader(“X-API-Version“)
.setDefaultVersion(“0.0“);
}
}
There would be two ways to manage the versioning. Manually, as shown above, or by writing a more complex visitor that would be used during startup to update the supportedVersions list. The out-of-the-box visitor used does not support managing endpoints with ranges very well.
There is also support for the deprecated version response. I will save that for a re-examination of the API versioning in the future, when it is closer to release. Overall, I believe this is a valuable addition to the Spring Framework, making API versioning easier to manage.
Conclusion
While Spring 7 / Boot 4 may not include radical must-have features, the API Versioning support stands out as a game-changer for REST API development. Baseline upgrades, Jakarta EE alignment, and smoother client integrations also make this a meaningful release.
If you’re starting a new project later this year, it will likely make sense to adopt Spring 7 / Boot 4 right away. For existing projects, planning ahead for Jackson 3.x, JUnit 5, and Jakarta EE migrations will ensure a smoother transition.
Want to see how your applications can take advantage of Spring 7 and Boot 4?
At RBA, our teams help organizations modernize applications, upgrade frameworks, and implement API best practices.
Contact us today to prepare your systems for the future of Spring.
About the Author
Adam Utsch
Senior Principal Consultant
Adam is a seasoned software professional with deep experience in development, deployment, and application support. With a strong engineering foundation, they specialize in building scalable solutions and mentoring others in the technologies that drive real impact. Adam is passionate about continuous improvement, collaboration, and staying ahead of the tech curve.