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.
Azure bibliotecas de clientes para Java dependem de bibliotecas populares de terceiros, como as seguintes:
Muitos aplicativos e frameworks 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 Azure SDK para Java
O Azure SDK para Java, ferramenta de build introduzida em Introdução ao Azure SDK e Apache Maven, ajuda a identificar problemas frequentemente 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 de cliente 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 Azure Functions
A versão de dependência interna em Azure Functions (executando apenas 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 a Azure Functions executando somente Java 8, as funções que executam Java 11 não precisam de configuração especial.
Configurar Apache Spark
O Azure SDK para Java dá suporte a várias versões de Jackson, mas às vezes podem surgir problemas dependendo das ferramentas de build e da 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 Azure SDK 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 de Jackson que o Azure SDK para Java não oferecer 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 em tempo de execução e melhoria nos diagnósticos da versão em tempo de execução 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 log no Azure SDK 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 por Azure SDK e as versões de Jackson com suporte, consulte a seção Support para várias versões de Jackson.
Atenuar problemas de incompatibilidade de versão
As seções a seguir descrevem como atenuar problemas de incompatibilidade de versão.
Usar Azure SDK BOM
Use o mais recente estável Azure SDK BOM e não especifique as versões do Azure SDK e de dependências no arquivo POM. Quando aplicável, use o Azure Spring Boot BOM.
As dependências listadas no Azure SDK BOM 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 Azure SDK BOM 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 Azure SDK 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 de terceiros
Arequer Jackson 2.9, que os SDKs do Azure não dão suporte e que não é possível atualizarA. Crie um módulo, que incluiAe 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 de Azure SDKs, portanto, você pode ser obrigado a realocar com.azure namespace para contornar conflitos de versão.
Entender 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 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 Azure SDK para Java dá suporte ao trabalho com uma variedade de versões de Jackson. A versão com suporte mais baixo é a Jackson 2.10.0. As bibliotecas de cliente do Azure SDK para Java ajustam sua configuração e o uso de Jackson dependendo da versão detectada em tempo de execução. 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 Azure SDK para bibliotecas de cliente 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 de Jackson, certifique-se de fazer isso para todos os módulos usados pelo Azure SDK, que são mostrados na seguinte lista:
jackson-annotationsjackson-corejackson-databindjackson-dataformat-xmljackson-datatype-jsr310
Migração de Jackson para azure-json
Azure bibliotecas de cliente para Java estão em processo de migração para azure-json, que não depende de nenhum componente de terceiros e oferece primitivos, abstrações e auxiliares compartilhados 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 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 Dependency Management for Java para obter informações sobre a melhor maneira de impedi-los.