Delen via


Problemen met afhankelijkheidsversies oplossen

In dit artikel worden afhankelijkheidsversieconflicten beschreven en hoe u deze problemen kunt oplossen.

Azure clientbibliotheken voor Java zijn afhankelijk van populaire bibliotheken van derden, zoals de volgende bibliotheken:

Veel Java toepassingen en frameworks gebruiken deze bibliotheken rechtstreeks of transitief, wat leidt tot versieconflicten. Afhankelijkheidsbeheerders zoals Maven en Gradle lossen alle afhankelijkheden op, zodat er slechts één versie van elke afhankelijkheid op het klassepad staat. Het is echter niet gegarandeerd dat de opgeloste afhankelijkheidsversie compatibel is met alle consumenten van die afhankelijkheid in uw toepassing. Zie Inleiding tot het mechanisme voor afhankelijkheden in de Maven-documentatie en Inzicht in afhankelijkheidsoplossing in de Gradle-documentatie voor meer informatie.

De API-incompatibiliteit van directe afhankelijkheden resulteert in compilatiefouten. Diamantafhankelijkheidsincompatibiliteit resulteert meestal in runtimefouten zoals NoClassDefFoundError, NoSuchMethodError of andere LinkageError. Niet alle bibliotheken volgen strikt semantisch versiebeheer, en brekende wijzigingen vinden soms plaats binnen dezelfde hoofdversie.

Problemen met niet-overeenkomende versies vaststellen

In de volgende secties worden methoden beschreven voor het vaststellen van problemen met niet-overeenkomende versies.

De Azure SDK gebruiken voor Java build-hulpprogramma

De Azure SDK voor Java build tool, geïntroduceerd in Get gestart met Azure SDK en Apache Maven helpt bij het identificeren van veelvoorkomende problemen. U wordt aangeraden dit buildhulpprogramma aan uw project toe te voegen en uit te voeren door het azure:run Maven-doel toe te voegen aan uw reguliere buildproces. Met de juiste configuratie kunt u afhankelijkheidsconflicten proactief identificeren en oplossen voordat ze tijdens runtime problemen worden.

Een afhankelijkheidsstructuur weergeven

Voer mvn dependency:tree de volledige afhankelijkheidsstructuur voor uw toepassing uit of gradle dependencies --scan geef deze weer met versienummers. mvn dependency:tree -Dverbose geeft meer informatie, maar kan misleidend zijn. Zie de Apache Maven-afhankelijkheidsstructuur in de Maven-documentatie voor meer informatie. Voor elke bibliotheek waarvan u vermoedt dat er een versieconflict is, noteert u het versienummer en bepaalt u welke onderdelen ervan afhankelijk zijn.

Afhankelijkheidsoplossing in ontwikkel- en productieomgevingen werkt mogelijk anders. Apache Spark-, Apache Flink-, Databricks- en IDE-invoegtoepassingen hebben extra configuratie nodig voor aangepaste afhankelijkheden. Ze kunnen ook hun eigen versies van Azure Client-bibliotheken of algemene onderdelen meenemen. Zie de volgende artikelen voor meer informatie:

Raadpleeg de sectie Een vet JAR maken verderop in dit artikel voor meer informatie over conflictoplossing in dergelijke omgevingen.

Azure Functions configureren

De interne afhankelijkheidsversie van Azure Functions (alleen Java 8) heeft voorrang op een door de gebruiker opgegeven versie. Deze afhankelijkheid veroorzaakt versieconflicten, met name met Jackson, Netty en Reactor.

Als u dit probleem wilt oplossen, stelt u de FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBS omgevingsvariabele in op true of 1. Zorg ervoor dat u de Azure Functiehulpprogramma's (v2 of v3) bijwerkt naar de nieuwste versie.

Opmerking

Deze configuratie is alleen van toepassing op Azure Functions die Java 8 uitvoeren. Functies die Java 11 uitvoeren hebben geen speciale configuratie nodig.

Apache Spark configureren

De Azure SDK voor Java ondersteunt meerdere versies van Jackson, maar soms kunnen er problemen optreden, afhankelijk van uw buildhulpprogramma's en de volgorde van afhankelijkheidsoplossing. Een goed voorbeeld van dit probleem is met Apache Spark, versie 3.0.0 en hoger, wat afhankelijk is van Jackson 2.10. Hoewel het compatibel is met de Azure SDK voor Java, ontdekken ontwikkelaars vaak dat een recentere versie van Jackson wordt gebruikt, wat resulteert in incompatibiliteit. Als u dit probleem wilt verhelpen, moet u een specifieke versie van Jackson vastmaken (een versie die compatibel is met Spark). Zie de sectie Ondersteuning voor meerdere Jackson-versies in dit artikel voor meer informatie.

