Entrevista Spring Boot: explica autoconfiguración, transacciones y pruebas con un caso práctico

Practica una entrevista Spring Boot con un pedido real: revisa autoconfiguración, proxy, rollback y pruebas HTTP que comprueban stock y pedidos al terminar.

Author: PracHub

Published: 10/11/2026

Entrevista Spring Boot: explica autoconfiguración, transacciones y pruebas con un caso práctico

October 11, 2026

Quick Overview

Boot3.5.16/Framework6.2.19/Temurin21.0.12.1/JDBC-H2 real10JUnitmethods46checks. SevenrandomloopbackHTTPcases/runtime-self-outer same409 differentstate; checkedcommitvsrollbackFor; swallowed201commit. ExplicitDataSourcebacksawayPooledDataSourceconfig, missingGatewaystartupfails/addbeanworks. NoJPA/concurrency/auth/durableexternalproof.

Backend EngineerFree

Para preparar una entrevista Spring Boot, sigue una petición desde el contexto de aplicación hasta el estado que queda en la base de datos. Explicar una anotación es solo el comienzo: necesitas comprobar qué bean existe, si la llamada cruza el proxy y qué excepción alcanza el límite transaccional. Las rutas runtime y self devuelven HTTP 409, pero solo la primera deja cero pedidos: el código de error no demuestra rollback.

Aquí puedes recorrer un pedido pequeño con JDBC y H2. El proyecto descargable fija Spring Boot 3.5.16, Spring Framework 6.2.19 y Java 21; ejecutamos diez métodos de prueba JUnit con 46 comprobaciones en Temurin 21.0.12.1. La guía general de entrevistas Spring Boot amplía después hacia seguridad y producción.

Límite de evidencia: los hechos oficiales llevan su referencia al aparecer; los resultados pertenecen a nuestro laboratorio y las recomendaciones son inferencias de preparación. No usamos informes de candidatos para afirmar rondas, preguntas frecuentes o cortes de contratación. Las preguntas publicadas de PracHub son material de práctica. H2 en memoria permite observar estas escrituras y sus transacciones; no valida dialectos, bloqueos concurrentes ni durabilidad tras reiniciar el proceso en producción.

Tres comprobaciones de Spring Boot: contexto, entrada al método y lectura del resultado después de la respuesta HTTP.

¿Qué aporta la autoconfiguración y qué no puede inventar?

Hecho oficial: la autoconfiguración de Boot 3.5 responde a las dependencias disponibles y permite que una configuración explícita sustituya determinados valores predeterminados. Tener un starter no significa que cualquier colaborador de negocio aparezca automáticamente.

El proyecto incluye los starters web y JDBC, H2 y las dependencias de prueba. En la aplicación completa observamos un HikariDataSource y un servicio gestionado mediante proxy. Esto demuestra ese conjunto concreto de dependencias y propiedades; no que todos los proyectos Boot deban elegir siempre el mismo pool.

Para aislar otra pregunta, creamos un contexto pequeño con ApplicationContextRunner: un bean NeedsGateway necesita una implementación de Gateway, pero no proporcionamos ninguna. El arranque falla y la causa final es NoSuchBeanDefinitionException. Al registrar explícitamente ese colaborador, el contexto arranca y contiene un NeedsGateway.

No arregles ese fallo añadiendo anotaciones al azar. Identifica el tipo requerido y quién debería registrarlo: un componente descubierto, un método @Bean, una importación o una configuración condicional. Nuestro Gateway es una interfaz inventada para la prueba; no representa un proveedor de pagos real ni una integración que Boot conozca.

Lee la condición que hizo retroceder un valor predeterminado

Otro contexto carga DataSourceAutoConfiguration junto a un bean propio llamado ownDataSource. La ejecución encuentra exactamente un DataSource, de clase DriverManagerDataSource. En este contexto aislado, el DataSource explícito ocupa el lugar de la alternativa automática; no quedan dos DataSource compitiendo.

El recibo guarda una condición negativa de PooledDataSourceConfiguration, dentro de DataSourceAutoConfiguration: @ConditionalOnMissingBean encontró ownDataSource. Esa evidencia explica por qué retrocede la alternativa, en lugar de limitarse a observar que el tipo final cambió.

Hecho oficial: la documentación de condiciones y pruebas de autoconfiguración describe condiciones sobre clases y beans, y el uso de ApplicationContextRunner para combinaciones concretas. Las condiciones dependen de las definiciones disponibles en su momento de evaluación; no son una elección aleatoria entre implementaciones.

En entrevista, separa «no se registró el bean que necesitaba» de «mi bean hizo retroceder uno automático». La primera situación impide resolver una dependencia; la segunda puede ser exactamente lo que querías. Consulta el informe de condiciones antes de excluir una autoconfiguración completa. --debug es una vía documentada para obtener ese informe al arrancar; en el laboratorio lo leemos directamente desde el contexto.

