52885


既存のjdbcの挙動を変えたくて、独自のラッパーjdbcを作成しているのですが、Mavenでjarを作成する際に META-
INF/services/java.sql.Driverファイルが既存のjdbcパッケージに入ってるjava.sql.Driverファイルで上書きされてしまいます。  
これを防ぐ手立てはあるのでしょうか？

今回作成するjdbcの呼び出し側は改変不可能なアプリケーションのため、Class.forNameで自作クラスを指定できません。jdbc
ver4.0の仕様上、必ず META-INF/services/java.sql.Driverファイルに自作クラスが指定されている必要があると考えています。

Maven実行後に作成されたjarファイルに対してjarコマンドでファイルの上書きを行えば期待したjdbcが作成されるのですが、できればMavenだけで完了させたいです。


CC BY-SA 4.0
2019-02-18T12:30:16.037
52853
2019-02-20T00:49:32.743
2019-02-19T14:18:38.013
32227
32227
question
java maven jdbc
jar内の一部のファイルが依存パッケージによって上書きされてしまうのを防ぎたい


一方が他方で上書きされている、というわけではなく、双方登録されている状態だと思います。

JDBCの仕様的には、次の2手段のいずれかになると思います。

1.  
システムプロパティ`jdbc.drivers`に使用する方のドライバだけ設定する。

  * [JDBC4.1 spec. 9.2.1 Loading a driver that implements java.sql.Driver](https://download.oracle.com/otn-pub/jcp/jdbc-4_1-mrel-spec/jdbc4.1-fr-spec.pdf)
  * [`DriverManager#loadInitialDrivers()`](http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/file/0a00f10abb2d/src/share/classes/java/sql/DriverManager.java#l483)

2.  
[`DriverManager#getDrivers()`](https://docs.oracle.com/javase/jp/8/docs/api/java/sql/DriverManager.html#getDrivers--)で取得したドライバ群から、使いたくないものを[`deregisterDriver`](https://docs.oracle.com/javase/jp/8/docs/api/java/sql/DriverManager.html#deregisterDriver-
java.sql.Driver-)で登録解除する。

* * *

少し古いですが、日本語の説明が次にありました:

  * [JDBCTMガイド: 入門 6.2 ドライバの選択](https://docs.oracle.com/javase/jp/1.3/guide/jdbc/spec/jdbc-spec.frame6.html#16326)

> ドライバを探すとき、JDBC は指定された URL に接続可能なドライバのうち、最初に見つかったものを使用します。

該当箇所は、ソースで言えば
[`DriverManager`クラス](https://docs.oracle.com/javase/jp/8/docs/api/java/sql/DriverManager.html)
の
[`getConnection`メソッド](http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/file/0a00f10abb2d/src/share/classes/java/sql/DriverManager.java#l579)のようです。

  * 利用するJDBCドライバは、登録されているドライバの中から、指定した`URL`によって1つ(または0)選ばれる
  * 指定した`URL`に対応するJDBCドライバが複数登録されている場合、そのうちどれになるかは決まっていない(利用者からはわからない)

* * *

1つの`URL`に対して複数のドライバが登録されているので登録解除処理など利用側に追加実装が必要になり煩雑だ、という見方であれば、接続`URL`を変更する、という方法になるでしょうか。  
(「ラッパー」としての在り方としてはこちらの方が正しいのかも…？)

* * *

「どれになるかは決まっていない(利用者からはわからない)」とはいえ、実装はロードした順で`List`に詰めて頭から確認していっているわけなので、カスタムJDBC登録時にオリジナルJDBCが登録されていたら解除してしまう、という対応もできるかもしれません。


CC BY-SA 4.0
2019-02-19T02:12:53.483
52861
2019-02-19T03:07:01.863
2019-02-19T03:07:01.863
2808
2808
52853
answer


あるMavenモジュールのリソースの一部(あるいは全部)を取り込んで新しいモジュールを作る場合、 [`maven-shade-
plugin`](http://maven.apache.org/plugins/maven-shade-plugin/examples/includes-
excludes.html)が利用できると思います。

[code]

    <dependencies>
      <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.2.5</version>
        <optional>true</optional>
      </dependency>
    </dependencies>
    
    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-shade-plugin</artifactId>
          <version>3.2.1</version>
          <executions>
            <execution>
              <phase>package</phase>
              <goals>
                <goal>shade</goal>
              </goals>
              <configuration>
                <filters>
                  <filter>
                    <artifact>org.postgresql:postgresql:*</artifact>
                    <excludes>
                      <exclude>META-INF/services/java.sql.Driver</exclude>
                    </excludes>
                  </filter>
                </filters>
              </configuration>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
    
[/code]


CC BY-SA 4.0
2019-02-20T00:49:32.743
52885
2019-02-20T00:49:32.743
2808
52853
answer