Als u eerdere versies van Spark gebruikt of als een andere bibliotheek die u gebruikt, een nog eerdere versie van Jackson vereist die de Azure SDK voor Java niet ondersteunt, leest u dit artikel verder voor mogelijke risicobeperkingsstappen.

Runtimeversie van Jackson detecteren

In Azure Core 1.21.0 hebben we runtimedetectie en betere diagnoses van de Runtime-versie van Jackson toegevoegd.

Als u LinkageError (of een van de subklassen) die gerelateerd zijn aan de Jackson-API ziet, controleert u het bericht van de uitzondering voor runtime versie-informatie. Bijvoorbeeld: 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

Zoek naar waarschuwings- en foutlogboeken van JacksonVersion. Voor meer informatie, zie Configure-logboekregistratie in de Azure SDK voor Java. Bijvoorbeeld: [main] ERROR com.azure.core.implementation.jackson.JacksonVersion - Version '2.9.0' of package 'jackson-core' is not supported (too old), please upgrade.

Opmerking

Controleer of alle Jackson-pakketten dezelfde versie hebben.

Zie de sectie Ondersteuning voor meerdere Jackson-versies voor de lijst met pakketten die worden gebruikt door Azure SDK en de ondersteunde Jackson-versies.

Problemen met niet-overeenkomende versies beperken

In de volgende secties wordt beschreven hoe u problemen met niet-overeenkomende versies kunt beperken.

Gebruik Azure SDK BOM

Gebruik de nieuwste stabiele Azure SDK BOM en geef geen Azure SDK- en afhankelijkheidsversies op in uw POM-bestand. Gebruik indien van toepassing de Azure Spring Boot BOM.

De afhankelijkheden die worden vermeld in de Azure SDK BOM worden grondig getest om afhankelijkheidsconflicten te voorkomen.

Vermijd onnodige afhankelijkheden

Verwijder desgewenst afhankelijkheden. Soms heeft een toepassing afhankelijkheden van meerdere bibliotheken die in wezen dezelfde functionaliteit bieden. Dergelijke onnodige afhankelijkheden stellen toepassingen bloot aan beveiligingsproblemen, versieconflicten en ondersteunings- en onderhoudskosten.

Afhankelijkheidsversies bijwerken

Als het overschakelen naar de meest recente Azure SDK BOM niet helpt, identificeert u de bibliotheken die conflicten veroorzaken en de onderdelen die deze gebruiken. (Zie de sectie Een afhankelijkheidsstructuur weergeven eerder in dit artikel voor meer informatie.) Probeer bij te werken naar een nieuwere versie, die bescherming biedt tegen beveiligingsproblemen en vaak nieuwe functies, prestatieverbeteringen en oplossingen voor fouten bevat.

Vermijd het downgraden van de Azure SDK-versie, omdat uw toepassing mogelijk wordt blootgesteld aan bekende beveiligingsproblemen en problemen.

Schadebibliotheken

Soms is er geen combinatie van bibliotheken die samenwerken, en arcering komt als laatste redmiddel.

Opmerking

Arcering heeft aanzienlijke nadelen: het verhoogt de pakketgrootte en het aantal klassen op het klassepad, maakt codenavigatie en foutopsporing moeilijk, verplaatst JNI-code niet, breekt reflectie en kan onder andere codelicenties schenden. Deze moet alleen worden gebruikt nadat andere opties zijn uitgeput.

Met arcering kunt u afhankelijkheden opnemen in een JAR tijdens het bouwen, vervolgens de naam van pakketten wijzigen en toepassingscode bijwerken om de code op de gearceerde locatie te gebruiken. Een conflict tussen diamantafhankelijkheid is geen probleem meer omdat er twee verschillende kopieën van een afhankelijkheid zijn. U kunt een bibliotheek met een conflicterende transitieve afhankelijkheid of een directe toepassingsafhankelijkheid weglaten, zoals beschreven in de volgende lijst.

  • Transitive dependency conflict: Bijvoorbeeld, een externe bibliotheek A vereist Jackson 2.9, die niet door Azure SDK's wordt ondersteund, en het is niet mogelijk om A bij te werken. Maak een nieuwe module, die A bevat en Jackson 2.9 verschuift (relocate) en, indien gewenst, andere afhankelijkheden van A.
  • Conflict met toepassingsafhankelijkheid: uw toepassing maakt rechtstreeks gebruik van Jackson 2.9. Terwijl u uw code bijwerkt, kunt u Jackson 2.9 hernoemen en herloceren naar een nieuwe module met verplaatste Jackson-klassen.