Las clases internas nombradas en el recibo sirven para explicar esta versión. No las conviertas en una API estable que tu aplicación deba importar para resolver el problema. La configuración explícita debe expresar la decisión funcional, no depender innecesariamente de la organización interna de Boot.

El informe también exige leer el nivel correcto. En el contexto con DataSource propio pueden aparecer condiciones positivas sobre la presencia de Hikari en el classpath. Eso no contradice el resultado: que exista una clase no significa que se haya creado su bean. La condición negativa que nos interesa pertenece a la configuración del pool y menciona el bean explícito encontrado. Compara la razón con el inventario final de beans.

Como ejercicio, predice qué dato pedirías si alguien solo te muestra «Hikari está instalado». Necesitarías saber si hay un DataSource registrado, qué configuración coincide y qué instancia termina inyectada. En nuestro recibo puedes comprobar esas tres piezas sin levantar un endpoint de diagnóstico público. No hace falta exponer información de configuración a usuarios externos para explicar el arranque en una entrevista.

Un pedido, dos escrituras y un fallo después de insertar

El estado inicial de cada caso es un SKU S con una unidad y ninguna fila en orders. El servicio realiza dos operaciones mediante JdbcTemplate: reduce el stock si todavía es positivo e inserta el pedido. Después provoca el fallo indicado por la ruta. Los tests restablecen las tablas antes de cada caso, de modo que las filas de una variante no contaminan la siguiente.

Este fragmento pertenece al servicio completo del paquete:

@Transactional
public void runtimeFailure() {
    write();
    throw new IllegalStateException("after insert");
}

public void selfCall() {
    runtimeFailure();
}

@Transactional
public void outerCall() {
    runtimeFailure();
}

La reducción de stock utiliza WHERE quantity > 0 y comprueba que se modificó una fila. Sin embargo, aquí no ejecutamos solicitudes concurrentes ni probamos un nivel de aislamiento de producción. El objetivo del caso es observar la frontera de la transacción, no certificar una solución completa de inventario.

El constructor de OrderController recibe OrderService; las rutas externas usan esa referencia gestionada, no una instancia creada con new. Cuando recibe IllegalStateException, devuelve 409; cuando recibe la excepción checked del ejercicio, devuelve 500. Estos códigos son decisiones simplificadas del laboratorio. Spring no impone esa correspondencia y un contrato real debería distinguir fallos de negocio, validación e infraestructura.

¿Por qué la autollamada cambia el resultado?

Hecho oficial: en el modo proxy descrito por @Transactional en Spring Framework 6.2, la interceptación depende de entrar desde fuera a través del proxy. Una llamada interna no obtiene por sí sola una nueva interceptación por llevar una anotación.

La ruta externa a runtimeFailure registra una transacción activa dentro de write. Después del fallo y de recibir HTTP 409, otra consulta ve stock 1 y cero pedidos. Las dos escrituras se revirtieron.

La ruta a selfCall también devuelve 409. Pero selfCall no tiene transacción exterior y llama directamente al método del mismo objeto. En write registramos transacción inactiva; después observamos stock 0 y un pedido. El controlador capturó una excepción cuando las escrituras ya habían quedado fuera de esa transacción inexistente.

Ahora cambia solo la entrada: el controlador llama a outerCall mediante el proxy. El método exterior está anotado, así que write registra transacción activa aunque la llamada interior siga sin interceptarse nuevamente. Al propagarse la excepción hasta el límite exterior, el resultado vuelve a ser stock 1 y cero pedidos.

Por eso «la autollamada nunca tiene transacción» es una explicación incompleta. Pregunta primero si ya existe una transacción en la ejecución actual. Para una reparación, considera mover la operación a otro bean o establecer una frontera explícita que coincida con la unidad de trabajo. La elección debe preservar qué escrituras necesitas confirmar juntas.

Tres respuestas HTTP 409 con distintos caminos: entrada externa, autollamada sin transacción y autollamada dentro de una transacción exterior.

La clase de excepción y el lugar donde se captura importan

Hecho oficial: las reglas de rollback de Framework 6.2 distinguen el comportamiento predeterminado para excepciones unchecked y checked, y permiten configurar reglas como rollbackFor. Esa política puede cambiar con la configuración; aquí usamos la predeterminada salvo donde lo indicamos.

El método checkedFailure está anotado, escribe y lanza Exception. La transacción está activa, pero el estado final es stock 0 y un pedido, aunque HTTP sea 500. En checkedRollback, la anotación incluye rollbackFor = Exception.class; con la misma clase de fallo observamos stock 1 y cero pedidos.

