8

私は Jaybird JDBC ドライバーを開発していますが、今日、Jaybird がコンポーネントの一部をロードする方法と、この場合は NetBeans がクラスロードを制限する方法に関連する問題 ( JDBC-325休止状態で Jaybird を構成する方法) に遭遇しました。

この問題は、Jaybird がエントリを使用してそれ自体の一部をロードする方法META-INF/servicesと、Hibernate ウィザード用に NetBeans によって使用されるクラスローダーがそれらのファイルを明示的に無視することに関連しています (以下の詳細を参照)。

Jaybird 実装の一部であるハードコードされたプラグインのリストを (また) ロードしようとするか、定義を別の場所に移動することで、この問題を回避できます。

META-INF/servicesしかし、Jaybird のように内部目的で使用するのは奇妙 (または間違っている) かどうか疑問に思っていましたか?

NetBeans が のロードを除外する理由もわかりませんMETA-INF/servicesDrewのコメントは、 NetBeans がドライバーのロード時のエラーを解決するためにそれを使用したことを示しているようです (この問題を参照)。

問題の詳細

Jaybird は、Type 4 プロトコル、カスタムの Type 4 Open Office プロトコル、Type 2 埋め込み (ネイティブ) プロトコル、Type 2 ネイティブ クライアント プロトコルなど、サポートされているプロトコルのプラグインを使用します。また、サードパーティがこれを使用して、Oracle 固有の構文を Firebird 構文に変換するドライバーを提供したこともあると思います。

これらのプラグインはすべて にリストされMETA-INF/services/org.firebirdsql.gds.impl.GDSFactoryPlugin、同様の方法でロードされますjava.util.ServiceLoader(現在の 2.2.x ドライバーは Java 5 をサポートしているため、実際には を使用しませんServiceLoader)。今後のバージョンでは、サポートされている接続エンコーディングと (ワイヤ) プロトコル定義にもこれを使用する予定でした。これにより、「カスタム」エンコーディング定義 (サポートされているエンコーディングを拡張する、または別のエンコーディングを使用するなど) または異なるプロトコルの実装 (トラブルシューティング、カスタム ロギングなど) が可能になります。

ここで実際の問題は、Netbeans ウィザードのHibernate Mapping Files and POJOs from Databaseがカスタム クラスローダー ( org.netbeans.modules.hibernate.util.CustomClassLoader) を使用し、このクラスローダーが のファイルを無視することですMETA-INF/services。問題があるのはこのウィザードだけであることに注意してください。Netbeans 自体は問題なくドライバを使用できます。

コード無視META-INF/services:

@Override
public URL findResource(String name) {
    return name.startsWith("META-INF/services") ? null : super.findResource(name); //NOI18N
}

@Override
public Enumeration<URL> findResources(String name) throws IOException {
    if (name.startsWith("META-INF/services")) { //NOI18N
        return Collections.enumeration(Collections.<URL>emptyList());
    } else {
        return super.findResources(name);
    }
}

これにより、プラグインが検出されず、ドライバにプロトコルがないNullPointerExceptionため、接続が作成されないため、内部 Netbeans が発生します。

4

1 に答える 1

3

Netbeans チームのバグ修正は間違っていたと思います。特定のディレクトリ内のファイルを特に理由もなく無視するのはひどいことです。主に META-INF/services のような重要なディレクトリにあります。それはセキュリティの問題でも、そのようなものでもありません。彼らは、他の人が書いた悪いコードから保護しているだけです。彼らはそれを行うために他の方法を使用する必要があります。あなたのような人がこの問題の原因を見つけるのにどれだけの時間を費やしたか想像できます!

Service Provider API が公開されている理由は 1 つあります。これは、コードの結合を少なくする優れた方法であり、うまく機能します! 私はできる限り常にそれを使用し、すべての人に使用することをお勧めします.

また、Java API は、サービス プロバイダー メカニズムを使用した JDBC ドライバーの追加を明確にサポートしています。

DriverManager メソッド getConnection および getDrivers が拡張され、Java Standard Edition Service Provider メカニズムがサポートされるようになりました。JDBC 4.0 ドライバーには、ファイル META-INF/services/java.sql.Driver が含まれている必要があります。

また、JDBC 4.0 (2007) 以降に作成されたドライバーは、そのメカニズムを介して入り口を提供することが期待されているとも述べています。

ただし、フォールバックを提供する必要がある/提供できないとは述べていません。他のドライバーがそうしている必要があります。そうしないと、同じ問題が発生します。しかし、おそらく他の理由 (JDBC API の古いバージョンをサポートするため) でそうしています。

したがって、あなたは正しいことをしており、その特定のユースケースをサポートすることがあなたにとって非常に重要である場合は、そのコードをフォールバックとして維持する必要があります. それ以外の場合は、コードを削除し、いくつかのドキュメントを追加して、人々がそれを回避できるようにします。

于 2013-12-24T00:23:20.470 に答える