Migración Spring 6 a Spring 7: guía paso a paso [2026]

2026-06-03
Spring BootJavaSpring FrameworkBackendCloud Native

Migrar de Spring Framework 6 (Spring Boot 3) a Spring Framework 7 (Spring Boot 4) es significativamente menos traumático que el salto de Spring 5 a Spring 6. No hay cambio de namespace: si ya estás en jakarta.*, el principal esfuerzo está en eliminar APIs deprecated, actualizar Tomcat y revisar Spring Security. Esta guía cubre cada paso en el orden correcto, con ejemplos de código reales y un checklist para verificar que la migración es completa antes de desplegar en producción.

Por qué migrar a Spring 7 ahora {#por-que-migrar}

Spring Framework 6.2.x tiene soporte OSS hasta agosto de 2026. A partir de esa fecha no recibirás parches de seguridad ni correcciones de bugs en la rama 6.x. Además, Spring 7 trae beneficios concretos que justifican la inversión técnica:

  • @Retryable sin dependencias externas — Eliminas spring-retry del classpath y reduces el tamaño del artefacto.
  • Virtual Threads nativos — Con Java 21+, el executor de threads virtuales se activa por defecto. Las APIs con alta I/O (JDBC, HTTP) obtienen mayor concurrencia con el mismo código.
  • @HttpServiceClient — Los clientes HTTP declarativos de Spring 6 evolucionan con autoconfiguración automática en Boot 4.
  • JSpecify para null-safety — El compilador detecta NullPointerException en tiempo de compilación en los módulos del core.
  • Tomcat 11 — Servlet API 6.1, mejor rendimiento y soporte completo de Jakarta EE 10.

Fase 0: Preparación (no saltar este paso) {#preparacion}

Antes de cambiar una sola dependencia, completa esta fase. Es la que determina si la migración irá bien o muy mal.

Actualiza a Spring Boot 3.3.x o 3.4.x

Si estás en Spring Boot 3.0.x o 3.1.x, actualiza primero a la última versión de la rama 3.x. Spring 7 elimina definitivamente todo lo que Spring 6.x marcó como @Deprecated. Mejor ver esos warnings en producción con Spring 6 que descubrir incompatibilidades el día de la migración a Spring 7.

<!-- pom.xml — actualiza primero a la última 3.x -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.4.5</version>
</parent>

Activa warnings de deprecación en el compilador

<!-- maven-compiler-plugin en pom.xml -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <compilerArgs>
            <arg>-Xlint:deprecation</arg>
            <arg>-Xlint:unchecked</arg>
        </compilerArgs>
    </configuration>
</plugin>

Ejecuta mvn compile y corrige todos los warnings antes de continuar. Cada warning de deprecación es una API que Spring 7 va a eliminar.

Verifica la compatibilidad de tus librerías de terceros

Estas son las librerías más comunes con breaking changes al subir a Spring Boot 4:

LibreríaVersión con Boot 3Versión con Boot 4Qué cambia
Hibernate ORM6.x7.xNueva API de SPI, cambios en tipos JPA
Spring Security6.x7.xMétodos deprecated eliminados
Spring Data JPA3.x4.xAligned con Hibernate 7
Spring Batch5.x6.xJob repository schema actualizado
Flyway9.x10.xCallbacks y configuración renombrados
Liquibase4.x4.29+Compatible, sin breaking changes mayores

Consulta siempre la lista oficial de versiones de dependencias de Spring Boot 4.

Actualiza Tomcat externo (si no usas el embebido)

Si despliegas tu aplicación en un Tomcat externo (no el embebido de Spring Boot), debes actualizar a Tomcat 11 antes de migrar a Spring Boot 4. Tomcat 11 implementa Servlet API 6.1 con jakarta.*. Tomcat 10.1 (Spring Boot 3) usa Servlet API 5.0, también con jakarta.*, pero hay diferencias de API entre ambas versiones del estándar que Spring Boot 4 asume resueltas.

Fase 1: Actualizar la versión del parent {#fase-1-version}

Una vez completada la preparación, el primer cambio real es actualizar la versión de Spring Boot.

Maven

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>4.0.0</version>
    <relativePath/>
</parent>

<properties>
    <!-- Mínimo 17, recomendado 21 para Virtual Threads, óptimo 25 -->
    <java.version>21</java.version>
</properties>

Gradle (build.gradle.kts)

plugins {
    id("org.springframework.boot") version "4.0.0"
    id("io.spring.dependency-management") version "1.1.x"
    kotlin("jvm") version "2.1.x"
}

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

Automatizado con OpenRewrite

Si tienes un proyecto grande con múltiples módulos, OpenRewrite automatiza la mayor parte de la actualización:

mvn org.openrewrite.maven:rewrite-maven-plugin:run \
  -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:RELEASE \
  -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_4_0

OpenRewrite actualiza:

  • La versión del parent en todos los pom.xml del proyecto
  • Propiedades de application.properties que han cambiado de nombre
  • Imports obsoletos de clases eliminadas
  • Elimina spring-retry si solo lo usabas para @Retryable

Fase 2: Breaking changes de Spring Framework 7 {#fase-2-breaking-changes}

spring-retry ya no es necesario

@Retryable, @Recover y @EnableRetry son ahora parte del core de Spring Framework 7. Elimina la dependencia explícita para evitar conflictos de clases duplicadas:

<!-- ELIMINAR de pom.xml -->
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>
<!-- También elimina spring-aspects si lo usabas solo para retry -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
</dependency>

Si usabas RetryTemplate programático o políticas de retry complejas, revisa la nueva API antes de eliminar la dependencia. La mayor parte de la API pública es compatible, pero algunos constructores y métodos han cambiado.

Spring Security 7: eliminación de métodos deprecated

Spring Security 7 es el cambio que más tiempo consume en la mayoría de las migraciones. Elimina todos los métodos deprecados desde Security 5.x. Los cambios más frecuentes:

// ❌ Spring Security 6 — deprecated, eliminado en Security 7
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatchers("/public/**").permitAll()
            .anyRequest().authenticated();
    }
}

// ✅ Spring Security 7 — configuración funcional (igual que en Security 6.x moderno)
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .permitAll()
            );
        return http.build();
    }
}

