Alejandría

Busca en Alejandría

Lenguajes y marcos

Spring Boot

Framework Java para crear servicios listos para producción con configuración por convención.

01

En pocas palabras

Proyecto del ecosistema Spring que ofrece autoconfiguración, starters de dependencias, servidor embebido y funciones operativas (Actuator, métricas, health checks) para construir aplicaciones Java y Kotlin.

Qué problema resuelve

Configuración extensa y repetitiva para arrancar un servicio Java con web, datos, seguridad y observabilidad.

Cuándo utilizarlo

Servicios backend en la JVM, APIs REST, consumidores de eventos y jobs. Ejemplo: la API de solicitudes que integra PostgreSQL, Kafka y un buró de crédito.

02

De la idea a la práctica

Funcionamiento, ejemplos y decisiones para pasar al siguiente nivel.

Piezas principales

Pieza Qué aporta
Starters Conjuntos coherentes de dependencias (spring-boot-starter-web, -data-jpa)
Autoconfiguración Beans creados según lo que hay en el classpath y la configuración
Configuración externa application.yml, variables de entorno y perfiles, con @ConfigurationProperties tipadas
Actuator Health, métricas (Micrometer), info, sondas de Kubernetes
Testing @SpringBootTest, slices (@WebMvcTest, @DataJpaTest) y Testcontainers

Configuración tipada

@ConfigurationProperties(prefix = "buro")
public record BuroProperties(URI baseUrl, Duration timeout, int maxConcurrentes) {}
buro:
  base-url: https://api.buro.example.com
  timeout: 3s
  max-concurrentes: 20

management:
  endpoints.web.exposure.include: health,info,prometheus
  endpoint.health.probes.enabled: true

Cada propiedad se puede sobrescribir con una variable de entorno (BURO_TIMEOUT=5s), lo que encaja con contenedores y Cloud Run.

Hilos virtuales

Con Java 21 o superior, spring.threads.virtual.enabled=true hace que el servidor web y los ejecutores usen hilos virtuales. Para servicios con mucha E/S bloqueante (JDBC, HTTP a terceros) permite alta concurrencia sin adoptar programación reactiva. Vigila los límites de las dependencias: miles de hilos virtuales pueden agotar un pool de 10 conexiones si no hay un bulkhead.

Pruebas con Testcontainers

@SpringBootTest
@Testcontainers
class SolicitudRepositoryTest {

    @Container
    @ServiceConnection
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:17");

    @Autowired SolicitudRepository repo;

    @Test
    void guardaYRecupera() { /* … */ }
}

@ServiceConnection configura el datasource automáticamente a partir del contenedor, sin propiedades manuales.

Arranque y memoria en serverless

Opción Efecto
Lazy initialization Arranque más rápido, errores de configuración más tardíos
CDS / AOT cache (JDK) Reduce el tiempo de arranque reutilizando clases precargadas
GraalVM native image Arranque en milisegundos y menos memoria; build más lento y restricciones de reflexión
-XX:MaxRAMPercentage=75 Ajusta el heap al límite del contenedor

API protegida con JWT

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: https://idp.krediya.example/realms/krediya
@Configuration
class Seguridad {
    @Bean
    SecurityFilterChain api(HttpSecurity http) throws Exception {
        return http
            .authorizeHttpRequests(a -> a
                .requestMatchers("/actuator/health/**").permitAll()
                .requestMatchers(HttpMethod.POST, "/v1/solicitudes/*/aprobar").hasAuthority("SCOPE_creditos:aprobar")
                .anyRequest().authenticated())
            .oauth2ResourceServer(o -> o.jwt(Customizer.withDefaults()))
            .build();
    }
}

Las autorizaciones por recurso («este asesor solo ve su sucursal») van además en el servicio de aplicación o con @PreAuthorize, no solo en la configuración de rutas.

Errores con Problem Details (RFC 9457)

@RestControllerAdvice
class Errores extends ResponseEntityExceptionHandler {
    @ExceptionHandler(ReglaDeNegocioVioladaException.class)
    ProblemDetail regla(ReglaDeNegocioVioladaException e) {
        var p = ProblemDetail.forStatusAndDetail(HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
        p.setType(URI.create("https://api.krediya.example/errores/regla-negocio"));
        p.setProperty("codigo", e.codigo());
        return p;
    }
}

Un formato de error estándar facilita a los clientes y a la observabilidad tratar todos los servicios igual.

Observabilidad y apagado ordenado

server:
  shutdown: graceful # termina las peticiones en curso al recibir SIGTERM
spring:
  lifecycle:
    timeout-per-shutdown-phase: 20s
management:
  tracing:
    sampling:
      probability: 0.2
  otlp:
    tracing:
      endpoint: http://otel-collector:4318/v1/traces
  observations:
    key-values:
      servicio: api-solicitudes
logging:
  structured:
    format:
      console: ecs # logs JSON estructurados

Micrometer genera métricas y trazas (con exportación OTLP) para peticiones HTTP, JDBC, clientes HTTP y Kafka sin código adicional.

Imagen de contenedor

./mvnw spring-boot:build-image -Dspring-boot.build-image.imageName=us-east1-docker.pkg.dev/krediya/apps/api:1.9.0

Los Cloud Native Buildpacks generan una imagen con JRE ajustado, usuario no root y capas separadas (dependencias, código), sin escribir un Dockerfile. Si se prefiere un Dockerfile, usa el layered jar (java -Djarmode=tools -jar app.jar extract --layers) para aprovechar la caché de capas.

Mantener la versión al día

Cada versión menor de Spring Boot tiene un periodo de soporte open source limitado; planifica al menos una actualización menor al año. El orden recomendado: subir a la última patch de la versión actual, resolver avisos de deprecación, y luego saltar de versión con ayuda de OpenRewrite y de las notas de migración oficiales.

Criterios de implementación

Genera proyectos desde Spring Initializr con una plantilla corporativa (starters internos para logging, seguridad y trazas). Expón solo los endpoints de Actuator necesarios y protégelos. Organiza el código por bounded context, protege la estructura con fitness functions (ArchUnit) y añade Resilience4j en las integraciones externas.

Continúa en las fuentes

Documentación oficial para verificar detalles y explorar más.