La variante swallowedFailure escribe y captura su propia IllegalStateException dentro del método transaccional. El método termina normalmente; en este caso el controlador responde 201 y queda un pedido. No lo confundas con un fallo de JDBC que haya marcado la transacción como rollback-only: esa situación no está representada por nuestra excepción de aplicación capturada.

Ruta del laboratorioHTTPTransacción en writeStock final / pedidos
runtime409activa1 / 0
self409inactiva0 / 1
outer409activa1 / 0
checked500activa0 / 1
checked-rollback500activa1 / 0
swallowed201activa0 / 1
success201activa0 / 1

Antes de añadir un catch, identifica qué excepción debe llegar al límite transaccional. Define qué fallos deben abortar la unidad de trabajo, quién traduce esos fallos a HTTP y qué puede confirmar el llamador. Capturar fuera del proxy permite que la infraestructura vea primero la excepción; capturar dentro puede impedirlo, como en esta variante concreta.

Elige una prueba que atraviese el límite que quieres explicar

Hecho oficial: la referencia de pruebas Boot 3.5 diferencia el contexto simulado del entorno con servidor real y advierte sobre transacciones que ocurren en hilos distintos al usar un servidor. Anotar el test no garantiza revertir lo que hizo la petición HTTP en otro hilo.

Nuestro test utiliza @SpringBootTest(classes = App.class, webEnvironment = RANDOM_PORT). Arranca el servidor en loopback y envía solicitudes con TestRestTemplate. Después de recibir cada respuesta, consulta stock y pedidos mediante JDBC. El método de prueba no lleva @Transactional; además, una comprobación confirma que su hilo no tiene una transacción ambiente.

Esa combinación distingue tres observaciones: la clase inyectada es un proxy AOP real, el servicio registra si hay transacción activa y el estado posterior coincide o no con un rollback. Un mock que solo verifique «se llamó a insert» no demuestra que la fila haya quedado confirmada o revertida después del fallo.

Para lógica pura, recomendamos empezar con una prueba pequeña sin contexto. Para serialización o validación web aislada, elige una prueba de esa capa. Para reglas de consulta, migraciones, dialecto o bloqueos, añade una base compatible con producción y las condiciones que realmente importan. Esas ampliaciones son recomendaciones: nuestro paquete ejecuta JDBC con H2, no JPA, Testcontainers ni pruebas de seguridad.

También conviene mantener independientes los contextos de diagnóstico. La prueba del Gateway ausente no pretende arrancar un servidor: registra únicamente la configuración que requiere ese colaborador. La prueba HTTP, en cambio, nombra explícitamente App.class como aplicación. Si cargas por accidente una configuración auxiliar como aplicación principal, un fallo del servidor puede ocultar la dependencia que intentabas estudiar. Eso cambia la hipótesis examinada.

Finalmente, no midas el éxito de la reparación por el estado de una ejecución anterior. Cada variante comienza otra vez con stock uno y tabla de pedidos vacía. Así podemos atribuir el pedido conservado a esa petición concreta. El reinicio del fixture facilita comparar resultados, pero no reproduce recuperación tras caída de proceso ni confirma persistencia fuera de H2 en memoria. Mantén esa diferencia en tu explicación.

El proyecto incluye los siete resultados HTTP, el informe de condiciones y las 46 comparaciones observadas. Ejecuta mvn test dentro de la carpeta extraída con Java 21 y Maven. Reserva tiempo para que Maven descargue las dependencias antes del ensayo. El paquete contiene código y recibos, sin binarios ni credenciales.

Practica una explicación que termine en evidencia

Estas preguntas publicadas permiten ampliar la preparación sin convertir la guía en un inventario de anotaciones. Abre el enunciado completo y conserva su alcance: algunas incluyen Java, seguridad o Thymeleaf, temas que el laboratorio no ha probado.

Pregunta de PracHubQué conectar con el pedido
Assess Spring IoC, AOP, JDBC, SecuritySeparar gestión de beans, proxy, acceso JDBC y seguridad.
Explain core Java and Spring fundamentalsExplicar qué aporta el lenguaje y qué necesita infraestructura Spring.
Answer Spring Boot and Thymeleaf engineering questionsDistinguir configuración del backend y representación de la vista.
Explain Spring Dependency Injection and Choose an Injection StyleHacer explícitas las dependencias requeridas por constructor.
Review a Spring REST Controller for Correctness and Per-Request WasteRevisar responsabilidad del controlador y recursos usados por petición.

Empieza por Review a Spring REST Controller for Correctness and Per-Request Waste. Explica después por qué runtime y self responden 409, pero conservan distinto stock. Añade qué cambia al introducir outer y dónde pondrías una prueba de regresión. Si tu argumento solo menciona la anotación o el código HTTP, vuelve a la consulta que muestra los pedidos realmente conservados.

Sources and Further Reading


Comments (0)