Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo descreve conflitos de versão de dependência e como solucioná-los.
As bibliotecas de clientes do Azure para Java dependem de bibliotecas de terceiros populares, como as seguintes:
Muitos aplicativos e estruturas Java usam essas 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 entendimento da 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 de dependência de losango geralmente resulta em falhas de runtime, como NoClassDefFoundError, NoSuchMethodError ou outros LinkageError. Nem todas as bibliotecas seguem estritamente o versionamento semântico, e alterações interruptivas às vezes ocorrem na 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.
Usar a ferramenta de build do SDK do Azure para Java
A ferramenta de build do SDK do Azure para Java, introduzida no Get started com o SDK do Azure e o Apache Maven, ajuda a identificar problemas comumente encontrados. Recomendamos que você adicione essa ferramenta de build ao seu projeto e execute-a adicionando o destino maven azure:run
ao seu processo de build regular. Com a configuração apropriada, você pode identificar e resolver conflitos de dependência de forma mais proativa, antes que eles se tornem problemas no runtime.
Exibir uma árvore de dependência
Execute mvn dependency:tree
ou gradle dependencies --scan
para mostrar a árvore completa de dependências da sua aplicação, com números de versões.
mvn dependency:tree -Dverbose
fornece mais informações, mas pode ser enganoso. Para obter mais informações, consulte a Árvore de Dependência do Apache Maven na documentação do Maven. Para cada biblioteca que você suspeita ter um conflito de versão, anote seu número de versão e determine quais componentes dependem dela.
A resolução de dependência em ambientes de desenvolvimento e produção pode funcionar de forma diferente. Os plug-ins Apache Spark, Apache Flink, Databricks e IDE precisam de configuração extra para dependências personalizadas. Eles também podem trazer suas próprias versões de bibliotecas do Cliente do Azure ou componentes comuns. Para obter mais informações, consulte os seguintes artigos:
- Agrupando as dependências da sua aplicação no Apache Spark
- Configuração do projeto para Apache Flink
- Como atualizar corretamente uma biblioteca Maven no Databricks para Databricks
Para obter mais informações sobre a resolução de conflitos nesses ambientes, consulte a seção Criar um JAR do fat mais adiante neste artigo.
Configurar o Azure Functions
A versão de dependência interna no Azure Functions (executando somente Java 8) tem precedência sobre uma fornecida pelo usuário. Essa dependência causa conflitos de versão, especialmente com Jackson, Netty e Reactor.
Para resolver esse problema, defina a variável de FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBS
ambiente como true
ou 1
. Atualize as Ferramentas de Funções do Azure (v2 ou v3) para a versão mais recente.
Observação
Essa configuração se aplica apenas ao Azure Functions executando o Java 8, as funções que executam o Java 11 não precisam de configuração especial.
Configurar Apache Spark
O SDK do Azure para Java dá suporte a várias versões do Jackson, mas às vezes podem surgir problemas dependendo das ferramentas de build e da sua ordenação de resolução de dependência. Um bom exemplo desse 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 desenvolvedores geralmente descobrem que uma versão mais recente de Jackson é usada, o que resulta em incompatibilidades. Para atenuar esse problema, você deve fixar uma versão específica de Jackson (uma compatível com o Spark). Para obter mais informações, consulte a seção Suporte para várias versões de Jackson neste artigo.
Se você usar versões anteriores do Spark ou se outra biblioteca usada exigir uma versão ainda anterior do Jackson à qual o SDK do Azure para Java não oferece suporte, continue lendo este artigo para possíveis etapas de mitigação.
Detectar a versão de runtime do Jackson
No Azure Core 1.21.0, adicionamos detecção de runtime e melhor diagnóstico da versão de runtime do Jackson.
Se você vir LinkageError
(ou qualquer uma das respectivas subclasses) relacionada à API do Jackson, verifique a mensagem da exceção para obter informações de versão de runtime. 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
Procure por logs de aviso e erro do JacksonVersion
. Para obter mais informações, consulte Configurar o log 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 obter a lista de pacotes usados pelo SDK do Azure e as versões de Jackson com suporte, consulte a seção Suporte para várias versões do Jackson .
Atenuar problemas de incompatibilidade de versão
As seções a seguir descrevem como atenuar problemas de incompatibilidade de versão.
Usar o BOM do SDK do Azure
Use o BOM do SDK estável mais recente do Azure e não especifique o SDK do Azure e as versões de dependência no arquivo POM. Quando aplicável, use a BOM do Azure Spring Boot.
As dependências listadas no BOM do SDK do Azure são testadas rigorosamente para evitar conflitos de dependência.
Evitar dependências desnecessárias
Remova as 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 aplicativos a vulnerabilidades de segurança, conflitos de versão e custos de suporte e manutenção.
Atualizar versões de dependência
Se a mudança para o BOM do SDK do Azure mais recente não ajudar, identifique as bibliotecas que causam conflitos e os componentes que as usam. (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 ela pode expor seu aplicativo a vulnerabilidades e problemas conhecidos.
Bibliotecas de sombra
Às vezes, não há nenhuma combinação de bibliotecas que funcionam em conjunto, e o sombreamento vem como o último recurso.
Observação
O sombreamento tem desvantagens significativas: aumenta o tamanho do pacote e o número de classes no classpath, dificulta a navegação e a depuração de código, não realoca código JNI, interrompe a reflexão e pode violar licenças de código entre outras coisas. Ele deve ser usado somente depois que outras opções estiverem esgotadas.
O sombreamento permite que você inclua dependências em um JAR no momento do build e, em seguida, renomeie pacotes e atualize o código do aplicativo para usar o código no local sombreado. O conflito de dependência de losango não é mais um problema, porque há duas cópias diferentes de uma dependência. Você pode sombrear uma biblioteca que tenha uma dependência transitiva conflitante ou uma dependência direta do aplicativo, conforme descrito na seguinte lista:
-
Conflito de dependência transitiva: por exemplo, a biblioteca
A
de terceiros requer o Jackson 2.9, que os SDKs do Azure não dão suporte e não é possível atualizarA
. Crie um módulo, que incluiA
e sombreia (realoca) o Jackson 2.9 e, opcionalmente, outras dependências deA
. - Conflito de dependência de aplicativo: seu aplicativo usa o Jackson 2.9 diretamente. Enquanto estiver trabalhando na atualização do código, você pode sombrear e realocar o Jackson 2.9 em um novo módulo com classes Jackson realocadas.
Observação
A criação de um JAR fat com classes do Jackson realocadas não resolve um conflito de versão nesses exemplos; ela apenas impõe que exista apenas uma versão sombreada do Jackson.
Criar um JAR do fat
Ambientes como o Databricks ou o Apache Spark têm gerenciamento de dependência personalizado e fornecem bibliotecas comuns, como Jackson. Para evitar conflitos com bibliotecas fornecidas, convém criar um JAR gordo que contenha todas as dependências. Para obter mais informações, consulte Plug-in de sombra do Apache Maven. Em muitos casos, a realocação de classes Jackson (com.fasterxml.jackson
) atenua o problema. Às vezes, esses ambientes também trazem sua própria versão dos SDKs do Azure, portanto, você pode ser obrigado a realocar com.azure
o namespace para contornar conflitos de versão.
Entender versões de dependência compatíveis
Para obter informações sobre azure-core
dependências específicas e suas versões, consulte azure-core no Repositório Central do Maven. A tabela a seguir mostra algumas considerações gerais:
Dependência | Versões suportadas |
---|---|
Jackson | As versões secundárias 2.10.0 e mais recentes são compatíveis. Para obter mais informações, consulte a seção Suporte para várias versões de Jackson . |
SLF4J | 1.7.* |
netty-tcnative-boringssl-static | 2.0.* |
netty-common | 4.1.* |
núcleo do reator | 3.X.* – Os números de versão principal e secundária devem corresponder exatamente aos números dos quais sua versão azure-core depende. Para obter mais informações, confira a política para preterimentos do Projeto Reactor. |
Suporte para várias versões do Jackson
O SDK do Azure para Java dá suporte ao trabalho com uma variedade de versões do Jackson. A versão com suporte mais baixo é a Jackson 2.10.0. As bibliotecas de clientes do SDK do Azure para Java ajustam sua configuração e o uso de Jackson dependendo da versão detectada no runtime. Esse ajuste permite maior compatibilidade com versões mais antigas do Spring Framework, Apache Spark e outros ambientes comuns. Os aplicativos podem fazer downgrade de versões de Jackson (para 2.10.0 ou superior) sem interromper o SDK do Azure para bibliotecas de clientes Java.
Observação
O uso de versões antigas do Jackson pode expor aplicativos a vulnerabilidades e problemas conhecidos. Para obter mais informações, consulte a lista de vulnerabilidades conhecidas para as bibliotecas Jackson.
Ao fixar uma versão específica do Jackson, certifique-se de fazer isso para todos os módulos usados pelo SDK do Azure, que são mostrados na lista a seguir:
jackson-annotations
jackson-core
jackson-databind
jackson-dataformat-xml
jackson-datatype-jsr310
Migração de Jackson para azure-json
As bibliotecas de clientes do Azure para Java estão em processo de migração para o azure-json, que não depende de nenhum componente de terceiros e oferece primitivos compartilhados, abstrações e auxiliares para JSON.
Ambientes como Apache Spark, Apache Flink e Databricks podem trazer versões mais antigas de azure-core
, que ainda não dependem de azure-json
. Como resultado, ao usar versões mais recentes de bibliotecas do Azure nesses ambientes, você pode receber erros semelhantes a java.lang.NoClassDefFoundError: com/azure/json/JsonSerializable
. Você pode atenuar esse erro adicionando uma dependência explícita em azure-json
.
Próximas etapas
Agora que você está familiarizado com conflitos de versão de dependência e como solucioná-los, consulte o Gerenciamento de Dependências para Java para obter informações sobre a melhor maneira de impedi-los.