Spring Framework shape Java Enterprise development for decades. It's started in 2004.
- 2004 - Version 1.0 - First production-ready release.
- 2006 - Version 2.0 - Simplified XML configuration and introduced custom namespaces.
- 2009 - Version 3.0 - Java 5 support, Spring Expression Language (SpEL), and Java-based configuration.
- 2013 - Version 4.0 - First version with full support for Java 8.
- 2017 - Version 5.0 - Introduction of Spring WebFlux (reactive programming)
- 2022 - Version 6.0 - Baseline moved to Java 17+ and Jakarta EE9.
- 2025 - Version 7.0 - Latest major generation focusing on Java 25 and modern cloud ecosystem.
Later something excited came out. It called Spring Boot to support auto configurations and production ready.
By now Spring Boot reached version 4 and supported Java 25. Spring Boot 4 released with many features. Learn more here.
There are 2 features is my favorite:
- API Versioning
- HTTP Service Client Enhancements
In this blog I'll cover only API Versioning. In the past each backend team they have different approach for API Versioning.
For a simple example, flight booking system have two main backend components.
- Booking: support by booking team to record booking information from user.
- Checkout: support by payment team to handle payment transactions.
Front end (Web UI) team has to integrate into both components. If both backends didn't have consistent approach. UI will cost double effort to integrate.
Imagine the backend have different API for mobile and other external system integration. Managing the version might became messy.
Spring Boot saw this problem; they came up with 4 standards strategy. In your project, you can use only one strategy across project.
- Path Segment Versioning
- Request Header Versioning
- Query Parameter Versioning
- Media Type Versioning
Additional configuration is needed to make API version work. As always spring boot offer Java class configuration or properties configuration.
Without version strategy configuration, your application will throw below error.
Caused by: java.lang.IllegalStateException: API version specified, but no ApiVersionStrategy configured
at org.springframework.util.Assert.state(Assert.java:80) ~[spring-core-7.0.1.jar:7.0.1]
at org.springframework.web.servlet.mvc.method.RequestMappingInfo$DefaultBuilder.build(RequestMappingInfo.java:773) ~[spring-webmvc-7.0.1.jar:7.0.1]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.createRequestMappingInfo(RequestMappingHandlerMapping.java:385) ~[spring-webmvc-7.0.1.jar:7.0.1]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.createRequestMappingInfo(RequestMappingHandlerMapping.java:289) ~[spring-webmvc-7.0.1.jar:7.0.1]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.getMappingForMethod(RequestMappingHandlerMapping.java:207) ~[spring-webmvc-7.0.1.jar:7.0.1]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.getMappingForMethod(RequestMappingHandlerMapping.java:80) ~[spring-webmvc-7.0.1.jar:7.0.1]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lambda$detectHandlerMethods$0(AbstractHandlerMethodMapping.java:279) ~[spring-webmvc-7.0.1.jar:7.0.1]
... 28 common frames omitted
1. Path Segment Versioning
Java class configuration
package com.bannalycode.springbootapiversion;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ApiVersionConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class APIVersionConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer.usePathSegment(1).addSupportedVersions("1.0", "2.0").setDefaultVersion("1.0");
}
}Properties configuration
spring.mvc.apiversion.default=1.0
spring.mvc.apiversion.supported=1.0,2.0
spring.mvc.apiversion.use.path-segment=1REST Controller Class
@RestController
@RequestMapping("/api")
public class APIVersionRestController {
@GetMapping( value = "/{version}/version", version = "1.0")
public String getVersionOne() {
return "version one";
}
@GetMapping(value = "/{version}/version", version = "2.0")
public String getVersionTwo() {
return "version two";
}
}2. Header Versioning
Java class configuration
@Configuration
public class APIVersionConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer.useRequestHeader("Server-API-Version").addSupportedVersions("1.0", "2.0").setDefaultVersion("1.0");
}
}
Properties configuration
spring.mvc.apiversion.default=1.0
spring.mvc.apiversion.supported=1.0,2.0
spring.mvc.apiversion.use.header=Server-API-VersionREST Controller Class
@RestController
@RequestMapping("/api")
public class APIVersionRestController {
@GetMapping( value = "/version", version = "1.0")
public String getVersionOne() {
return "version one";
}
@GetMapping(value = "/version", version = "2.0")
public String getVersionTwo() {
return "version two";
}
}3. Query Parameter Versioning
Java Configuration
@Configuration
public class APIVersionConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer.useQueryParam("version").addSupportedVersions("1.0", "2.0").setDefaultVersion("1.0");
}
}Properties Configuration
spring.mvc.apiversion.default=1.0
spring.mvc.apiversion.supported=1.0,2.0
spring.mvc.apiversion.use.query-parameter=version4. Media Type Versioning
Java Configuration
@Configuration
public class APIVersionConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer.useMediaTypeParameter(MediaType.APPLICATION_JSON, "version").addSupportedVersions("1.0", "2.0").setDefaultVersion("1.0");
}
}
Properties Configuration
spring.mvc.apiversion.default=1.0
spring.mvc.apiversion.supported=1.0,2.0
spring.mvc.apiversion.use.media-type-parameter[application/json]=version

0 Comments