Opmerking

Het maken van een vet JAR-bestand met verplaatste Jackson-klassen lost geen versieconflict op in deze voorbeelden - het dwingt slechts een enkele schaduwversie van Jackson af.

Een fat JAR-bestand maken

Omgevingen zoals Databricks of Apache Spark hebben aangepast afhankelijkheidsbeheer en bieden algemene bibliotheken zoals Jackson. Om conflicten met opgegeven bibliotheken te voorkomen, kunt u een vet JAR maken die alle afhankelijkheden bevat. Zie de Apache Maven Shade-invoegtoepassing voor meer informatie. In veel gevallen vermindert het verplaatsen van Jackson-klassen (com.fasterxml.jackson) het probleem. Soms brengen dergelijke omgevingen ook hun eigen versie van Azure SDKs mee, zodat u mogelijk wordt gedwongen om com.azure naamruimte te verplaatsen om versieconflicten te omzeilen.

Compatibele afhankelijkheidsversies begrijpen

Zie azure-core in de Centrale opslagplaats van Maven voor informatie over -specifieke afhankelijkheden en hun versies. In de volgende tabel ziet u enkele algemene overwegingen:

Afhankelijkheid Ondersteunde versies
Jackson 2.10.0 en nieuwere secundaire versies zijn compatibel. Zie de sectie Ondersteuning voor meerdere Jackson-versies voor meer informatie.
SLF4J 1.7.*
netty-tcnative-boringssl-static 2.0.*
netty-common 4.1.*
reactorkern 3.X.* - Primaire en secundaire versienummers moeten exact overeenkomen met de nummers waarop uw azure-core versie afhankelijk is. Voor meer informatie raadpleeg het Project Reactor-beleid over verouderde functies.

Ondersteuning voor meerdere Jackson-versies

De Azure SDK voor Java ondersteunt het werken met een reeks Jackson-versies. De laagste ondersteunde versie is Jackson 2.10.0. De Azure SDK voor Java clientbibliotheken passen hun configuratie en jacksongebruik aan, afhankelijk van de versie die tijdens runtime wordt gedetecteerd. Deze aanpassing maakt een grotere compatibiliteit mogelijk met oudere versies van het Spring-framework, Apache Spark en andere algemene omgevingen. Toepassingen kunnen Jackson-versies (naar 2.10.0 of hoger) downgraden zonder dat Azure SDK voor Java clientbibliotheken wordt onderbroken.

Opmerking

Het gebruik van oude versies van Jackson kan toepassingen blootstellen aan bekende beveiligingsproblemen en problemen. Zie de lijst met bekende beveiligingsproblemen voor Jackson-bibliotheken voor meer informatie.

Wanneer u een specifieke versie van Jackson vastzet, moet u dit doen voor alle modules van de Azure SDK die worden gebruikt, zoals te zien in de volgende lijst:

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

Migratie van Jackson naar azure-json

Azure clientbibliotheken voor Java worden gemigreerd naar azure-json, die niet afhankelijk zijn van onderdelen van derden en gedeelde primitieven, abstracties en helpers voor JSON biedt.

Omgevingen zoals Apache Spark, Apache Flink en Databricks kunnen oudere versies van azure-core bevatten die nog niet afhankelijk zijn van azure-json. Als u nieuwere versies van Azure bibliotheken in dergelijke omgevingen gebruikt, krijgt u mogelijk fouten die vergelijkbaar zijn met java.lang.NoClassDefFoundError: com/azure/json/JsonSerializable. U kunt deze fout beperken door een expliciete afhankelijkheid toe te voegen aan azure-json.

Volgende stappen

Nu u bekend bent met conflicten met afhankelijkheidsversies en hoe u deze kunt oplossen, raadpleegt u Beheer voor Java voor informatie over de beste manier om deze te voorkomen.