Spring Boot 4.0: Novedades y Guía de Migración desde 3.x

Spring Boot 4.0 es la actualización más significativa desde el salto a Spring Boot 3.0. Requiere Spring Framework 7.0, Java 17 como mínimo (con soporte completo para Java 21+), e introduce cambios de ruptura importantes junto con nuevas capacidades que simplifican el desarrollo de APIs, la observabilidad y los tests. Esta guía cubre las novedades más relevantes y cómo migrar desde 3.x.

Requisitos previos

Spring Boot 4.0 eleva las versiones mínimas de todo el ecosistema:

DependenciaVersión mínima
Java17 (recomendado 21+)
Spring Framework7.0
Spring Security7.0
Jackson3.0
Hibernate7.1
Tomcat11.0
Gradle8.14+ / 9.x
// build.gradle.kts
plugins {
    id("org.springframework.boot") version "4.0.6"
    id("io.spring.dependency-management") version "1.1.7"
    kotlin("jvm") version "2.1.0"
    kotlin("plugin.spring") version "2.1.0"
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

HTTP Service Clients: REST sin código boilerplate

Una de las novedades más esperadas. Spring Boot 4.0 auto-configura implementaciones de interfaces anotadas con @HttpExchange, eliminando la necesidad de implementar manualmente los clientes REST.

// Define la interfaz — Spring genera la implementación
@HttpExchange("https://api.github.com")
public interface GitHubClient {

    @GetExchange("/users/{username}")
    GitHubUser getUser(@PathVariable String username);

    @GetExchange("/repos/{owner}/{repo}")
    GitHubRepo getRepo(@PathVariable String owner, @PathVariable String repo);
}

// Registra el cliente como bean
@Configuration
public class ClientConfig {

    @Bean
    public GitHubClient gitHubClient(RestClient.Builder builder) {
        var restClient = builder.baseUrl("https://api.github.com").build();
        var factory = HttpServiceProxyFactory.builderFor(RestClientAdapter.create(restClient)).build();
        return factory.createClient(GitHubClient.class);
    }
}

// Inyecta y usa directamente
@Service
public class GitHubService {

    private final GitHubClient client;

    public GitHubUser getUserInfo(String username) {
        return client.getUser(username); // Llamada HTTP gestionada automáticamente
    }
}

API Versioning integrado en Spring MVC y WebFlux

Spring Boot 4.0 añade auto-configuración para versionado de APIs sin librerías externas:

# application.yml
spring:
  mvc:
    apiversion:
      enabled: true
      default-version: "1"
      supported-versions: "1,2"
      header-name: "X-API-Version"          # por cabecera
      # param-name: "api-version"            # o por query param
      # media-type-prefix: "application/vnd.myapp.v"  # o por media type
@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping
    @ApiVersion("1")
    public List<UserV1Dto> getUsersV1() {
        return userService.findAllV1();
    }

    @GetMapping
    @ApiVersion("2")
    public List<UserV2Dto> getUsersV2() {
        return userService.findAllV2(); // Respuesta enriquecida en V2
    }
}

OpenTelemetry Starter: observabilidad sin configuración

Nuevo starter dedicado que auto-configura el SDK de OpenTelemetry y exporta métricas y trazas vía OTLP:

// build.gradle.kts
dependencies {
    implementation("org.springframework.boot:spring-boot-starter-opentelemetry")
}
# application.yml — basta con definir el endpoint
management:
  opentelemetry:
    resource-attributes:
      service.name: "mi-servicio"
      service.version: "4.0.6"
    otlp:
      endpoint: "http://otel-collector:4318"
      export:
        traces: true
        metrics: true
        logs: true

Ya no necesitas configurar manualmente el SDK de OpenTelemetry — Spring Boot lo gestiona junto con la integración de Micrometer.

Virtual Threads con JDK HttpClient

Spring Boot 4.0 aprovecha los Virtual Threads (Project Loom) en más lugares. El JDK HttpClient ahora los usa automáticamente cuando están habilitados:

