Guía

De javax a jakarta con OpenRewrite: qué cubre y qué no

OpenRewrite automatiza el renombrado de paquetes de Jakarta EE. Lo importante no es lo que hace, que es previsible, sino la lista de lo que deja sin tocar.

Por qué no vale un buscar y reemplazar

Es lo primero que se intenta, y es lo que provoca los fallos más difíciles de localizar después.

No todos los paquetes que empiezan por javax pertenecen a Jakarta EE. javax.sql, javax.naming, javax.crypto y javax.net siguen en el JDK y no cambian de nombre. Un reemplazo global los rompe y el error aparece lejos del sitio donde se hizo el cambio.

Además el renombrado no ocurre solo en las importaciones: aparece en cadenas de texto de configuración, en descriptores XML, en nombres de propiedades y en ficheros de servicios. Un reemplazo sobre todo el proyecto toca cosas que no debía y deja sin tocar cosas que sí.

Las herramientas específicas acotan el cambio a los paquetes que de verdad cambiaron de dueño, y ese es todo su valor: no es que sean más rápidas, es que saben dónde parar.

Cómo se ejecuta la receta

  1. Partir de un árbol limpio

    La receta reescribe ficheros en sitio. Se ejecuta sobre un repositorio sin cambios pendientes, de forma que todo lo que aparezca después sea obra suya y se pueda revisar de un vistazo.

  2. Ejecutar primero en modo de solo lectura

    El objetivo rewrite:dryRun genera un parche con lo que haría, sin modificar nada. Es la forma de ver el alcance real antes de aceptarlo, y sirve para estimar.

  3. Aplicar la receta de migración

    rewrite:run con la receta de migración a Jakarta EE aplica el renombrado sobre el código, y también sobre los ficheros de propiedades y los descriptores que reconoce.

  4. Revisar el cambio como se revisa cualquier otro

    El resultado es un diff, no una caja negra. Conviene leerlo: es donde se detectan los ficheros que la receta ha tocado de más y los que no ha sabido interpretar.

  5. Compilar y ejecutar las pruebas

    Que la receta termine sin errores no significa que el proyecto compile. Las dependencias de terceros siguen siendo responsabilidad de quien migra, y ahí es donde aparece el trabajo real.

Qué cubre la receta y qué queda a mano

Esta es la parte útil de la guía: saber de antemano qué va a seguir roto cuando la herramienta termine.

Alcance de la migración automática por tipo de fichero
QuéLo cubreQué queda pendiente
Importaciones del código propioSíNada, es el caso para el que está hecha
Versiones de las dependenciasEn parteLas librerías sin variante jakarta hay que sustituirlas a mano
Descriptores XMLEn parteConviene comprobar versión y espacio de nombres uno por uno
Cadenas de texto en configuraciónSolo las que reconoceNombres de clase construidos por concatenación o leídos de un fichero
Clases cargadas por reflexiónNoHay que localizarlas y cambiarlas a mano
Artefactos de terceros ya compiladosNoO se actualizan, o se transforma el artefacto, o se aíslan tras una interfaz propia

La última fila es la que decide el calendario de la migración, y es lo que se mide en el inventario de dependencias antes de empezar.

Cómo se comprueba que está completa

Que compile no basta: los casos que quedan fuera del alcance de la receta compilan igual y fallan en ejecución.

  • Buscar en todo el proyecto referencias a los paquetes que sí cambiaron, incluidas las que estén dentro de cadenas de texto.
  • Revisar los descriptores XML uno a uno: versión y espacio de nombres tienen que cambiar juntos.
  • Comprobar que no conviven en el classpath la variante antigua y la nueva de una misma librería.
  • Arrancar la aplicación completa, no solo ejecutar las pruebas unitarias.
  • Ejercitar los flujos que cargan clases por nombre, que es donde la receta no llega.

El contexto completo de este cambio, con las versiones de Jakarta EE y qué servidor soporta cada una, está en la página sobre la migración a Jakarta EE.

Preguntas frecuentes

Preguntas sobre la migración automática

¿La receta puede dejar el proyecto sin compilar?

Sí, y es lo esperable si hay dependencias sin variante jakarta. La receta cambia el código propio; las librerías de terceros siguen pidiendo el espacio de nombres antiguo hasta que se actualizan.

¿Se puede aplicar módulo a módulo?

Se puede ejecutar por módulos, pero el artefacto que se despliega tiene que quedar entero en un mismo espacio de nombres. No existe un estado intermedio que funcione en el contenedor.

¿Y si una librería crítica no tiene versión jakarta?

Hay tres salidas: sustituirla, transformar el artefacto compilado con una herramienta de conversión, o aislar su uso tras una interfaz propia y posponer la decisión. Cuál conviene depende de cuánto código dependa de ella.

¿Sirve esto también para el salto de Spring Boot 2 a 3?

El renombrado es el mismo y la receta ayuda igual, pero el salto de Spring Boot arrastra además propiedades renombradas y cambios en la configuración de seguridad que no son parte de Jakarta EE.

JavaEvolve

¿Te has encontrado con esto en tu aplicación?

Si el caso concreto no encaja con lo que hay aquí, cuéntamelo y te digo por dónde lo abordaría.

Escríbeme