Řešení konfliktů verzí závislostí

Tento článek popisuje konflikty verzí závislostí a jejich řešení.

Azure klientské knihovny pro Java závisejí na oblíbených knihovnách třetích stran, například na následujících knihovnách:

Mnoho Java aplikací a architektur používá tyto knihovny přímo nebo tranzitivně, což vede ke konfliktům verze. Správci závislostí, jako je Maven a Gradle, řeší všechny závislosti tak, aby na třídní cestě byla pouze jedna verze každé závislosti. Není však zaručeno, že vyřešená verze závislostí je kompatibilní se všemi příjemci této závislosti ve vaší aplikaci. Další informace najdete v tématu Úvod do mechanismu závislostí v dokumentaci k Mavenu a vysvětlení řešení závislostí v dokumentaci Gradle.

Nekompatibilita rozhraní API přímých závislostí způsobuje chyby při kompilaci. Nekompatibilita diamantových závislostí obvykle vede k selháním runtime, jako je NoClassDefFoundError, NoSuchMethodError nebo jiná LinkageError. Ne všechny knihovny striktně dodržují sémantické správy verzí a zásadní změny se někdy dějí ve stejné hlavní verzi.

Diagnostika problémů s neshodou verzí

Následující části popisují metody diagnostiky problémů s neshodou verzí.

Použití Azure SDK pro nástroj pro sestavení Java

Nástroj Azure SDK pro sestavení Java, který byl zaveden v Get spuštěný s Azure SDK a Apache Mavenem, pomáhá identifikovat běžné problémy. Doporučujeme přidat tento nástroj pro sestavení do vašeho projektu a spustit jej přidáním úlohy azure:run Mavenu do vašeho běžného procesu sestavení. S příslušnou konfigurací můžete identifikovat a vyřešit konflikty závislostí proaktivněji, než se stanou problémy za běhu.

Zobrazení stromu závislostí

Spusťte mvn dependency:tree nebo gradle dependencies --scan zobrazte celý strom závislostí pro vaši aplikaci s čísly verzí. mvn dependency:tree -Dverbose poskytuje více informací, ale může být zavádějící. Další informace najdete v dokumentaci k Stromu závislostí Apache Maven. Pro každou knihovnu, u které se domníváte, že došlo ke konfliktu verzí, si poznamenejte číslo verze a určete, které komponenty na ní závisí.

Řešení závislostí ve vývojových a produkčních prostředích může fungovat jinak. Apache Spark, Apache Flink, Databricks a pluginy pro IDE vyžadují další konfiguraci pro vlastní závislosti. Můžou si také přinést vlastní verze klientských knihoven Azure nebo společných komponent. Další informace najdete v následujících článcích:

Další informace o řešení konfliktů v takových prostředích naleznete v části Vytvoření Fat JAR dále v tomto článku.

Konfigurace Azure Functions

Interní verze závislostí na Azure Functions (fungující výhradně na Java 8) má přednost před verzí poskytovanou uživatelem. Tato závislost způsobuje konflikty verzí, zejména s Jacksonem, Nettym a Reactor.

Chcete-li tento problém vyřešit, nastavte proměnnou FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBS prostředí na true hodnotu nebo 1. Nezapomeňte aktualizovat nástroje funkcí Azure (verze 2 nebo v3) na nejnovější verzi.

Poznámka:

Tato konfigurace se vztahuje pouze na Azure Functions spuštěné Java 8. Funkce, na kterých běží Java 11, nepotřebují speciální konfiguraci.

Konfigurace Apache Sparku

Azure SDK pro Java podporuje více verzí Jacksona, ale problémy můžou někdy nastat v závislosti na nástrojích sestavení a jejich řazení řešení závislostí. Dobrým příkladem tohoto problému je Apache Spark verze 3.0.0 a novější, která závisí na Jacksonu 2.10. I když je kompatibilní s Azure SDK pro Java, vývojáři často zjistí, že se místo toho používá novější verze Jacksona, což vede k nekompatibilitě. Pokud chcete tento problém zmírnit, měli byste nastavit konkrétní verzi Jacksona, která je kompatibilní se Sparkem. Další informace najdete v části Podpora více verzí Jackson v tomto článku.