Otros cambios comunes en Spring Security 7:

// ❌ Forma antigua de configurar CORS — eliminada en Security 7
http.cors().and()...

// ✅ Forma correcta en Security 7
http.cors(cors -> cors.configurationSource(corsConfigurationSource()))...

// ❌ Forma antigua de deshabilitar CSRF — eliminada
http.csrf().disable()...

// ✅ Security 7
http.csrf(csrf -> csrf.disable())...

Jakarta EE 10: cambios en APIs de Servlet y JPA

Si ya migraste a jakarta.* con Spring Boot 3, el impacto de Jakarta EE 10 es mínimo. Los cambios afectan principalmente a:

  • jakarta.servlet.Filter — El método init(FilterConfig) es ahora default (no abstracto). Si tenías implementaciones vacías de init() solo para satisfacer la interfaz, puedes eliminarlas.
  • jakarta.persistence — Hibernate 7 introduce cambios en el SPI interno. Las anotaciones JPA (@Entity, @Id, @Column) no cambian. El impacto es en código que usaba APIs internas de Hibernate, no la API pública de JPA.
  • jakarta.validation — Bean Validation 3.1 añade nuevas restricciones. Las restricciones existentes siguen funcionando igual.

Propiedades de application.properties renombradas

Spring Boot 4 renombra algunas propiedades que quedaron deprecadas en Boot 3.x. OpenRewrite las actualiza automáticamente, pero si no usas OpenRewrite, revisa:

Propiedad Boot 3.x (deprecated)Propiedad Boot 4.x
spring.mvc.pathmatch.use-suffix-patternEliminada (sufijos en paths ya no son soportados)
spring.security.oauth2.client.registration.*.redirect-uri-templateredirect-uri
management.server.ssl.*management.ssl.*
spring.datasource.hikari.connection-test-querySigue igual (HikariCP sin breaking changes)

La lista completa está en las Release Notes de Spring Boot 4.0.

Spring Data JPA 4 e Hibernate 7

Hibernate 7 (que acompaña a Spring Data JPA 4 en Boot 4) introduce cambios en el motor de mapeo interno. El impacto en código típico de aplicación es bajo, pero revisa si usas:

// Si usas SessionFactory directamente (no recomendado con Spring Data)
// Algunos métodos de la API de bajo nivel han cambiado en Hibernate 7
SessionFactory sf = entityManagerFactory.unwrap(SessionFactory.class);

// Las anotaciones JPA no cambian — esto sigue igual
@Entity
@Table(name = "pedidos")
public class Pedido {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "cliente_id")
    private Cliente cliente;
}

Spring Batch 6 (si lo usas)

Spring Batch 6 actualiza el esquema de la base de datos de metadatos del repositorio de jobs. Si no usas Spring Batch, ignora esta sección.

