猫が綴る雑多なブログ

JavaのModule導入でGsonパースエラー

プロジェクトをJava8からJava17へLTS移行するにあたり、対処を迫られた事象の解決備忘録です

やっていたこと

Java8で構築していたプロジェクトを、Java17へ移行していました。 当該プロジェクトはMavenで構成していましたが、今回の事象は特に関係なく発生すると思われ、また対処も共通です。

either increase its visibility or write a custom TypeAdapter for its declaring type.

ビルドエラーの解消と、依存先ライブラリのバージョン更新を一通り終え、jUnitテストを流した時、 GsonのテストケースがFailedとなりました。

[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.044 s <<< FAILURE! - in pro.eng.yui.myproj.pkj.sub.ParseTest
[ERROR] pro.eng.yui.myproj.pkj.sub.ParseTest.fromJson  Time elapsed: 0.039 s  <<< ERROR!
com.google.gson.JsonIOException: Failed making field 'pro.eng.yui.myproj.pkj.def.MyDataCls#dataField' accessible;
either increase its visibility or write a custom TypeAdapter for its declaring type.
	at com.google.gson@2.10.1/com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:38)
	at com.google.gson@2.10.1/com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:286)
	at com.google.gson@2.10.1/com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:130)
	at com.google.gson@2.10.1/com.google.gson.Gson.getAdapter(Gson.java:556)
	at com.google.gson@2.10.1/com.google.gson.Gson.fromJson(Gson.java:1226)
	at com.google.gson@2.10.1/com.google.gson.Gson.fromJson(Gson.java:1137)
	at com.google.gson@2.10.1/com.google.gson.Gson.fromJson(Gson.java:1047)
	at com.google.gson@2.10.1/com.google.gson.Gson.fromJson(Gson.java:1014)
	at MyProject@1.2/pro.eng.yui.myproj.pkj.utils.JsonUtil.getObjectFromJsonStr(JsonUtil.java:26)
	at MyProject@1.2/pro.eng.yui.myproj.pkj.sub.ParseTest.fromJson(ParseTest.java:22)

エラー内容を和訳すると、変換しようとしたクラスMyDataCls内のprivateフィールドdataFieldを読み出し可能にできませんでした。 可視度をpublicに引き上げるか、独自のTypeAdapterを定義してくださいと言われています。

対策

Java9で導入されたModuleを明確化するために導入したmodule-info.javaへの追記で、本エラーは対策できます。

module-info.java
module MyProject {
    requires com.google.gson;
    
    exports pro.eng.yui.myproj;
    
    // 指定したパッケージへのリフレクションによるアクセスをto指定のモジュールに対して許可する
    opens pro.eng.yui.myproj.pkj.def to com.google.gson;
}

Gson変換の対象でprivateフィールドを持つクラスが格納されているパッケージを、ひとつひとつopens指定により、 Gsonモジュールからのreflection-accessを明示的に認めます。
Module化によってリフレクションが阻害されるという副次効果と、その対策という形になります

つれづれ

に公開した技術記事「jUnitでprivateメソッドをテストする」が、 実はこのサイト内で最多アクセスを誇る記事となっています。おかげさまでちょっとやる気が出て、同記事を英語翻訳したりもしています。(Test the PRIVATE method with jUnit
Javaエンジニアの皆様の手助けになっていること、嬉しく思いながらGoogleAnalyticsを眺めています

謝辞・参考サイト

本記事の対応に際して参照したサイトを以下に掲げ、感謝を申し上げます


ブログランキング・にほんブログ村へに参加しています。 PVアクセスランキング にほんブログ村 猫が綴る雑多なブログ - にほんブログ村 にほんブログ村 IT技術ブログへ にほんブログ村 IT技術ブログ IT技術メモへ



コメントはこちらからお寄せください