Guía
Cómo hacer el inventario de dependencias antes de migrar
El inventario es lo que convierte una migración de una apuesta en un plan. Estos son los comandos que lo producen y qué mirar en cada salida.
Qué responde un inventario y qué no
Un inventario responde tres preguntas: qué hay realmente en el classpath, qué de eso ha dejado de mantenerse, y qué va a romperse al cambiar de versión. No responde cuánto va a costar: eso sale después, cuando se cruza con lo que la aplicación necesita hacer.
La diferencia con leer el fichero de construcción es que ahí solo están las dependencias declaradas. Las que causan problemas suelen ser transitivas, es decir, dependencias de dependencias que nadie eligió y que aparecen en el classpath sin figurar en ninguna parte del proyecto.
Todo lo que sigue son comandos que se ejecutan sobre el proyecto tal y como está, sin modificar nada.
Los comandos y qué mirar en cada salida
El árbol completo de dependencias
mvn dependency:treeimprime el árbol resuelto, que es lo que de verdad acaba en el classpath. Interesa buscar la misma dependencia apareciendo dos veces con versiones distintas: eso es el origen de la mayoría de los NoSuchMethodError. Añadiendo-Dverbosese ven también las que fueron descartadas y por qué.Quién trae una dependencia concreta
Cuando ya se sabe qué librería molesta,
mvn dependency:tree -Dincludes=grupo:artefactorecorta el árbol a las ramas que llevan hasta ella. Es la forma rápida de saber a quién hay que excluir o actualizar.Qué versiones hay disponibles
mvn versions:display-dependency-updateslista, para cada dependencia, la versión actual y la última publicada. Lo importante no es el número, sino la fecha: una librería cuya última versión es de hace cinco años es una decisión pendiente, no una dependencia.Qué plugins se han quedado atrás
mvn versions:display-plugin-updateshace lo mismo con los plugins de construcción. Suelen ser lo último que alguien actualiza y lo primero que falla al cambiar de JDK, porque muchos dependen de detalles internos del compilador.Qué código usa APIs internas del JDK
jdeps --jdk-internals --multi-release 17 target/la-aplicacion.jaranaliza el bytecode y señala qué clases dependen de APIs internas. Es el comando que anticipa los InaccessibleObjectException antes de que aparezcan, y funciona igual sobre las dependencias que sobre el código propio.Qué hay declarado y no se usa
mvn dependency:analyzedistingue entre dependencias declaradas sin usar y usadas sin declarar. Las segundas son las peligrosas: funcionan por casualidad, porque otra dependencia las arrastra, y desaparecen el día que esa otra cambia de versión.
Qué significa cada hallazgo
La salida de los comandos anteriores se traduce en decisiones. Esta es la correspondencia.
| Lo que aparece | Qué significa | Qué se decide |
|---|---|---|
| La misma librería en dos versiones | El classpath resuelve una de las dos de forma impredecible | Fijar la versión en la gestión de dependencias del proyecto |
| Última publicación hace años | No habrá versión compatible con el JDK de destino | Sustituir, o aislar su uso tras una interfaz propia |
| Uso de APIs internas del JDK | Fallará en ejecución a partir de Java 16 | Actualizar la librería, y solo si no hay otra, abrir el módulo |
| Dependencia usada sin declarar | Funciona por arrastre y desaparecerá sin aviso | Declararla de forma explícita antes de tocar nada más |
| Plugin de construcción desactualizado | El build fallará antes que la aplicación | Actualizarlo primero, separado del resto del trabajo |
Con esta tabla rellenada ya se puede ordenar el trabajo por riesgo, que es lo que convierte el inventario en el plan por fases del servicio de modernización.
Lo que ningún comando va a decir
El inventario automático cubre el classpath. El resto hay que mirarlo a mano, y suele pesar más en el calendario.
- Qué versión de Java certifica el servidor de aplicaciones que hay en producción.
- Qué configuración vive fuera del repositorio y solo existe en el servidor.
- Qué sistemas consumen la aplicación y con qué contrato lo hacen.
- Qué partes del código no tienen pruebas que comprueben comportamiento.
- Qué reglas de negocio no están documentadas en ningún sitio salvo en el propio código.
Un inventario que solo cubre las dependencias da una falsa sensación de control: es la mitad más fácil del problema.
Preguntas frecuentes
Preguntas sobre el inventario
¿Sirve esto igual con Gradle?
El planteamiento es idéntico y los comandos cambian: el árbol se obtiene con la tarea de dependencias del propio Gradle, y jdeps funciona igual porque analiza bytecode, no ficheros de construcción.
¿Cuánto se tarda en hacer un inventario?
Los comandos son minutos. Interpretar la salida y cruzarla con lo que la aplicación necesita es el trabajo real, y depende del tamaño del árbol de dependencias más que del código propio.
¿Hace falta el inventario si la migración parece sencilla?
Es justo cuando parece sencilla cuando más conviene: una migración que se estima en dos semanas sin mirar el árbol de dependencias es una estimación sin base. El inventario cuesta poco y es lo que evita la sorpresa a mitad.
¿Se puede hacer sin acceso al código?
Parcialmente. Con el artefacto empaquetado se puede analizar el bytecode y ver las APIs internas, pero no se obtiene el árbol de dependencias resuelto ni se puede distinguir lo declarado de lo arrastrado.
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