Diario
Secciones
Ajustes de lectura
Voz
Ninguna voz para este idioma en este navegador.
Más voces
Voz para el inglés
Código y términos técnicos en inglés
Desactivado: la voz de la página lo lee todo, sin pausa entre dos voces.
Ninguna voz para este idioma en este navegador.
Más voces
Más voces: Microsoft Edge ofrece voces naturales en línea, y Windows (Configuración › Hora e idioma › Voz), macOS y Android instalan otras.
Progreso
Sección titulada «Progreso»- Lección 1 — Spring Boot visto desde ASP.NET Core
- Lección 2 — Reactor:
MonoyFlux - Lección 3 — Reactor por dentro
- Lección 4 — WebFlux
- Lección 5 — Acceso reactivo a datos con R2DBC y Spring Data
- Lección 6 — Spring Cloud Gateway
- Lección 7 — Configuración centralizada con Spring Cloud Config
- Lección 8 — Descubrimiento de servicios y balanceo de carga del lado del cliente
- Lección 9 — Resiliencia con Resilience4j y Spring Cloud Circuit Breaker
- Lección 10 — Mensajería con Spring Cloud Stream
- Lección 11 — Observabilidad con Micrometer
- Lección 12 — Probar un conjunto de servicios Spring
2026-09-14 — Lecciones 1 a 4
Sección titulada «2026-09-14 — Lecciones 1 a 4»- Las versiones son las que start.spring.io ofrecía por defecto el 2026-09-14: Spring Boot 4.1.1, con Spring Framework 7.0.9, Reactor 3.8.7, Jackson 3, Tomcat 11 y Netty 4.2. El release train de Spring Cloud es 2025.1.3 “Oakwood”, que spring.io asocia con Spring Boot 4.0.x y 4.1.x. Su BOM sigue declarando
spring-boot.version4.0.8; el curso lo importa bajo el padre Boot 4.1.1, y nada en las lecciones 1 a 4 usa todavía Spring Cloud, así que será la lección 6 la que muestre si la combinación se sostiene. - El código es un proyecto Maven multimódulo en
code/spring-cloud-reactor: un módulomusiccompartido (notas, modos, escalas, tríadas) y un módulo por lección.check.shejecuta las pruebas, que comparan cada salida citada con un archivo deexpected/, ejecuta el JAR de la lección 1 con variables de entorno, y ejecuta los cuatro programas C# condotnet runsobre .NET 10. La CI lo ejecuta en Windows, Linux y macOS. - Todos los servidores HTTP de las pruebas arrancan en un puerto local libre, y la minimal API de C# escucha en el puerto 0 y se llama a sí misma. Sin Docker, sin servicios externos.
- Ninguno de los repositorios de GuitarAlchemist tiene código Spring o Reactor, así que estas lecciones aún no tienen caso práctico; el ejemplo conductor es un servicio de escalas escrito para el curso.
Sorpresas viniendo de ASP.NET Core:
- Spring Boot 4 renombró el starter web:
spring-boot-starter-webmvc, donde la mayoría de los ejemplos de la web dicenspring-boot-starter-web. La API de Initializr sigue queriendodependencies=web, y respondió awebmvccon un 400, “Unknown dependency ‘webmvc’”. - También nuevo en Spring Boot 4: el bean
WebClient.Buildernecesitaspring-boot-starter-webclient, yHealthIndicatory@AutoConfigureWebTestClientse movieron a paquetes nuevos. - Una dependencia que falta o que es ambigua detiene una aplicación Spring al arrancar con un informe que sugiere una solución, mientras que
IServiceCollectiontoma el último registro y descubre uno que falta en la primera resolución, salvo queValidateOnBuildesté activado. - Jackson escribe un
ProblemDetailen orden alfabético; ASP.NET Core empieza portypeytitle. UnProblemDetaildevuelto por un endpoint funcional conbodyValuesale comoapplication/jsoncon el título “Bad Request”; el mismo objeto desde un@ExceptionHandleresapplication/problem+jsonconinstance. - Spring escribe los server-sent events como
data:G, .NET 10 comodata: G. Ambos son válidos. Flux.log()sin SLF4J en el class path escribe en la consola con su propio formato, y unsubscribesin manejador de errores registraErrorCallbackNotImplementeden lugar de lanzar una excepción.Mono.fromCallable(...).block()en un hilo deparallel()no dispara la comprobación “block() is not supported” de Reactor:MonoCallableejecuta el callable directamente. BlockHound lo detectó.onBackpressureBuffer(3)no señala su desbordamiento en el momento en que ocurre: el error espera detrás de los valores del buffer, así que un suscriptor que ha pedido un valor no ve nada hasta que pide más.- Del lado .NET,
Channel.CreateBoundedconBoundedChannelFullMode.DropWritehace queTryWritedevuelvatruepara los elementos que descarta. - Una app C# basada en archivo con
#:sdk Microsoft.NET.Sdk.Webpublica con Native AOT por defecto:CreateSlimBuildery los tipos anónimos respondían entonces un 500 con advertencias IL2026 e IL3050, hasta#:property PublishAot=false. dotnet build file.cs -v quiet -nologofalló con MSB4025: las opciones antes o después de una app basada en archivo rompían la compilación con el SDK 10.0.112, ydotnet build file.csa secas funciona. Por verificar: si es intencionado.
Lo que hice mal al principio:
- La primera ejecución de CI falló en Linux y macOS: la prueba del log de arranque capturaba las líneas que Tomcat imprime al cerrarse el contexto, y otro hilo las imprime sin un orden fijo. La prueba ahora lee el log antes de cerrar el contexto.
- La segunda ejecución falló solo en macOS. El endpoint de progresiones usaba
Flux.interval, que falla conOverflowExceptioncuando Netty no ha pedido a tiempo el siguiente evento.delayElementsespera a la demanda; la lección 4 cuenta la historia. - Llamé
scaleRoutesa un método@Beande una clase llamadaScaleRoutes: mismo nombre de bean, y la aplicación se negó a arrancar conBeanDefinitionOverrideException. - La JVM de Surefire imprimía la advertencia de Mockito “A Java agent has been loaded dynamically”, aunque ninguna prueba simula nada: el starter de pruebas de Spring inicializa Mockito. Cargarlo con
-javaagent, como en la lección 11 del curso de Java, la eliminó. - Una prueba arrancada con
SpringApplicationregistraba elForkedBooterde Surefire como clase de la aplicación hastasetMainApplicationClass. - Mi primer borrador del ejercicio 2 de la lección 3 afirmaba que ocho búsquedas tardaban menos de 160 ms. Las aserciones de tiempo fallan en los runners de CI cargados; la prueba ahora cuenta las búsquedas que se ejecutan al mismo tiempo.
2026-09-21 — Lecciones 5 y 6
Sección titulada «2026-09-21 — Lecciones 5 y 6»- La lección 5 usa una base H2 en memoria mediante R2DBC. Dos pruebas de integración deterministas demuestran el flujo de señales de inserción y consulta y el rollback de una transacción, sin Docker ni una base externa.
- La lección 6 arranca Spring Cloud Gateway y un servidor Reactor Netty de origen en puertos loopback dinámicos. Dos pruebas de integración demuestran el enrutamiento, la eliminación del prefijo, la propagación de cabeceras y el reenvío, además del caso
404sin ruta. mvn -B -pl l05-r2dbc,l06-gateway -am testpasa con Java 25: cuatro pruebas, sin fallos ni errores. Spring Cloud 2025.1.3 soporta por tanto este escenario Gateway acotado bajo el padre Spring Boot 4.1.1; no es una afirmación general de compatibilidad.
Preguntas abiertas
Sección titulada «Preguntas abiertas»- El BOM de Spring Cloud 2025.1.3 declara Spring Boot 4.0.8. El escenario Gateway de la lección 6 pasa con Boot 4.1.1; la compatibilidad de los demás módulos queda por verificar.
- Rendimiento del mismo endpoint en Spring MVC con hilos virtuales y en WebFlux, medido en esta máquina: por verificar en la lección 11.
- Lo que ve el servidor cuando un suscriptor de
WebClientcancela un stream de server-sent events tras dos eventos: por verificar. - Los comandos de Initializr,
java -jarycurlde las lecciones 1 y 4 solo se ejecutaron en Windows; en Linux y macOS están por verificar, mientras que la CI ejecuta allí las pruebas equivalentes.