Azure SDK for Javaが悪いのか、Nettyが悪いのか、Reactor Nettyが悪いのか、Spring Bootが悪いのか

nazology.net

そしてこのほど、米ペンシルベニア州立大学(PSU)の研究により、”湿度の高い環境”では、人が耐えられる気温の上限は、これまで想定されていたよりも低いことが明らかになりました。

人体が耐えられる「高温多湿の限界」はこれまでの想定より低いと判明 - ナゾロジー

⇧ 湿度大国日本...

Gradleの依存関係のjarがよく分からない...

ローカル環境で動いていたものが、テスト環境に上げたところ、

NoSuchMethodError reactor.netty.http.client.httpclient.resolver

みたいなエラーが出て正常に動かないという事象が起きてるんだけど、

blog.rutake.com

根本原因はコンパイル時に使ったjarファイルと実行時のjarファイルが違うこと。
jarファイルが同じものか確認することと、同じクラスを含むjarファイルが混在していたりしないかチェック。

NoSuchMethodErrorの原因をさぐる (技術メモ)

一度あったのが、アプリをバージョンアップした後に古いjarがworkディレクトリに残っていたためにこのエラーが出たというケース。

NoSuchMethodErrorの原因をさぐる (技術メモ)

⇧ということらしく、jarの差分を確認すれば、解決できるのか...

そもそも、同じ内容のbuild.gradleを利用しているのに、jarが残ることがあるのか?

discuss.gradle.org

⇧ 残るらしい...

確かに、ローカル環境で、build.gradleに依存関係を追加したり削除したりを繰り返して必要な依存関係の洗い出しを行っていたから、残ったjarファイルの影響でローカル環境は正常に動作していたってことになるんかな?

51.9. 依存関係のキャッシュ

Gradleのキャッシュでは、ローカルキャッシュによって問題が隠蔽されるようなことはありませんし、多くのビルドツールで直面してきたような不可解でデバッグ困難な動作をすることもありません。 また、その実装は帯域、ストレージ双方において効率的なものです。それにより、Gradleはエンタープライズでのビルドに必要な信頼性、再現性を達成しているのです。

http://gradle.monochromeroad.com/docs/userguide/dependency_management.html

⇧ ってあるんだけどな...

実際に不可解な現象が起きてるんだが...

Gradleの基本のドキュメントを見ると、

docs.gradle.org

⇧リモートリポジトリにあるライブラリについては、一度ダウンロードできると、「Gradle Cache」に保存され、そちらを参照する仕組みらしい。

であれば、何を基準に、「Gradle Cache」に保存されたライブラリを参照しているかを知りたいんだけどな、まさかキャッシュされたものは無差別にすべて読み込むなんてことは無いと思うし。

最終的には、WARファイルにした後に、中身を確認してどのjarが読み込まれてるのかをチェックしていくしかないんかな...

ちなみに、自分の問題なく動いている環境では、

■build.gradle

plugins {
	id 'org.springframework.boot' version '2.6.6'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'org.postgresql:postgresql'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'com.azure.resourcemanager:azure-resourcemanager-mediaservices:2.0.0'
    implementation 'com.googlecode.json-simple:json-simple:1.1.1'
    implementation 'com.azure:azure-storage-blob:12.16.0'
    implementation 'com.azure:azure-identity:1.5.0'
    
    implementation 'com.azure:azure-security-keyvault-secrets:4.4.2'
}

tasks.named('test') {
	useJUnitPlatform()
}

で、依存関係を追加しているのですが、

■メインクラスとその依存関係を含む実行可能なjar一覧

