今回は、複数JDBCを使用するアプリケーションなどを「Gradle Shadow Plugin」で作成したJAR(Java ARchive)ファイルを実行したときに、次のようなエラーが発生した場合の原因と解決方法を紹介していきます。
java.sql.SQLException: No suitable driver found for xxxx
検証環境
検証に使用した環境/ライブラリを次に記載します。
- Java
- バージョン:11
- Gradle
- バージョン:7.0
- Gradle Shadow Plugin
- バージョン:7.0.0
- SQLite
- バージョン:3.34.0
- H2Database
- バージョン:1.4.200
原因
原因については、JDBCドライバを見つける仕組みを説明してから、今回の問題が発生する理由を説明していきます。
JDBCドライバを見つける仕組みは、JDBCのバージョンにより異なりますがJDBC4.0(JDK1.6以降)では、それぞれのJDBCライブラリの「META-INF/services/java.sql.Driver」ファイルに、使用するドライバークラス名を指定しています。
SQLiteでは、対象ファイルの内容は次のようになります。
org.sqlite.JDBC
H2Databaseでは、対象ファイルの内容は次のようになります。
org.h2.Driver
作成したJARファイルにも同じファイルが必要になりますが、「Gradle Shadow Plugin」で作成した場合の対象ファイルの内容は次のようになります。
org.h2.Driver
複数JDBCを指定している場合は、次のようにそれぞれのJDBCライブラリのファイル内容をまとめたものにする必要があります。
org.sqlite.JDBC
org.h2.Driver
このようなファイル内容になるのは、「Gradle Shadow Plugin」でJARファイルを作成するときは、JARファイルをすべて展開したあとに再度まとめる動作をしているためです。
複数JDBCを使用している場合は、それぞれのJDBCライブラリを展開すると「META-INF/services/java.sql.Driver」ファイルが同じディレクトリ/ファイル名になります。このときに、重複したファイルは上書きされるためどちらかの設定が消えてしまいます。
解決方法
ビルドスクリプトファイルの「build.gradle」などに次の設定を追加することで、「META-INF/services」ファイルに対してのは、上書きではなくマージする動作に変更することができます。
shadowJar {
mergeServiceFiles()
}
まとめ
複数JDBCを使用しているアプリケーションで「Gradle Shadow Plugin」を使用して1つのJARファイルを作成したときに、JDBCドライバの登録に失敗する原因と解決方法を紹介しました。