【Gradle Shadow Plugin】複数JDBCが使用できない場合の解決方法の紹介

今回は、複数JDBCを使用するアプリケーションなどを「Gradle Shadow Plugin」で作成したJAR(Java ARchive)ファイルを実行したときに、次のようなエラーが発生した場合の原因と解決方法を紹介していきます。

java.sql.SQLException: No suitable driver found for xxxx

「No suitable driver found」は、JDBCドライバが見つからない場合に発生するエラーになります。「xxxx」には、登録されていないJDBCドライバの情報が表示されます。

この問題は、開発環境などでは発生しません。「Gradle Shadow Plugin」で作成したJARファイルを実行するまでわからないため、問題の発生が遅れることがあります。

スポンサーリンク

検証環境

検証に使用した環境/ライブラリを次に記載します。

  • Java
    • バージョン:11
  • Gradle
    • バージョン:7.0
  • Gradle Shadow Plugin
    • バージョン:7.0.0
  • SQLite
    • バージョン:3.34.0
  • H2Database
    • バージョン:1.4.200

「SQLite」、「H2Database」は、複数JDBCの環境を確認するための検証用ライブラリとして使用しています。「Oracle」、「MySQL」などのJDBCを使用している場合でも同じ問題が発生します。

原因

原因については、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

ファイル内容は例になります。SQLite、または、H2Databaseのどちらかの内容が設定されます。

複数JDBCを指定している場合は、次のようにそれぞれのJDBCライブラリのファイル内容をまとめたものにする必要があります。

org.sqlite.JDBC
org.h2.Driver

このようなファイル内容になるのは、「Gradle Shadow Plugin」でJARファイルを作成するときは、JARファイルをすべて展開したあとに再度まとめる動作をしているためです。

JARファイルは、ZIP形式で圧縮されたファイルのため展開することが可能です。

複数JDBCを使用している場合は、それぞれのJDBCライブラリを展開すると「META-INF/services/java.sql.Driver」ファイルが同じディレクトリ/ファイル名になります。このときに、重複したファイルは上書きされるためどちらかの設定が消えてしまいます。

解決方法

ビルドスクリプトファイルの「build.gradle」などに次の設定を追加することで、「META-INF/services」ファイルに対してのは、上書きではなくマージする動作に変更することができます。

shadowJar {
  mergeServiceFiles()
}
Controlling JAR Content Merging

まとめ

複数JDBCを使用しているアプリケーションで「Gradle Shadow Plugin」を使用して1つのJARファイルを作成したときに、JDBCドライバの登録に失敗する原因と解決方法を紹介しました。