accessors-smart-2.4.8.jar
antlr-2.7.7.jar
asm-9.1.jar
aspectjweaver-1.9.7.jar
attoparser-2.0.5.RELEASE.jar
azure-core-1.28.0.jar
azure-core-http-netty-1.12.0.jar
azure-core-management-1.5.3.jar
azure-identity-1.5.0.jar
azure-resourcemanager-mediaservices-2.0.0.jar
azure-security-keyvault-secrets-4.4.2.jar
azure-storage-blob-12.16.0.jar
azure-storage-common-12.15.1.jar
azure-storage-internal-avro-12.2.1.jar
byte-buddy-1.11.22.jar
checker-qual-3.5.0.jar
classmate-1.5.1.jar
content-type-2.2.jar
hamcrest-2.2.jar
hamcrest-core-2.2.jar
HdrHistogram-2.1.12.jar
hibernate-commons-annotations-5.1.2.Final.jar
hibernate-core-5.6.7.Final.jar
HikariCP-4.0.3.jar
istack-commons-runtime-3.0.12.jar
jackson-annotations-2.13.2.jar
jackson-core-2.13.2.jar
jackson-databind-2.13.2.2.jar
jackson-dataformat-xml-2.13.2.jar
jackson-datatype-jdk8-2.13.2.jar
jackson-datatype-jsr310-2.13.2.jar
jackson-module-parameter-names-2.13.2.jar
jakarta.activation-1.2.2.jar
jakarta.annotation-api-1.3.5.jar
jakarta.persistence-api-2.2.3.jar
jakarta.transaction-api-1.3.3.jar
jakarta.xml.bind-api-2.3.3.jar
jandex-2.4.2.Final.jar
jaxb-runtime-2.3.6.jar
jboss-logging-3.4.3.Final.jar
jcip-annotations-1.0-1.jar
jna-5.6.0.jar
jna-platform-5.6.0.jar
json-simple-1.1.1.jar
json-smart-2.4.8.jar
jul-to-slf4j-1.7.36.jar
junit-4.13.2.jar
lang-tag-1.5.jar
LatencyUtils-2.0.3.jar
log4j-api-2.17.2.jar
log4j-to-slf4j-2.17.2.jar
logback-classic-1.2.11.jar
logback-core-1.2.11.jar
micrometer-core-1.8.4.jar
msal4j-1.11.3.jar
msal4j-persistence-extension-1.1.0.jar
netty-buffer-4.1.75.Final.jar
netty-codec-4.1.75.Final.jar
netty-codec-dns-4.1.75.Final.jar
netty-codec-http-4.1.75.Final.jar
netty-codec-http2-4.1.75.Final.jar
netty-codec-socks-4.1.75.Final.jar
netty-common-4.1.75.Final.jar
netty-handler-4.1.75.Final.jar
netty-handler-proxy-4.1.75.Final.jar
netty-resolver-4.1.75.Final.jar
netty-resolver-dns-4.1.75.Final.jar
netty-resolver-dns-classes-macos-4.1.75.Final.jar
netty-resolver-dns-native-macos-4.1.75.Final-osx-x86_64.jar
netty-tcnative-boringssl-static-2.0.51.Final.jar
netty-tcnative-classes-2.0.51.Final.jar
netty-transport-4.1.75.Final.jar
netty-transport-classes-epoll-4.1.75.Final.jar
netty-transport-classes-kqueue-4.1.75.Final.jar
netty-transport-native-epoll-4.1.75.Final-linux-x86_64.jar
netty-transport-native-kqueue-4.1.75.Final-osx-x86_64.jar
netty-transport-native-unix-common-4.1.75.Final.jar
nimbus-jose-jwt-9.15.2.jar
oauth2-oidc-sdk-9.22.1.jar
postgresql-42.3.3.jar
reactive-streams-1.0.3.jar
reactor-core-3.4.16.jar
reactor-netty-core-1.0.17.jar
reactor-netty-http-1.0.17.jar
slf4j-api-1.7.36.jar
snakeyaml-1.29.jar
spring-aop-5.3.18.jar
spring-aspects-5.3.18.jar
spring-beans-5.3.18.jar
spring-boot-2.6.6.jar
spring-boot-actuator-2.6.6.jar
spring-boot-actuator-autoconfigure-2.6.6.jar
spring-boot-autoconfigure-2.6.6.jar
spring-boot-jarmode-layertools-2.6.6.jar
spring-context-5.3.18.jar
spring-core-5.3.18.jar
spring-data-commons-2.6.3.jar
spring-data-jpa-2.6.3.jar
spring-expression-5.3.18.jar
spring-jcl-5.3.18.jar
spring-jdbc-5.3.18.jar
spring-orm-5.3.18.jar
spring-tx-5.3.18.jar
spring-web-5.3.18.jar
spring-webmvc-5.3.18.jar
stax2-api-4.2.1.jar
thymeleaf-3.0.15.RELEASE.jar
thymeleaf-extras-java8time-3.0.4.RELEASE.jar
thymeleaf-spring5-3.0.15.RELEASE.jar
tomcat-embed-core-9.0.60.jar
tomcat-embed-el-9.0.60.jar
tomcat-embed-websocket-9.0.60.jar
txw2-2.3.6.jar
unbescape-1.1.6.RELEASE.jar
woodstox-core-6.2.7.jar