spring:
  threads:
    virtual:
      enabled: true  # Activa Virtual Threads en toda la aplicación
// Este código síncrono ahora escala como reactivo
@Service
public class ExternalApiService {

    private final GitHubClient gitHubClient;

    // Cada llamada se ejecuta en un Virtual Thread — sin bloqueo del pool
    public List<GitHubUser> getTeamMembers(List<String> usernames) {
        return usernames.parallelStream()
            .map(gitHubClient::getUser)
            .toList();
    }
}

Cambios de ruptura importantes

Jackson 3.0

Jackson 3.0 elimina algunas APIs obsoletas. El soporte de Jackson 2 existe pero en modo deprecado:

// build.gradle.kts — Si dependes de APIs de Jackson 2, actualiza a Jackson 3
dependencies {
    // Jackson 3 viene incluido con Spring Boot 4.0
    // Si tienes dependencias directas de Jackson 2, actualízalas:
    implementation("com.fasterxml.jackson.core:jackson-databind:3.0.2")
}
// Jackson 3 cambia algunos imports — usa el migration tool
// Antes: com.fasterxml.jackson.databind.ObjectMapper
// Ahora: igual, pero verifica las APIs específicas que uses

Propiedades renombradas

Usa spring-boot-properties-migrator temporalmente para detectar propiedades obsoletas:

dependencies {
    runtimeOnly("org.springframework.boot:spring-boot-properties-migrator")
}

Las renombradas más comunes:

Propiedad antiguaPropiedad nueva
management.tracing.enabledmanagement.tracing.export.enabled
spring.dao.exceptiontranslation.enabledspring.persistence.exceptiontranslation.enabled
server.error.* (algunas)movidas a nivel raíz

Auto-configuraciones: API pública eliminada

Los miembros públicos de las clases de auto-configuración han sido eliminados. Si extendías o referenciabas directamente clases como DataSourceAutoConfiguration, debes refactorizar:

// ❌ Ya no compila en Spring Boot 4.0
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
DataSourceAutoConfiguration.SomeMember member = ...;

// ✅ Usa los beans configurados directamente
@Autowired
DataSource dataSource;

Testing mejorado: @MockitoBean y RestTestClient

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserControllerTest {

    @MockitoBean  // Reemplaza definitivamente @MockBean
    private UserService userService;

    @Autowired
    private RestTestClient restTestClient; // Nuevo en Spring Boot 4.0

    @Test
    void shouldReturnUser() {
        when(userService.findById(1L)).thenReturn(mockUser());

        restTestClient.get()
            .uri("/api/users/1")
            .exchange()
            .expectStatus().isOk()
            .expectBody(UserDto.class)
            .value(user -> assertThat(user.name()).isEqualTo("Test"));
    }
}

Control de logging por consola

Nueva propiedad para entornos donde solo quieres logging en fichero:

logging:
  console:
    enabled: false   # Desactiva la salida por consola — útil en producción
  file:
    name: /var/log/app.log

Checklist de migración desde 3.x

  1. Actualiza Java a 17 mínimo (21 recomendado)
  2. Añade spring-boot-properties-migrator y ejecuta la app — revisa los warnings
  3. Actualiza Jackson a 3.x si tienes dependencias directas
  4. Reemplaza @MockBean por @MockitoBean en todos los tests
  5. Revisa las auto-configuraciones que extiendas o referencien clases internas
  6. Migra a OpenTelemetry Starter si usas Zipkin/Jaeger manualmente
  7. Prueba en staging con el mismo tráfico que producción antes de migrar

Conclusión

Spring Boot 4.0 consolida la modernización del ecosistema Spring: menos boilerplate para clientes HTTP, versionado de APIs integrado, observabilidad con OpenTelemetry desde el primer día y Virtual Threads en más capas de la aplicación. La migración desde 3.x requiere atención a los cambios de ruptura, pero el properties-migrator y los mensajes de deprecación guían el proceso de forma clara.