-- Necesitarás ejecutar el script de migración del esquema de Spring Batch
-- Disponible en: spring-batch-core/src/main/resources/org/springframework/batch/core/
-- Compara el esquema actual con el de Batch 6 y aplica los ALTER TABLE necesarios

Fase 3: Verificación post-migración {#fase-3-verificacion}

Compilación y tests

# Limpia el caché de Maven y recompila desde cero
mvn clean compile -Xlint:deprecation

# Verifica que no quedan warnings de deprecación
mvn compile 2>&1 | grep -c "deprecated"
# Objetivo: 0 warnings

# Ejecuta los tests unitarios
mvn test

# Ejecuta los tests de integración (incluyendo contexto Spring activo)
mvn verify

# Verifica el arranque completo de la aplicación
mvn spring-boot:run

Checklist antes del deploy en producción

PasoEstado
Actualizado a Spring Boot 3.4.x antes de empezar
Todos los warnings de deprecación resueltos en 3.4.x
Tomcat externo actualizado a 11 (si aplica)
Compatibilidad de librerías de terceros verificada
Versión del parent actualizada a 4.0.0 en todos los módulos
spring-retry eliminado del pom.xml (si aplica)
Spring Security refactorizado (sin métodos deprecated)
Tests unitarios pasando
Tests de integración pasando
Propiedades de application.properties actualizadas
Schema de Spring Batch migrado (si aplica)
Deploy en staging validado con tráfico de prueba
Monitorización activa en las primeras 24h post-deploy

Estrategia de migración para proyectos grandes {#proyectos-grandes}

Si tienes múltiples microservicios o un monolito grande, la migración en un solo sprint es arriesgada. Un enfoque más seguro:

Migración por módulo (recomendado)

  1. Empieza por los servicios sin dependencias críticas — Los microservicios de solo lectura, sin Spring Security complejo y con pocas dependencias de terceros son los candidatos perfectos para la primera migración a Boot 4.
  2. Usa feature flags — Despliega el microservicio migrado detrás de un flag. El tráfico principal sigue en la versión antigua hasta validar que Boot 4 se comporta igual.
  3. Migra Spring Security en un paso separado — Si tu aplicación tiene Spring Security complejo (OAuth2, múltiples cadenas de filtros), dedica un sprint solo a la migración de Security, pruébalo en staging con un paquete de tests de autenticación y autorización.
  4. Monolitos: usa el módulo Maven/Gradle para aislar los cambios. Migra un módulo interno a la vez, con tests de integración entre módulos ejecutándose en cada paso.

Preguntas frecuentes sobre la migración {#faq}

¿Puedo migrar directamente de Spring Boot 2 a Spring Boot 4?

No directamente. El salto de Spring Boot 2 a Spring Boot 4 implica dos migraciones críticas: primero el cambio de namespace javax.*jakarta.* (Spring Boot 3), y luego los breaking changes de APIs deprecated (Spring Boot 4). Haz la migración en dos fases: 2 → 3 primero, 3 → 4 después.

Migré a Boot 4 y mi aplicación lanza ClassNotFoundException: javax.servlet.Filter

Tienes una dependencia transitiva que no se ha actualizado a Jakarta EE. Usa mvn dependency:tree | grep javax.servlet para identificar qué librería tira de javax.servlet y actualiza esa librería a una versión compatible con Jakarta EE 9+. Si no existe versión compatible, busca una alternativa.

¿Virtual Threads se activan solos en Spring Boot 4?

Sí, si la JVM es Java 21+. Spring Boot 4 detecta automáticamente si la JVM soporta Virtual Threads y activa el executor virtual para el servidor web embebido (Tomcat 11). No necesitas ninguna configuración extra. Puedes verificarlo con el endpoint de Actuator /actuator/metrics/executor.pool.size — si el tamaño es 0, estás usando el executor de threads virtuales (no tiene pool fijo).


Relacionado: Novedades de Spring Framework 7 vs Spring 6 — qué aporta Spring 7 y por qué vale la pena migrar.

¿Gestionas múltiples microservicios Spring en producción y necesitas planificar la migración sin interrumpir el negocio? Cuéntame tu caso — diseño hojas de ruta de modernización con riesgo controlado.

¿Buscas un consultor IT para tu empresa? Conoce mis servicios de consultoría IT: arquitectura cloud, desarrollo fullstack y liderazgo técnico. ¿Empresa en Mallorca o Baleares? Consultor IT en Mallorca.

¿Listo para transformar tu stack tecnológico?

Hablemos sobre cómo llevar tus sistemas al siguiente nivel, optimizar el rendimiento y potenciar el talento de tu equipo.