Pokud používáte starší verze Sparku, nebo pokud jiná knihovna, kterou používáte, vyžaduje ještě starší verzi Jacksona, kterou Azure SDK pro Javu nepodporuje, pokračujte ve čtení tohoto článku, kde najdete možné kroky k vyřešení problému.

Zjištění verze modulu runtime Jackson

V Azure Core 1.21.0 jsme přidali detekci modulu runtime a lepší diagnostiku verze modulu runtime Jackson.

Pokud se zobrazí LinkageError (nebo některá z jeho podtříd), které souvisejí s rozhraním Jackson API, zkontrolujte zprávu výjimky pro informace o verzi běhového prostředí. Příklad: 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

Vyhledejte upozornění a protokoly chyb z JacksonVersion. Další informace najdete v tématu Konfigurace protokolování v Azure SDK pro Java. Příklad: [main] ERROR com.azure.core.implementation.jackson.JacksonVersion - Version '2.9.0' of package 'jackson-core' is not supported (too old), please upgrade.

Poznámka:

Zkontrolujte, že všechny balíčky Jackson mají stejnou verzi.

Seznam balíčků používaných Azure SDK a podporovaných verzích Jacksonu najdete v části Support pro více verzí Jackson.

Zmírnění problémů s neshodou verzí

Následující části popisují, jak zmírnit problémy s neshodou verzí.

Použití Azure SDK BOM

Použijte nejnovější stabilní Azure SDK BOM a v souboru POM nezadávejte Azure SDK a verze závislostí. Pokud je to možné, použijte Azure Spring Boot BOM.

Závislosti uvedené ve specifikaci balíku Azure SDK jsou pečlivě testovány, aby nedocházelo ke konfliktům závislostí.

Vyhněte se zbytečným závislostem

Pokud je to možné, odeberte závislosti. Někdy má aplikace závislosti na více knihovnách, které poskytují v podstatě stejné funkce. Tyto zbytečné závislosti zpřístupňují aplikace ohrožením zabezpečení, konfliktům verzí a nákladům na podporu a údržbu.

Aktualizace verzí závislostí

Pokud přechod na nejnovější verzi kusovníku Azure SDK nepomůže, identifikujte knihovny, které způsobují konflikty, a komponenty, které je využívají. (Další informace najdete v části Zobrazit strom závislostí dříve v tomto článku.) Zkuste aktualizovat na novější verzi, která chrání před ohroženími zabezpečení, a často přináší nové funkce, vylepšení výkonu a opravy chyb.

Vyhněte se downgradu verze Azure SDK, protože může vystavit aplikaci známým ohrožením zabezpečení a problémům.

Stínovat knihovny

Někdy neexistuje žádná kombinace knihoven, které spolupracují, a stínování přichází jako poslední možnost.

Poznámka:

Stínování má významné nevýhody: zvyšuje velikost balíčku a počet tříd na classpath, ztěžuje navigaci v kódu a ladění, nepřemísťuje kód JNI, narušuje reflexi a může mimo jiné porušovat licence na kód. Mělo by se použít až po vyčerpání dalších možností.

Stínování umožňuje zahrnout závislosti v rámci souboru JAR v době sestavení a pak přejmenovat balíčky a aktualizovat kód aplikace tak, aby používal kód ve stínovaném umístění. Konflikt diamantové závislosti už není problém, protože existují dvě různé kopie závislosti. Můžete stínovat knihovnu, která má konfliktní tranzitivní závislost nebo přímou závislost aplikace, jak je popsáno v následujícím seznamu:

  • Konficiální konflikt závislostí: Například knihovna třetích stran A vyžaduje Jacksona 2.9, který Azure SDKs nepodporuje, a není možné aktualizovat A. Vytvořte nový modul, který zahrnuje A a odstíny (přemístí) Jackson 2.9 a volitelně i další závislosti A.
  • Konflikt závislostí aplikace: Aplikace používá Jackson 2.9 přímo. Zatímco pracujete na aktualizaci kódu, můžete stínovat a přemístit Jacksona 2.9 do nového modulu s přemísťovanými jacksonovými třídami.

