Migrar AngularJS que vive dentro de Java y JSP
En muchos sistemas Java, AngularJS se entrega mediante páginas JSP y se empaqueta en el mismo WAR que el backend. Migrarlo exige separar antes tres cosas: las páginas, el build y la sesión.
El punto de partida
Una configuración común es así. Los controladores de Spring MVC devuelven vistas JSP. Un layout armado con Tiles, SiteMesh o includes de JSP renderiza el encabezado y las etiquetas script. Los archivos AngularJS están en la carpeta de la aplicación web, a veces minificados por un plugin de Maven y a veces incluidos uno por uno. Todo se empaqueta en un solo WAR y se despliega en un servidor de aplicaciones, con el calendario de publicaciones del backend.
El frontend depende entonces del servidor en tres capas. Cada una necesita su propio trabajo.
Capa 1: Las páginas
JSP mezcla lógica de servidor con el markup que AngularJS usa después:
- Tags que muestran u ocultan partes de la página según los roles del usuario.
- Tags de mensajes que insertan textos traducidos desde resource bundles.
- Atributos del modelo escritos en scripts inline como variables de JavaScript.
- El token CSRF renderizado en una etiqueta meta o en un campo oculto.
Angular moderno compila templates estáticos en el build, así que nada de esto puede quedarse en los templates.
Qué hacer
- Busca en los archivos JSP los tags y expresiones de servidor, y lista cada uso.
- Expón el usuario actual y sus permisos mediante un endpoint REST. El servidor sigue controlando el acceso en cada solicitud.
- Publica los resource bundles como JSON, por idioma, para que el cliente cargue sus traducciones.
- Reemplaza los datos inline del modelo por llamadas a controladores REST.
- Reduce cada JSP a una página delgada que solo cargue la aplicación. Al final, reemplázala por un
index.htmlestático.
Capa 2: El build
Las herramientas de Angular corren sobre Node. El backend se construye con Maven o Gradle. En algún punto tienen que encontrarse.
| Opción | Cómo funciona | Costo y beneficio |
|---|---|---|
| Build del frontend dentro de Maven o Gradle | Un plugin instala Node y ejecuta el build de Angular durante el build del backend. El resultado se copia al WAR o al JAR | Un solo artefacto y un solo pipeline. Los builds son más lentos, y las publicaciones de frontend y backend siguen atadas |
| Pipeline separado, mismo artefacto | CI construye primero el frontend y le pasa los archivos estáticos al build del backend | Feedback más rápido para cada lado. Sigue siendo una sola unidad de despliegue |
| Despliegue separado | Los archivos estáticos los sirve un servidor web o un CDN. Un reverse proxy envía las rutas del API a la aplicación Java | Publicaciones independientes. Requiere configurar el proxy y cuidar la compatibilidad del API entre versiones |
Empezar con la primera o la segunda opción mantiene la operación igual durante la migración. Pasar después a la tercera es directo cuando el frontend ya es un conjunto de archivos estáticos.
Dos detalles ahorran tiempo:
- Context path. Si la aplicación se despliega bajo una ruta como
/portal, configura la misma ruta base en el build de Angular. Si no, los scripts y las rutas fallan solo en el entorno desplegado. - Desarrollo local. Ejecuta el servidor de desarrollo de Angular con un proxy hacia el backend local. Las solicitudes se ven como del mismo origen y las cookies de sesión funcionan igual que en producción.
Capa 3: La sesión
Las aplicaciones web Java suelen mantener una sesión en el servidor, identificada por una cookie JSESSIONID. Una SPA servida desde el mismo origen envía esa cookie en cada solicitud, así que el login puede quedarse como está. El trabajo está en los bordes.
- Expiración de la sesión. Cuando la sesión expira, la capa de seguridad redirige a la página de login. Una llamada al API recibe entonces HTML con estado 200. Configura las rutas del API para que respondan 401, y deja que un único interceptor HTTP en el cliente lleve al usuario al login.
- CSRF. Reemplaza el token renderizado por JSP por el enfoque de cookie y header. Spring Security puede publicar el token en una cookie que el cliente HTTP de Angular lee y devuelve en un header. Revisa la documentación de tu versión de Spring Security, porque la configuración cambia entre versiones mayores.
- Estado guardado en la sesión. Busca pasos de asistentes, registros seleccionados o filtros guardados en la sesión HTTP. Las páginas antiguas dependían de ellos entre solicitudes. Decide para cada uno si pasa al cliente, si se convierte en un parámetro explícito del API o si se queda en el servidor detrás de un endpoint.
El estado de sesión guardado en el servidor es un acoplamiento oculto que causa muchas sorpresas. Una pantalla puede funcionar solo porque otra pantalla anterior dejó algo en la sesión. Rastrea estas dependencias antes de estimar las pantallas involucradas.
Después de la separación
Con las tres capas separadas, las pantallas se mueven de a una, como se describe en Cómo migrar de AngularJS a Angular sin downtime. El frontend queda como archivos estáticos que hablan con un API, y el lado Java se puede actualizar sin tocar las pantallas.
La misma estructura aplica a sistemas .NET, descrita en AngularJS con ASP.NET MVC. Para el mapeo de conceptos entre ambos frameworks, revisa la referencia de AngularJS a Angular.
Más en esta sección
- Cómo seguir entregando funcionalidades durante una migración
- Cómo medir el avance de una migración
- Después de la migración: mantener el frontend al día
- Costo de una migración de AngularJS: qué lo determina y cómo estimarlo
¿Planeas una migración o una plataforma de microfrontends?
En una llamada de 20 minutos me cuentas tu situación y te digo cómo la abordaría. Si todavía no vale la pena, también te lo digo.
Escríbeme por LinkedIn