⇧ だけのjarが読み込まれている。

とりあえず、今回の『NoSuchMethodError reactor.netty.http.client.httpclient.resolver』に関わってるんじゃなかろうか的なものを調べてみます。

Azure SDK for Javaとは?

Azure SDK for Javaとは、

github.com

This repository is for active development of the Azure SDK for Java. For consumers of the SDK we recommend visiting our public developer docs at https://docs.microsoft.com/java/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-java.

https://github.com/Azure/azure-sdk-for-java

⇧ と、全く説明がなってないのですが、

docs.microsoft.com

  • Azure SDK for Java ライブラリは、基になる Azure REST API の上に構築されているため、使い慣れた Javaパラダイムからそれらの API を使用できます。 ただし、REST API は、必要に応じていつでも Java コードから直接使用できます。

https://docs.microsoft.com/ja-jp/azure/developer/java/sdk/overview

⇧ ということらしい。

Azure REST APIありきということのようです。

役立ち情報みたいなまとめが以下らしい。

azuresdkartifacts.blob.core.windows.net

で、

azuresdkartifacts.blob.core.windows.net

⇧ 上記のMaven Siteの中のリンクがバグっていて、肝心のそれぞれのライブラリが必要とする依存関係が参照できなかったので、調整したのが以下のURL。2022年7月2日(土)時点の情報。ドキュメントの配置場所が変わったら参照できなくなると思うけど...

https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-ai-anomalydetector/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-data-appconfiguration/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-security-attestation/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-communication-chat/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-communication-common/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-communication-identity/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-communication-phonenumbers/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-communication-sms/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-security-confidentialledger/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-containers-containerregistry/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-core/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-core-amqp/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-core-amqp-experimental/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-core-experimental/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-core-http-netty/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-core-http-okhttp/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-core-serializer-avro-apache/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-core-serializer-json-gson/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-core-serializer-json-jackson/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-core-test/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-core-tracing-opentelemetry/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-cosmos/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-iot-deviceupdate/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-digitaltwins-core/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-messaging-eventgrid/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-messaging-eventhubs/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-messaging-eventhubs-checkpointstore-blob/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-ai-formrecognizer/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-identity/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-security-keyvault-administration/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-security-keyvault-certificates/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-security-keyvault-jca/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-security-keyvault-keys/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-security-keyvault-secrets/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-ai-metricsadvisor/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-mixedreality-authentication/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-iot-modelsrepository/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-monitor-opentelemetry-exporter/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-monitor-query/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-analytics-purview-catalog/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-analytics-purview-scanning/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-quantum-jobs/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-mixedreality-remoterendering/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-data-schemaregistry/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-data-schemaregistry-avro/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-search-documents/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-messaging-servicebus/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-storage-blob/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-storage-blob-batch/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-storage-blob-changefeed/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-storage-blob-cryptography/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-storage-blob-nio/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-storage-common/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-storage-file-datalake/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-storage-file-share/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-storage-internal-avro/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-storage-queue/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-analytics-synapse-accesscontrol/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-analytics-synapse-artifacts/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-analytics-synapse-managedprivateendpoints/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-analytics-synapse-monitoring/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-analytics-synapse-spark/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-data-tables/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-ai-textanalytics/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-ai-documenttranslator/dependencies.html
https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/azure-messaging-webpubsub/dependencies.html

で、試しに、Azure Blob StorageのAPI利用に必要な依存関係を確認してみる。

azuresdkartifacts.blob.core.windows.net

最後の更新が、2021-08-30ってのが、まず辛い...

そして、Azure Blob StorageのAPIを動作させるには、以下の依存関係が必要であると。

