Spring Framework 7.0

Released November 13 2025. Home+2GitHub+2
Some of the major headlines:
- The baseline continues to be Java 17 (well-adopted LTS), but the release recommends Java 25. GitHub+2Home+2
- It aligns with Jakarta EE 11 (Servlet 6.1, JPA 3.2, Bean Validation 3.1) rather than older Java EE namespaces. GitHub+1
- Null-safety support through JSpecify annotations (
@NonNull,@Nullable) across the Spring portfolio. InfoQ - API versioning support built into MVC/WebFlux (path/header/query/media‐type strategies). InfoQ+1
- Built-in resilience features:
@Retryable,@ConcurrencyLimit, etc. That means the framework itself takes on concerns formerly handled by separate libraries. Home+1
In short: Spring Framework 7 is less about huge new flashy APIs, and more about modernizing the foundations, trimming boilerplate, aligning with modern Java ecosystems, and enabling safer and more maintainable code.
Spring Boot 4.0
Released November 20 2025. Home+1
Key updates include:
- Built on Spring Framework 7, so you get all of the above.
- Modularization: The large
spring-boot-autoconfigurejar is being broken up into smaller, more focused modules. Smaller footprint, faster IDE completions, less “what does this starter bring in” guesswork. GitHub - HTTP Service Clients support: you can declare plain Java interfaces and Spring will automatically provide implementations via
@HttpExchange, etc. Less boilerplate REST client code. GitHub+1 - Built-in API versioning support via properties like
spring.mvc.apiversion.*/spring.webflux.apiversion.*. GitHub+1 - Support for Kotlin 2.2 as baseline, better Kotlin integration. The JetBrains Blog+1
- Java 25 support (while keeping Java 17 baseline) to allow you to adopt newer JVM features while maintaining compatibility. Home+1
Why this matters
Here’s what this really means for you as a developer or architect:
- If your team is still on Java 11 or Java 8, these releases mark a clear signal: you’ll want to plan upgrading to Java 17 at a minimum, and consider Java 25 when feasible.
- The API versioning support is a big win if you’re building public-facing REST services with versioning requirements (path, header, media type). Previously you’d wire your own strategies; now Spring gives you first-class support.
- The modularization in Boot means lighter weight services: less “starter brings in everything”, better visibility, potentially faster startup and smaller packaging.
- Null-safety annotations and improved Kotlin support mean fewer runtime surprises, fewer null pointer issues, better developer ergonomics (especially if you mix Java/Kotlin).
- Built-in resilience (retry, concurrency limits) means you can standardize your error handling and fault-tolerance logic rather than scatter custom solutions.
- For teams using Kotlin, Microservices, or modern build tools (Gradle 9 is supported) these releases give you an opportunity to refresh tooling and align with state‐of‐the‐art ecosystem. GitHub
Migration and upgrading – what to watch out for
Since these are major releases, some caution and planning is needed. Here are some things you’ll want to check.
Baseline versions
- Ensure your project uses at least Java 17. While Java 25 is supported and recommended, you can keep 17 for now.
- If you rely on older Jakarta/Javax namespaces (e.g.,
javax.*), you’ll need to address the shift tojakarta.*in Spring Framework 7.0. InfoQ - Make sure dependencies you use (Hibernate version, servlet container, etc.) are compatible with the new Jakarta EE 11 alignment (e.g., Servlet 6.1). GitHub
Configuration and behavioural changes
- Because Boot’s auto-configure modules are broken up, if you had custom logic that assumed one big jar/one big starter you may need to update your dependencies.
- The HTTP Service Client feature: if you adopt it, you may want to refactor existing REST clients to the new interface-based model. Example (in Kotlin) from Medium:
@HttpExchange("https://jsonplaceholder.typicode.com") interface TodoClient { @GetExchange("/todos") fun getTodos(): List<Todo> @GetExchange("/todos/{id}") fun getTodoById(@PathVariable id: Long): Todo? @PostExchange("/todos") fun createTodo(@RequestBody todo: Map<String, String>) } @Configuration @ImportHttpServices(TodoClient::class) class ClientsConfigurationMedium - API versioning: you’ll want to revisit how your controllers are annotated if you previously used home-grown versioning. Example (from InfoQ) shows:
@GetMapping(url = "/accounts/{id}", version = "1.1")InfoQ - Null-safety: you may need to annotate your code with
@NonNull/@Nullableand ensure you’re aware which APIs now leverage those annotations. - Test context behaviour: in Spring Framework 7, the test context can be paused when idle to save memory, which may affect some custom test lifecycle hooks. Baeldung on Kotlin
Breaking changes / deprecated features
- Some modules or APIs may have been removed or deprecated—always check the “Removed APIs” section. For example, in Spring Framework 7 the
spring-jclmodule is removed, replaced by Apache Commons Logging. GitHub - For Boot, you’ll want to check the “Configuration Changelog” which details property changes, default behaviours changed, etc. GitHub
Example: How you might start using these new features
Let’s say you’re building a REST microservice using Kotlin + Spring Boot for one of your Android-backend systems (fits nicely with your Android work).
Setting up the project (Gradle)
plugins {
id("org.springframework.boot") version "4.0.0"
kotlin("jvm") version "1.9.x"
kotlin("plugin.spring") version "1.9.x"
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(25))
}
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
// If you use Spring Data, etc.
// Additional modules...
}
Defining an HTTP Service Client
@HttpExchange("https://api.mycompany.com")
interface AccountClient {
@GetExchange("/accounts/{id}")
fun getAccount(@PathVariable id: Long): AccountResponse
@PostExchange("/accounts")
fun createAccount(@RequestBody request: CreateAccountRequest): AccountResponse
}
@Configuration
@ImportHttpServices(AccountClient::class)
class ClientConfig
With this you avoid writing RestTemplate/WebClient boilerplate. Using the new feature means your client looks like a clean POJO interface.
Versioned REST Controller
@RestController
@RequestMapping("/v{version}/accounts", version = "1")
class AccountControllerV1(private val service: AccountService) {
@GetMapping("/{id}")
fun getAccount(@PathVariable id: Long): AccountDto {
return service.findById(id)
}
// other endpoints
}
Then later:
@RestController
@RequestMapping("/v{version}/accounts", version = "2")
class AccountControllerV2(private val service: AccountServiceV2) {
// new behaviour
}
Spring’s built-in API versioning means you can do media-type, header or query param versioning if you prefer. You save a lot of custom wiring. (Feature introduced in Spring Framework 7/Boot 4) InfoQ+1
Null‐safe Kotlin interop example
@Service
class UserService {
fun findUser(id: Long): User? {
// return null if not found
}
}
If you annotate your Kotlin types and interoperate with Java APIs that now carry @Nullable/@NonNull, you get better compiler-assisted null safety. This reduces the runtime NPE risks.
Should you upgrade now – and how to plan it
Here’s a practical recommendation based on your situation:
- If you’re starting a new project, go ahead and pick Spring Boot 4.0 + Framework 7.0 now. It gives you long-term alignment, modern features and avoids later large upgrade effort.
- If you have an existing project (for instance your Android-backend systems, daily post apps etc) on Spring Boot 3.x:
- Check dependencies: Are all your libraries compatible with Jakarta EE 11 (Servlet 6.1 etc)?
- Plan the upgrade path: It’s recommended to move to Spring Boot 3.5 first (if you’re not already), then to 4.0. GitHub
- Allocate time for testing: API versioning changes, autoconfiguration changes, module boundaries may expose surprises.
- For production critical systems: let the community stabilize for a short period (e.g., 2–3 minor releases) unless you’re actively needing the new features. But don’t delay too long: staying on older major versions means more technical debt.
My verdict
From my perspective, these releases are important. They don’t simply add flashy new endpoints — they modernize the foundation of Spring development. For you, as a developer working on Android-backends, microservices, Kotlin, clean architecture and modern build systems, they offer real benefit: less boilerplate, stronger defaults, better future-proofing.
That said: the upgrade isn’t trivial. It’s worth planning, especially if you have legacy code or heavy dependencies.