Poznámka:

Vytvoření fat JAR s přemísťovanými jacksonovými třídami nevyřeší konflikt verzí v těchto příkladech – vynutí pouze jednu stínovanou verzi Jacksona.

Vytvořte "fat JAR"

Prostředí, jako jsou Databricks nebo Apache Spark, mají vlastní správu závislostí a poskytují běžné knihovny, jako je Jackson. Abyste se vyhnuli konfliktu s poskytnutými knihovnami, můžete vytvořit fat JAR, který obsahuje všechny závislosti. Další informace najdete v Apache Maven Shade Plugin. V mnoha případech se přemístěním jacksonových tříd (com.fasterxml.jackson) problém zmírní. V některých případech tato prostředí také přinášejí vlastní verzi Azure SDKs, takže můžete být nuceni přemístit com.azure obor názvů, abyste mohli obejít konflikty verzí.

Vysvětlení kompatibilních verzí závislostí

Informace o azure-corekonkrétních závislostech a jejich verzích najdete v azure-core v centrálním úložišti Maven. Následující tabulka uvádí některé obecné aspekty:

Závislost Podporované verze
Jackson Verze 2.10.0 a novější podverze jsou kompatibilní. Další informace najdete v části Podpora více verzí Jacksonu .
SLF4J 1.7.*
netty-tcnative-boringssl-static 2.0.*
netty-common 4.1.*
jádro reaktoru 3.X.* – Čísla hlavních a dílčích verzí musí přesně odpovídat těm, na kterých vaše azure-core verze závisí. Další informace najdete v zásadách projektu Reactor pro vyřazení.

Podpora více verzí Jacksonu

Azure SDK pro Java podporuje práci s řadou verzí Jackson. Nejnižší podporovaná verze je Jackson 2.10.0. Azure SDK pro klientské knihovny Java upraví konfiguraci a využití Jacksona v závislosti na verzi, která se detekuje za běhu. Tato úprava umožňuje větší kompatibilitu se staršími verzemi architektury Spring, Apache Sparku a dalšími běžnými prostředími. Aplikace můžou downgradovat verze Jackson (na verzi 2.10.0 nebo vyšší), aniž by došlo k narušení Azure SDK pro klientské knihovny Java.

Poznámka:

Používání starých verzí Jacksonu může vystavit aplikace známým ohrožením zabezpečení a problémům. Další informace najdete v seznamu známých ohrožení zabezpečení pro knihovny Jackson.

Při připnutí konkrétní verze Jacksonu je nutné to udělat pro všechny moduly používané Azure SDK, které jsou uvedeny v následujícím seznamu:

  • jackson-annotations
  • jackson-core
  • jackson-databind
  • jackson-dataformat-xml
  • jackson-datatype-jsr310

Migrace z Jacksonu na azure-json

Azure klientské knihovny pro Javu jsou v procesu migrace na azure-json, které nezávisí na komponentách třetích stran a nabízí sdílené primitivy, abstrakce a pomocné funkce pro JSON.

Prostředí jako Apache Spark, Apache Flink a Databricks můžou přinést starší verze azure-core, které ještě nezávisí na azure-json. V důsledku toho se při použití novějších verzí knihoven Azure v takových prostředích můžou zobrazit chyby podobné java.lang.NoClassDefFoundError: com/azure/json/JsonSerializable. Tuto chybu můžete zmírnit přidáním explicitní závislosti na azure-json.

Další kroky

Teď, když už znáte konflikty verzí závislostí a způsob jejich řešení, najdete v tématu Dependency Management pro Java informace o nejlepším způsobu, jak jim zabránit.