⇧ Spring Bootが依存関係をカバーしてくれているように見えますと。

Azure SDK for Java の HTTP クライアント

Azure SDK for JavaとHTTPクライアントの説明によると、

docs.microsoft.com

Azure SDK for Java は、HttpClient の抽象化を使用して実装されます。 この抽象化により、複数の HTTP クライアント ライブラリまたはカスタム実装を受け入れるプラグ可能なアーキテクチャが可能になります。 ただし、ほとんどのユーザーの依存関係の管理を簡素化するために、すべての Azure クライアント ライブラリは azure-core-http-netty に依存しています。 そのため、すべての Azure SDK for Java ライブラリで使用される既定のクライアントは NettyHTTP クライアントです。

https://docs.microsoft.com/ja-jp/azure/developer/java/sdk/http-client-pipeline

Netty が既定の HTTP クライアントですが、SDK には、お使いのプロジェクトに既に存在する依存関係に応じて 3 つのクライアント実装が用意されています。 これらの実装は、次を対象とします。

https://docs.microsoft.com/ja-jp/azure/developer/java/sdk/http-client-pipeline

⇧ とあり、デフォルトだと、全てのAzure SDK for Javaについて、Netty HTTPクライアントが利用されてますと。

Azure SDK for Javaは、Nettyありきというか、Netty無いと動かんってことですかね。

Nettyとは

公式のドキュメントによりますと、

netty.io

Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server.

https://netty.io/

⇧NIOというのは、「Non Blocking I/O」の略らしいんですが、

takezoe.hatenablog.com

⇧ 上記サイト様の説明がイメージしやすいかと。

で、

⇧ サラッと、Windowsが除け者にされとるんだが...

I/Oの多重化って、OSに依存するんかな?

まぁ、NettyがI/Oの多重化を実現してないんであれば、関係ないですが、もしNettyがI/Oの多重化を実現しているんであれば、Windows環境でも機能するのは、「Java仮想マシンJVMJava Virtual Machine)」のおかげとかになるんかな?

NettyのGitHubで公開している情報によると、

github.com

Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.

https://github.com/netty/netty

⇧ 非同期イベント駆動ネットワークアプリケーションフレームワークということらしい。

Reactor Nettyとは

Reactor NettyのGitHubで公開している情報によると、

github.com

Reactor Netty offers non-blocking and backpressure-ready TCP/HTTP/UDP/QUIC clients & servers based on Netty framework.

https://github.com/reactor/reactor-netty

⇧ とあり、Nettyをベースにしているらしい。

Reactorはと言うと、

projectreactor.io

Reactor is a fourth-generation reactive library, based on the Reactive Streams
specification, for building non-blocking applications on the JVM

https://projectreactor.io/

⇧「Java仮想マシンJVMJava Virtual Machine)」上で動作するアプリケーションがターゲットらしい。

Spring BootとNetty

ドキュメントによると、

spring.pleiades.io

 WebClient クラスを使用するには spring-boot-starter-reactor-netty が必要なので、別の HTTP サーバーを含める必要がある場合でも、Netty への依存関係を維持する必要があります。

https://spring.pleiades.io/spring-boot/docs/current/reference/html/howto.html#howto.webserver

⇧ WebClientを利用しないのであれば、特に気にする必要はないらしいのですが、WebClientを使ってるかどうかの確認の術が不明なんだが...

で、結局、やっぱりSpring Bootが悪いと思う

まぁ、結局のところ、悪いのはSpring Bootになるんだと思う。

というのも、まず、Spring Bootのバージョンによるのかもしれないですが、

⇧ Netty系のライブラリと、

⇧ Reactor Netty系のライブラリが暗黙的に追加されてるという...

ただ、

github.com

⇧ Spring Bootのbuild.gradleを見た限り、上記の依存関係がすべて読み込まれるようには見えない気がするんよね...

つまり、Spring Bootが依存関係をどこまで面倒見てくれているのかが非常に分かり辛い...

そして、問題が起こってるSpring Bootのバージョンが低いせいなのかが分からんのだけど、暗黙的に読み込まれてるライブラリで動かんというね...

毎度モヤモヤ感が半端ない...

今回はこのへんで。