Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este artículo se describen los conflictos de versiones de dependencia y cómo solucionarlos.
Las bibliotecas cliente de Azure para Java dependen de bibliotecas populares de terceros, como las siguientes:
Muchas aplicaciones y marcos de Java usan estas bibliotecas directamente o transitivamente, lo que conduce a conflictos de versiones. Los administradores de dependencias, como Maven y Gradle , resuelven todas las dependencias para que solo haya una sola versión de cada dependencia en la ruta de clase. Sin embargo, no se garantiza que la versión de dependencia resuelta sea compatible con todos los consumidores de esa dependencia en la aplicación. Para obtener más información, consulte Introducción al mecanismo de dependencia en la documentación de Maven y Descripción de la resolución de dependencias en la documentación de Gradle.
La incompatibilidad de las API de las dependencias directas resulta en errores de compilación. La incompatibilidad de dependencias en rombo suele dar lugar a errores en tiempo de ejecución como NoClassDefFoundError, NoSuchMethodError u otros de tipo LinkageError. No todas las bibliotecas siguen estrictamente la versión semántica, y a veces ocurren cambios importantes dentro de la misma versión principal.
Diagnóstico de problemas de coincidencia de versiones
En las secciones siguientes se describen métodos sobre cómo diagnosticar problemas de coincidencia de versiones.
Uso de la herramienta de compilación del SDK de Azure para Java
La herramienta de compilación del SDK de Azure para Java, que se introdujo en Introducción al SDK de Azure y Apache Maven, ayuda a identificar problemas comunes. Se recomienda agregar esta herramienta de compilación al proyecto y ejecutarla agregando el azure:run
destino de Maven al proceso de compilación normal. Con la configuración adecuada, puede identificar y resolver conflictos de dependencia de forma más proactiva, antes de que se conviertan en problemas en tiempo de ejecución.
Visualización de un árbol de dependencias
Ejecute mvn dependency:tree
o gradle dependencies --scan
y muestre el árbol de dependencias completo de su aplicación, con números de versión.
mvn dependency:tree -Dverbose
proporciona más información, pero puede ser engañosa. Para más información, consulte Árbol de dependencias de Apache Maven en la documentación de Maven. Para cada biblioteca sospechosa de que tiene un conflicto de versión, anote su número de versión y determine qué componentes dependen de ella.
La resolución de dependencias en entornos de desarrollo y producción puede funcionar de forma diferente. Los complementos apache Spark, Apache Flink, Databricks y IDE necesitan una configuración adicional para las dependencias personalizadas. También pueden traer sus propias versiones de las bibliotecas cliente de Azure o componentes comunes. Para obtener más información, consulte los artículos siguientes:
- Agrupación de las dependencias de la aplicación para Apache Spark
- Configuración del proyecto para Apache Flink
- Actualización correcta de una biblioteca de Maven en Databricks para Databricks
Para obtener más información sobre la resolución de conflictos en estos entornos, consulte la sección Creación de un archivo JAR fat más adelante en este artículo.
Configuración de Azure Functions
La versión de dependencia interna en Azure Functions (solo en ejecución de Java 8) tiene prioridad sobre una proporcionada por el usuario. Esta dependencia provoca conflictos de versión, especialmente con Jackson, Netty y Reactor.
Para resolver este problema, establezca la variable de FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBS
entorno en true
o 1
. Asegúrese de actualizar Las herramientas de funciones de Azure (v2 o v3) a la versión más reciente.
Nota:
Esta configuración solo se aplica a Azure Functions que ejecuta Java 8, las funciones que ejecutan Java 11 no necesitan una configuración especial.
Configurar Apache Spark
El SDK de Azure para Java admite varias versiones de Jackson, pero a veces pueden surgir problemas en función de las herramientas de compilación y su orden de resolución de dependencias. Un buen ejemplo de este problema es con Apache Spark, versión 3.0.0 y posteriores, que depende de Jackson 2.10. Aunque es compatible con el SDK de Azure para Java, los desarrolladores a menudo descubren que se usa una versión más reciente de Jackson en su lugar, lo que da lugar a incompatibilidades. Para mitigar este problema, debe anclar una versión específica de Jackson (una compatible con Spark). Para obtener más información, consulte la sección Compatibilidad con varias versiones de Jackson de este artículo.
Si usa versiones anteriores de Spark o si otra biblioteca que usa requiere una versión incluso anterior de Jackson que el SDK de Azure para Java no admite, siga leyendo este artículo para conocer los posibles pasos de mitigación.
Detección de la versión del entorno de ejecución de Jackson
En Azure Core 1.21.0, agregamos detección en tiempo de ejecución y mejores diagnósticos de la versión en tiempo de ejecución de Jackson.
Si ve LinkageError
(o cualquiera de sus subclases) relacionadas con la API de Jackson, compruebe el mensaje de la excepción para obtener información sobre la versión en tiempo de ejecución. Por ejemplo: com.azure.core.implementation.jackson.JacksonVersionMismatchError: com/fasterxml/jackson/databind/cfg/MapperBuilder Package versions: jackson-annotations=2.9.0, jackson-core=2.9.0, jackson-databind=2.9.0, jackson-dataformat-xml=2.9.0, jackson-datatype-jsr310=2.9.0, azure-core=1.19.0-beta.2
Busque registros de advertencias y errores de JacksonVersion
. Para más información, consulte Configuración del registro en el SDK de Azure para Java. Por ejemplo: [main] ERROR com.azure.core.implementation.jackson.JacksonVersion - Version '2.9.0' of package 'jackson-core' is not supported (too old), please upgrade.
Nota:
Compruebe que todos los paquetes de Jackson tienen la misma versión.
Para obtener la lista de paquetes usados por el SDK de Azure y las versiones compatibles de Jackson, consulte la sección Compatibilidad con varias versiones de Jackson .
Mitigar problemas de incompatibilidad de versiones
En las secciones siguientes se describe cómo mitigar los problemas de coincidencia de versiones.
Usar BOM del SDK de Azure
Use la versión estable más reciente de BOM de Azure SDK y no especifique las versiones de dependencias y Azure SDK en el archivo POM. Si procede, use BOM de Azure Spring Boot.
Las dependencias enumeradas en el BOM del SDK de Azure se prueban rigurosamente para evitar conflictos de dependencia.
Evitar dependencias innecesarias
Quite las dependencias si puede. A veces, una aplicación tiene dependencias en varias bibliotecas que proporcionan básicamente la misma funcionalidad. Estas dependencias innecesarias exponen las aplicaciones a vulnerabilidades de seguridad, conflictos de versión y costos de soporte técnico y mantenimiento.
Actualizar versiones de dependencia
Si cambiar a la boM más reciente del SDK de Azure no ayuda, identifique las bibliotecas que causan conflictos y los componentes que los usan. (Para obtener más información, consulte la sección Ver un árbol de dependencias anteriormente en este artículo). Intente actualizar a una versión más reciente, que protege contra vulnerabilidades de seguridad y, a menudo, aporta nuevas características, mejoras de rendimiento y correcciones de errores.
Evite degradar la versión del SDK de Azure porque puede exponer la aplicación a vulnerabilidades y problemas conocidos.
Bibliotecas de sombra
A veces, no hay ninguna combinación de bibliotecas que funcionen juntas y el uso de bibliotecas en la sombra es el último recurso.
Nota:
El uso de sombreado tiene inconvenientes significativos: aumenta el tamaño del paquete y el número de clases en el classpath, hace que la navegación del código y la depuración sean difíciles, no reubica el código JNI, dificulta la reflexión y puede infringir licencias de código, entre otras cuestiones. Solo se debe usar después de que se agoten otras opciones.
El sombreado permite incluir dependencias dentro de un archivo JAR en tiempo de compilación y, a continuación, cambiar el nombre de los paquetes y actualizar el código de la aplicación para usar el código en la ubicación sombreada. El conflicto de dependencias en rombo ya no es un problema, porque hay dos copias diferentes de una dependencia. Puede sombrear una biblioteca que tenga una dependencia transitiva conflictiva o una dependencia de aplicación directa, como se describe en la lista siguiente:
-
Conflicto de dependencia transitiva: por ejemplo, la biblioteca
A
de terceros requiere Jackson 2.9, que los SDK de Azure no admiten y no es posible actualizarA
. Cree un nuevo módulo, que incluyaA
y ponga en la sombra (reubicar) la versión 2.9 de Jackson y, opcionalmente, otras dependencias deA
. - Conflicto de dependencias de la aplicación: la aplicación usa Jackson 2.9 directamente. Mientras trabaja para actualizar el código, puede sombrear y reubicar Jackson 2.9 en un nuevo módulo con clases de Jackson reubicadas en su lugar.
Nota:
La creación de un archivo fat-JAR con clases de Jackson reubicadas no resuelve el conflicto de versiones de estos ejemplos: solo fuerza una única versión en la sombra de Jackson.
Creación de un archivo fat-JAR
Los entornos como Databricks o Apache Spark tienen administración de dependencias personalizada y proporcionan bibliotecas comunes como Jackson. Para evitar conflictos con las bibliotecas proporcionadas, es posible que desee compilar un archivo JAR fat que contenga todas las dependencias. Para más información, consulte Complemento de sombra de Apache Maven. En muchos casos, la reubicación de las clases de Jackson (com.fasterxml.jackson
) mitiga el problema. A veces, estos entornos también aportan su propia versión de las SDK de Azure, por lo que podría verse obligado a reubicar com.azure
el espacio de nombres para solucionar conflictos de versiones.
Descripción de las versiones de dependencia compatibles
Para obtener información sobre dependencias específicas de azure-core
y sus versiones, consulte azure-core en el Repositorio Central de Maven. En la tabla siguiente se muestran algunas consideraciones generales:
Dependencia | Versiones compatibles |
---|---|
Jackson | 2.10.0 y versiones secundarias más recientes son compatibles. Para obtener más información, consulte la sección Compatibilidad con varias versiones de Jackson . |
SLF4J | 1.7.* |
netty-tcnative-boringssl-static | 2.0.* |
netty-common | 4.1.* |
núcleo de reactor | 3.X.*: los números de versión principal y secundaria deben coincidir exactamente con aquellos de los que depende su versión de azure-core . Para más información, consulte la directiva sobre entrada en desuso del proyecto Reactor. |
Compatibilidad con varias versiones de Jackson
El SDK de Azure para Java admite el trabajo con una variedad de versiones de Jackson. La versión más baja admitida es Jackson 2.10.0. Las bibliotecas cliente del SDK de Azure para Java ajustan su configuración y el uso de Jackson en función de la versión que se detecte en tiempo de ejecución. Este ajuste permite una mayor compatibilidad con versiones anteriores del marco spring, Apache Spark y otros entornos comunes. Las aplicaciones pueden degradar las versiones de Jackson (a la versión 2.10.0 o posterior) sin interrumpir las bibliotecas cliente de Azure SDK para Java.
Nota:
El uso de versiones anteriores de Jackson puede exponer aplicaciones a vulnerabilidades y problemas conocidos. Para obtener más información, consulte la lista de vulnerabilidades conocidas para las bibliotecas de Jackson.
Al anclar una versión específica de Jackson, asegúrese de hacerlo para todos los módulos usados por Azure SDK, que se muestran en la lista siguiente:
jackson-annotations
jackson-core
jackson-databind
jackson-dataformat-xml
jackson-datatype-jsr310
Migración de Jackson a azure-json
Las bibliotecas cliente de Azure para Java están en proceso de migración a azure-json, que no depende de ningún componente de terceros y ofrece primitivos compartidos, abstracciones y asistentes para JSON.
Los entornos como Apache Spark, Apache Flink y Databricks pueden traer versiones anteriores de azure-core
que aún no dependen de azure-json
. Como resultado, cuando se usan versiones más recientes de bibliotecas de Azure en estos entornos, es posible que reciba errores similares a java.lang.NoClassDefFoundError: com/azure/json/JsonSerializable
. Para mitigar este error, agregue una dependencia explícita en azure-json
.
Pasos siguientes
Ahora que está familiarizado con los conflictos de versiones de dependencia y cómo solucionarlos, consulte Administración de dependencias para Java para obtener información sobre la mejor manera de evitarlos.