Spring Boot 3.4: Todas las novedades explicadas
Spring Boot 3.4 trae logging estructurado nativo, virtual threads extendidos, graceful shutdown por defecto y MockMvcTester. Guía completa de las nuevas funcionalidades.

Spring Boot 3.4, lanzado en noviembre de 2024, aporta mejoras significativas en productividad y rendimiento de aplicaciones. Esta versión introduce logging estructurado nativo, habilita graceful shutdown por defecto y amplía el soporte de virtual threads en todo el framework.
Spring Boot 3.4 requiere Java 17 como mínimo y soporta Java 21 para virtual threads. Esta versión utiliza Spring Framework 6.2.
Logging estructurado nativo
El logging estructurado representa un avance importante para la observabilidad de aplicaciones. En lugar de logs basados en texto difíciles de analizar, Spring Boot 3.4 genera logs en formato JSON consumibles por herramientas como Elasticsearch, Grafana Loki o Datadog.
Tres formatos son soportados de forma nativa: Elastic Common Schema (ECS), Logstash y Graylog Extended Log Format (GELF).
# application.properties
# Enable structured logging in console
logging.structured.format.console=ecs
# Or for log files
logging.structured.format.file=logstashEsta simple configuración produce logs JSON estructurados de forma automática.
@RestController
@RequestMapping("/api/demo")
public class LoggingController {
// Logger injection via SLF4J
private static final Logger logger = LoggerFactory.getLogger(LoggingController.class);
@GetMapping("/action")
public ResponseEntity<String> performAction(@RequestParam String userId) {
// Log will be automatically formatted as structured JSON
logger.info("Action performed by user: {}", userId);
return ResponseEntity.ok("Action completed");
}
}Con el formato ECS habilitado, este log se convierte en un objeto JSON que contiene timestamp, nivel, mensaje, nombre de clase, hilo y metadatos de la aplicación. Esta estructura simplifica la búsqueda y agregación en plataformas de monitoreo.
Graceful Shutdown habilitado por defecto
Cambio importante: el graceful shutdown está ahora habilitado por defecto. Las peticiones HTTP en curso se procesan antes del cierre del servidor, evitando errores 502 durante los despliegues.
# application.properties
# Graceful shutdown is now ON by default
# To restore previous behavior (immediate shutdown):
server.shutdown=immediate
# Configure maximum wait timeout (30s default)
spring.lifecycle.timeout-per-shutdown-phase=45sEste comportamiento aplica a todos los servidores embebidos: Tomcat, Jetty, Undertow y Reactor Netty.
@Configuration
public class LifecycleConfig {
private static final Logger logger = LoggerFactory.getLogger(LifecycleConfig.class);
@Bean
public ApplicationListener<ContextClosedEvent> gracefulShutdownListener() {
// This listener executes at shutdown start
return event -> {
logger.info("Graceful shutdown initiated - completing in-flight requests");
// Custom logic: close connections, save state, etc.
};
}
}Esta mejora simplifica la implementación de despliegues sin tiempo de inactividad, sin necesidad de configuración adicional en la mayoría de los casos.
Soporte extendido de Virtual Threads
Spring Boot 3.4 extiende el soporte de virtual threads (Java 21+) a más componentes. OtlpMeterRegistry y el servidor Undertow ahora utilizan virtual threads cuando están habilitados.
# application.properties
# Enable virtual threads globally
spring.threads.virtual.enabled=trueEsta única propiedad transforma el modelo de hilos de la aplicación. Cada petición HTTP obtiene su propio virtual thread, permitiendo miles de conexiones concurrentes sin agotar el pool de hilos.
@Service
public class AsyncService {
private static final Logger logger = LoggerFactory.getLogger(AsyncService.class);
// With virtual threads enabled, each blocking call
// no longer consumes an OS thread
public String fetchExternalData() {
logger.info("Executing on thread: {}", Thread.currentThread());
// Blocking HTTP call - with virtual threads,
// the OS thread is released during I/O wait
return restClient.get()
.uri("https://api.external.com/data")
.retrieve()
.body(String.class);
}
}Los virtual threads destacan en aplicaciones con alta carga de I/O: llamadas HTTP, consultas a bases de datos, operaciones con archivos. El hilo del sistema operativo se libera durante el tiempo de espera y se reasigna al reanudar.
Los virtual threads requieren Java 21 como mínimo. En Java 17, esta propiedad se ignora y se aplica el comportamiento clásico.
RestClient y RestTemplate mejorados
Spring Boot 3.4 normaliza la configuración del cliente HTTP. La selección de HttpRequestFactory ahora sigue una precedencia clara basada en el classpath.
@Configuration
public class HttpClientConfig {
@Bean
public RestClient restClient(RestClient.Builder builder) {
// Spring Boot automatically chooses implementation:
// 1. Apache HTTP Components (if present)
// 2. Jetty Client
// 3. Reactor Netty
// 4. JDK HttpClient (Java 11+)
// 5. SimpleClientHttpRequestFactory (fallback)
return builder
.baseUrl("https://api.example.com")
.defaultHeader("Accept", "application/json")
.build();
}
}La configuración del comportamiento de redirecciones también se simplifica.
# application.properties
# Force specific implementation
spring.http.client.factory=jdk
# Configure redirect behavior
spring.http.client.redirects=dont-followPara un control más detallado, el nuevo ClientHttpRequestFactoryBuilder permite una configuración programática completa.
@Configuration
public class CustomHttpClientConfig {
@Bean
public RestClient customRestClient(ClientHttpRequestFactoryBuilder factoryBuilder) {
// Advanced factory configuration
ClientHttpRequestFactory factory = factoryBuilder
.httpComponents()
.connectTimeout(Duration.ofSeconds(5))
.readTimeout(Duration.ofSeconds(30))
.build();
return RestClient.builder()
.requestFactory(factory)
.baseUrl("https://api.example.com")
.build();
}
}Este enfoque ofrece máxima flexibilidad manteniendo una API consistente independientemente de la implementación HTTP subyacente.
¿Listo para aprobar tus entrevistas de Spring Boot?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
MockMvcTester para testing fluido
Spring Boot 3.4 introduce MockMvcTester, una alternativa basada en AssertJ a MockMvc. Este nuevo enfoque hace que los tests sean más legibles y expresivos.
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvcTester mockMvc; // New class!
@Test
void shouldReturnUserById() {
// Fluent API with AssertJ
mockMvc.get().uri("/api/users/{id}", 1)
.assertThat()
.hasStatusOk()
.hasContentType(MediaType.APPLICATION_JSON)
.bodyJson()
.extractingPath("$.name")
.isEqualTo("John Doe");
}
@Test
void shouldReturn404ForUnknownUser() {
mockMvc.get().uri("/api/users/{id}", 999)
.assertThat()
.hasStatus(HttpStatus.NOT_FOUND)
.bodyJson()
.extractingPath("$.error")
.isEqualTo("User not found");
}
}Comparado con el enfoque anterior usando MockMvc, las aserciones son más concisas y el encadenamiento resulta más natural.
@WebMvcTest(UserController.class)
class ComparisonTest {
@Autowired
private MockMvcTester mockMvcTester;
@Autowired
private MockMvc mockMvc;
@Test
void withMockMvcTester() {
// New approach: fluent and concise
mockMvcTester.post().uri("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"name\": \"Jane\"}")
.assertThat()
.hasStatus(HttpStatus.CREATED)
.hasHeader("Location", "/api/users/2");
}
@Test
void withClassicMockMvc() throws Exception {
// Old approach: more verbose
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"name\": \"Jane\"}"))
.andExpect(status().isCreated())
.andExpect(header().string("Location", "/api/users/2"));
}
}MockMvcTester se configura automáticamente cuando AssertJ está presente en el classpath (incluido por defecto con spring-boot-starter-test).
Docker Compose y Testcontainers mejorados
El soporte de Docker Compose gana flexibilidad con múltiples archivos de configuración y argumentos personalizados.
# application.properties
# Use multiple Docker Compose files
spring.docker.compose.file=compose.yaml,compose-dev.yaml
# Pass arguments at startup
spring.docker.compose.start.arguments=--scale redis=2
# Arguments at shutdown
spring.docker.compose.stop.arguments=--timeout 60Nuevos servicios se detectan y configuran automáticamente.
# compose.yaml
services:
postgres:
image: postgres:16
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
ports:
- "5432:5432"
redis-stack:
image: redis/redis-stack:latest
ports:
- "6379:6379"
- "8001:8001" # RedisInsight UI
grafana-lgtm:
image: grafana/otel-lgtm:latest
ports:
- "3000:3000" # Grafana
- "4317:4317" # OTLP gRPCSpring Boot 3.4 detecta automáticamente estos servicios y configura las propiedades de conexión correspondientes.
Para testing con Testcontainers, nuevos contenedores son soportados.
@TestConfiguration(proxyBeanMethods = false)
public class IntegrationTestConfig {
@Bean
@ServiceConnection
public PostgreSQLContainer<?> postgresContainer() {
return new PostgreSQLContainer<>("postgres:16");
}
@Bean
@ServiceConnection
public RedisStackContainer redisStackContainer() {
// New Redis Stack support
return new RedisStackContainer("redis/redis-stack:latest");
}
@Bean
@ServiceConnection
public LgtmStackContainer observabilityContainer() {
// New Grafana LGTM support (Loki, Grafana, Tempo, Mimir)
return new LgtmStackContainer("grafana/otel-lgtm:latest");
}
}La anotación @ServiceConnection configura automáticamente las propiedades de conexión, eliminando la necesidad de @DynamicPropertySource en la mayoría de los casos.
Actuator SSL y observabilidad
El nuevo endpoint /actuator/info ahora expone información sobre los certificados SSL configurados: fechas de validez, emisor y sujeto.
# application.properties
# Enable SSL information in actuator
management.info.ssl.enabled=true
# Configure warning threshold for expiring certificates
management.health.ssl.certificate-validity-warning-threshold=30dEsta funcionalidad permite monitorear la expiración de certificados directamente via actuator, facilitando la automatización de renovaciones.
@Configuration
public class SslMonitoringConfig {
@Bean
public HealthIndicator sslCertificateHealth(SslInfo sslInfo) {
return () -> {
// Custom certificate validity check
boolean allValid = sslInfo.getBundles().values().stream()
.flatMap(bundle -> bundle.getCertificates().stream())
.allMatch(cert -> cert.getValidityEnds().isAfter(Instant.now()));
return allValid
? Health.up().build()
: Health.down().withDetail("reason", "Certificate expiring soon").build();
};
}
}Para observabilidad, el transporte OTLP ahora soporta gRPC además de HTTP.
# application.properties
# Use gRPC for OTLP (traces and metrics)
management.otlp.tracing.transport=grpc
management.otlp.tracing.endpoint=http://localhost:4317
# New: group applications together
spring.application.group=payment-servicesEl grupo de aplicación (spring.application.group) permite agrupar lógicamente múltiples servicios en dashboards de observabilidad.
Imágenes OCI más ligeras
El builder de imágenes OCI por defecto cambia de paketobuildpacks/builder-jammy-base a paketobuildpacks/builder-jammy-java-tiny, produciendo imágenes significativamente más pequeñas.
tasks.named("bootBuildImage") {
// Native ARM support (new)
imagePlatform = "linux/arm64"
// New security flag
trustBuilder = false
// Image configuration
imageName = "myregistry.com/myapp:${version}"
}El nuevo parámetro imagePlatform simplifica las builds multiplataforma para ARM y x64.
<!-- pom.xml -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<!-- Native ARM support -->
<platform>linux/arm64</platform>
<!-- Builder optimized for minimal images -->
<builder>paketobuildpacks/builder-jammy-java-tiny</builder>
</image>
</configuration>
</plugin>Estas imágenes optimizadas arrancan más rápido y consumen menos recursos, especialmente beneficioso para despliegues en Kubernetes.
El cambio de builder puede afectar a aplicaciones que dependan de ciertas herramientas del sistema. Es recomendable probar las nuevas imágenes antes de desplegar en producción.
Cambios en Bean Validation
Spring Boot 3.4 alinea el comportamiento de validación con la especificación de Bean Validation. La validación ya no se propaga automáticamente a propiedades anidadas.
@ConfigurationProperties(prefix = "app")
@Validated
public class AppConfig {
@NotBlank
private String name;
// IMPORTANT: @Valid required to cascade validation
@Valid
private DatabaseConfig database;
// Without @Valid, ServerConfig constraints will NOT be checked
private ServerConfig server;
// Getters and setters
}
public class DatabaseConfig {
@NotBlank
private String url;
@Min(1)
private int poolSize;
// Getters and setters
}
public class ServerConfig {
@NotNull // This constraint will NOT be checked without @Valid on parent
private Integer port;
// Getters and setters
}Este cambio puede afectar aplicaciones existentes. Se recomienda auditar las clases @ConfigurationProperties y agregar @Valid donde la validación debe propagarse.
Deprecación de @MockBean y @SpyBean
Las anotaciones @MockBean y @SpyBean de Spring Boot están deprecadas en favor de las nuevas anotaciones de Mockito.
@SpringBootTest
class UserServiceTest {
// New: native Mockito annotations
@MockitoBean
private UserRepository userRepository;
@MockitoSpyBean
private EmailService emailService;
@Autowired
private UserService userService;
@Test
void shouldCreateUser() {
// Mock configuration
when(userRepository.save(any())).thenReturn(new User(1L, "test@example.com"));
userService.createUser("test@example.com");
// Spy verification
verify(emailService).sendWelcomeEmail("test@example.com");
}
}Las anotaciones antiguas siguen funcionando pero muestran advertencias de deprecación. Se recomienda planificar la migración a @MockitoBean y @MockitoSpyBean.
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Conclusión
Spring Boot 3.4 ofrece mejoras sustanciales en productividad y observabilidad:
Checklist de migración:
- Habilitar logging estructurado para mejorar la observabilidad
- Verificar el comportamiento de graceful shutdown (ahora habilitado por defecto)
- Considerar virtual threads para aplicaciones con alta carga de I/O (Java 21+)
- Migrar a MockMvcTester para tests más legibles
- Agregar
@Validen propiedades@ConfigurationPropertiesanidadas - Reemplazar
@MockBean/@SpyBeanpor@MockitoBean/@MockitoSpyBean - Probar las nuevas imágenes OCI antes del despliegue en producción
Spring Boot 3.4 consolida su posición como el framework de referencia para el desarrollo Java moderno, con especial atención a los estándares de observabilidad y rendimiento.
Fuentes:
Etiquetas
Compartir
Artículos relacionados

Preguntas de entrevista Node.js Backend: Guia completa 2026
Las 25 preguntas mas frecuentes en entrevistas de backend Node.js. Event loop, async/await, streams, clustering y rendimiento explicados con respuestas detalladas.

Go: Fundamentos para Desarrolladores Java/Python en 2026
Aprende Go rápidamente aprovechando tu experiencia en Java o Python. Goroutines, channels, interfaces y patrones esenciales para una transición fluida.

NestJS: Construir una API REST Completa
Tutorial completo para construir una API REST profesional con NestJS. Controladores, Servicios, Modulos, validacion con class-validator y manejo centralizado de errores.