Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este artigo descreve conflitos de versão de dependência e como solucioná-los.
As bibliotecas clientes do Azure para Java dependem de bibliotecas de terceiros populares, como as seguintes:
Muitas aplicações e frameworks Java utilizam estas bibliotecas de forma direta ou transitiva, o que leva a conflitos de versão. Os gerentes de dependência, como Maven e Gradle , resolvem todas as dependências para que haja apenas uma única versão de cada dependência no classpath. No entanto, não é garantido que a versão de dependência resolvida seja compatível com todos os consumidores dessa dependência em seu aplicativo. Para obter mais informações, consulte Introdução ao mecanismo de dependência na documentação do Maven e Noções básicas sobre resolução de dependência na documentação do Gradle.
A incompatibilidade da API de dependências diretas resulta em erros de compilação. A incompatibilidade das dependências Diamond geralmente resulta em falhas em tempo de execução, como NoClassDefFoundError, NoSuchMethodError ou outro LinkageError. Nem todas as bibliotecas seguem estritamente o controle de versão semântico, e as alterações de quebra às vezes acontecem dentro da mesma versão principal.
Diagnosticar problemas de incompatibilidade de versão
As seções a seguir descrevem métodos sobre como diagnosticar problemas de incompatibilidade de versão.
Use a ferramenta de compilação SDK do Azure para Java
A ferramenta SDK do Azure for Java build, introduzida em Comece com SDK do Azure e Apache Maven, ajuda a identificar problemas comuns. Adiciona esta ferramenta de build ao teu projeto e executa-a adicionando o azure:run alvo do Maven ao teu processo normal de build. Com a configuração apropriada, você pode identificar e resolver conflitos de dependência de forma mais proativa, antes que eles se tornem problemas em tempo de execução.
Ver uma árvore de dependência
Execute mvn dependency:tree ou gradle dependencies --scan para mostrar a árvore de dependência completa para seu aplicativo, com números de versão.
mvn dependency:tree -Dverbose Dá mais informações, mas pode ser enganador. Para obter mais informações, consulte Apache Maven Dependency Tree na documentação do Maven. Para cada biblioteca suspeita de ter um conflito de versão, anote seu número de versão e determine quais componentes dependem dela.
A resolução de dependências em ambientes de desenvolvimento e produção pode funcionar de forma diferente. Os plugins Apache Spark, Apache Flink, Databricks e IDE precisam de configuração extra para dependências personalizadas. Também podem trazer as suas próprias versões das bibliotecas do Azure Client ou componentes comuns. Para obter mais informações, consulte os seguintes artigos:
- Agrupando as dependências da sua aplicação para o Apache Spark
- Configuração do projeto para Apache Flink
- Como atualizar corretamente uma biblioteca Maven no Databricks for Databricks
Para obter mais informações sobre a resolução de conflitos nesses ambientes, veja a seção Criar um JAR completo mais adiante neste artigo.
Configurar Funções do Azure
A versão interna de dependência do Funções do Azure (apenas a correr Java 8) tem precedência sobre uma versão fornecida pelo utilizador. Essa dependência causa conflitos de versão, especialmente com Jackson, Netty e Reator.
Para resolver esse problema, defina a FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBS variável de ambiente como true ou 1. Certifique-se de atualizar as Ferramentas de Função do Azure (v2 ou v3) para a versão mais recente.
Observação
Esta configuração aplica-se apenas ao serviço Funções do Azure em execução com Java 8. As funções executadas em Java 11 não precisam de qualquer configuração especial.
Configurar Apache Spark
O SDK do Azure para Java suporta múltiplas versões do Jackson, mas por vezes podem surgir problemas dependendo das ferramentas de compilação e da sua ordem de resolução de dependências. Um bom exemplo deste problema é com o Apache Spark, versão 3.0.0 e posterior, que depende do Jackson 2.10. Embora seja compatível com o SDK do Azure para Java, os programadores frequentemente descobrem que é usada uma versão mais recente do Jackson, o que resulta em incompatibilidades. Para mitigar este problema, especifique uma versão específica do Jackson que seja compatível com o Spark. Para obter mais informações, consulte a seção Suporte para várias versões do Jackson neste artigo.
Se usa versões anteriores do Spark, ou se outra biblioteca que utiliza requer uma versão ainda mais antiga do Jackson que o SDK do Azure para Java não suporta, continue a ler este artigo para possíveis passos de mitigação.
Detetar a versão do tempo de execução de Jackson
No Azure Core 1.21.0, a biblioteca adiciona deteção em tempo de execução e melhores diagnósticos para a versão de runtime do Jackson.
Se vires LinkageError (ou qualquer uma das suas subclasses) relacionada à API Jackson, verifica a mensagem da exceção para obter informações sobre a versão de execução. Por exemplo: 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
Verifique logs de aviso e erro do JacksonVersion. Para mais informações, consulte Configure o registo no SDK do Azure para Java. Por exemplo: [main] ERROR com.azure.core.implementation.jackson.JacksonVersion - Version '2.9.0' of package 'jackson-core' is not supported (too old), please upgrade.
Observação
Verifique se todos os pacotes Jackson têm a mesma versão.
Para a lista de pacotes usados pela SDK do Azure e as versões Jackson suportadas, veja a secção Suporte para múltiplas versões Jackson.
Atenuar problemas de incompatibilidade de versão
As seções a seguir descrevem como mitigar problemas de incompatibilidade de versão.
Utilizar SDK do Azure BOM
Usa a versão estável mais recente SDK do Azure BOM e não especifiques versões de SDK do Azure e dependências no teu ficheiro POM. Quando aplicável, use o Azure Spring Boot BOM.
As dependências listadas no SDK do Azure BOM são rigorosamente testadas para evitar conflitos de dependências.
Evite dependências desnecessárias
Remova dependências, se puder. Às vezes, um aplicativo tem dependências em várias bibliotecas que fornecem essencialmente a mesma funcionalidade. Essas dependências desnecessárias expõem os aplicativos a vulnerabilidades de segurança, conflitos de versão e custos de suporte e manutenção.
Atualizar versões de dependência
Se mudar para o BOM mais recente do SDK do Azure não ajudar, identifique as bibliotecas que causam conflitos e os componentes que utilizam essas bibliotecas. (Para obter mais informações, consulte a seção Exibir uma árvore de dependência anteriormente neste artigo.) Tente atualizar para uma versão mais recente, que protege contra vulnerabilidades de segurança e geralmente traz novos recursos, melhorias de desempenho e correções de bugs.
Evite fazer downgrade da versão do SDK do Azure porque isso pode expor a sua aplicação a vulnerabilidades e problemas conhecidos.
Bibliotecas de sombreamento
Às vezes, não há nenhuma combinação de bibliotecas que trabalham juntas, e o sombreamento vem como último recurso.
Observação
O shading tem desvantagens significativas: aumenta o tamanho do pacote e o número de classes no classpath, dificulta a navegação e a depuração do código, não reloca o código JNI, compromete a reflexão e pode violar licenças de software, entre outras coisas. Usa-o apenas depois de esgotarem as outras opções.
O sombreamento permite incluir dependências em um JAR no momento da compilação, renomear pacotes e atualizar o código do aplicativo para usar o código no local sombreado. O conflito de dependência de diamantes não é mais um problema porque há duas cópias diferentes de uma dependência. Pode sombrear uma biblioteca que tenha uma dependência transitiva conflitante ou uma dependência direta de aplicação, conforme descrito na seguinte lista:
-
Conflito de dependências transitivas: Por exemplo, a biblioteca de terceiros
Arequer Jackson 2.9, que SDKs do Azure não suporta, e não é possível atualizarA. Crie um novo módulo, que incluiAe sombreia (realoca) Jackson 2.9 e, opcionalmente, outras dependências doA. - Conflito de dependência do aplicativo: seu aplicativo usa Jackson 2.9 diretamente. Enquanto está a trabalhar na atualização do código, pode ocultar e realocar o Jackson 2.9 num novo módulo com classes Jackson realocadas.
Observação
A criação de um JAR gordo com classes Jackson realocadas não resolve um conflito de versão nos exemplos - apenas impõe uma única versão sombreada do Jackson.
Crie um JAR gordo
Ambientes como Databricks ou Apache Spark têm gerenciamento de dependência personalizado e fornecem bibliotecas comuns como Jackson. Para evitar conflitos com as bibliotecas disponibilizadas, poderá querer criar um JAR com todas as dependências incluídas. Para obter mais informações, consulte Apache Maven Shade Plugin. Em muitos casos, a realocação de classes Jackson (com.fasterxml.jackson) atenua o problema. Por vezes, esses ambientes também trazem a sua própria versão dos SDKs do Azure, por isso pode ser necessário realocar com.azure o namespace para contornar conflitos de versões.
Compreender as versões de dependência compatíveis
Para obter informações sobre azure-coredependências específicas e suas versões, consulte azure-core no Maven Central Repository. A tabela a seguir mostra algumas considerações gerais:
| Dependência | Versões suportadas |
|---|---|
| Jackson | 2.10.0 e versões secundárias mais recentes são compatíveis. Para obter mais informações, consulte a seção Suporte para várias versões do Jackson . |
| SLF4J | 1.7.* |
| netty-tcnative-boringssl-static | 2.0.* |
| Netty Comum | 4.1.* |
| núcleo do reator | 3.X.* - Os números das versões principais e secundárias devem corresponder exatamente aos números da sua azure-core versão depende. Para obter mais informações, consulte a política do Project Reactor sobre desativações. |
Suporte para as várias versões de Jackson
O SDK do Azure para Java suporta trabalhar com várias versões do Jackson. A versão mais baixa suportada é Jackson 2.10.0. O SDK do Azure para bibliotecas cliente Java ajusta a sua configuração e o uso do Jackson consoante a versão detetada em tempo de execução. Esse ajuste permite maior compatibilidade com versões mais antigas da estrutura Spring, Apache Spark e outros ambientes comuns. As aplicações podem fazer downgrade das versões Jackson (para 2.10.0 ou superior) sem quebrar o SDK do Azure para bibliotecas clientes Java.
Observação
Usar versões antigas do Jackson pode expor as aplicações a vulnerabilidades e problemas conhecidos. Para obter mais informações, consulte a lista de vulnerabilidades conhecidas para bibliotecas Jackson.
Ao fixar uma versão específica do Jackson, certifique-se de o fazer para todos os módulos usados pelo SDK do Azure, que são mostrados na lista seguinte:
jackson-annotationsjackson-corejackson-databindjackson-dataformat-xmljackson-datatype-jsr310
Migração de Jackson para azure-json
As bibliotecas clientes do Azure para Java estão a migrar para o azure-json, que não depende de componentes de terceiros. Oferece primitivas partilhadas, abstrações e auxiliares para JSON.
Ambientes como Apache Spark, Apache Flink e Databricks podem trazer versões mais antigas do que ainda não dependem do azure-coreazure-json. Como resultado, ao usar versões mais recentes das bibliotecas do Azure nestes ambientes, pode obter erros semelhantes a java.lang.NoClassDefFoundError: com/azure/json/JsonSerializable. Adicione uma dependência explícita em azure-json para mitigar este erro.
Próximos passos
Agora que já está familiarizado com conflitos de versões de dependências e como os diagnosticar, consulte Dependency Management para Java para informações sobre a melhor forma de os evitar.