私のオフィスでは、Xerces という言葉に言及するだけで、開発者の殺意を掻き立てるのに十分です。SO に関する他の Xerces の質問をざっと見てみると、ほぼすべての Maven ユーザーがこの問題に「触れた」ことがあることがわかります。残念ながら、この問題を理解するには、Xerces の歴史について少し知識が必要です...
歴史
Xerces は、Java エコシステムで最も広く使用されている XML パーサーです。Java で記述されたほぼすべてのライブラリまたはフレームワークは、Xerces をある程度 (直接ではないにしても、推移的に) 使用します。
公式バイナリに含まれる Xerces jar は、今日までバージョン管理されていません。たとえば、Xerces 2.11.0 実装 jar の名前は
xercesImpl.jar
ではなく、xercesImpl-2.11.0.jar
.Xerces チームは Mavenを使用していません。つまり、公式リリースをMaven Centralにアップロードしていません。
Xerces は以前は単一の jar としてリリースされていました( ) が、API を含むもの ( ) とそれらの API の実装を含むもの( )
xerces.jar
の 2 つの jar に分割されました。古い Maven POM の多くは、依然として への依存関係を宣言しています。過去のある時点で、Xerces は としてもリリースされ、一部の古い POM も依存しています。xml-apis.jar
xercesImpl.jar
xerces.jar
xmlParserAPIs.jar
jar を Maven リポジトリーにデプロイする人によって xml-apis および xercesImpl jar に割り当てられるバージョンは、多くの場合、異なります。たとえば、xml-apis にはバージョン 1.3.03 が指定され、xercesImpl にはバージョン 2.8.0 が指定される場合がありますが、どちらも Xerces 2.8.0 のものです。これは、xml-apis jar に、それが実装する仕様のバージョンのタグを付けることがよくあるためです。ここには、非常に素晴らしいが不完全な内訳があります。
さらに複雑なことに、Xerces は、JRE に含まれる Java API for XML Processing (JAXP) のリファレンス実装で使用される XML パーサーです。実装クラスは
com.sun.*
名前空間の下に再パッケージ化されているため、一部の JRE では使用できない可能性があるため、直接アクセスするのは危険です。ただし、すべての Xerces 機能がjava.*
およびjavax.*
API を介して公開されているわけではありません。たとえば、Xerces のシリアル化を公開する API はありません。さらに混乱を招くのは、ほとんどすべてのサーブレット コンテナー (JBoss、Jetty、Glassfish、Tomcat など) が、1 つまたは複数の
/lib
フォルダーに Xerces と共に出荷されていることです。
問題
紛争解決
上記の理由の一部、またはすべての理由から、多くの組織は POM で Xerces のカスタム ビルドを公開および使用しています。小さなアプリケーションで Maven Central のみを使用している場合、これは実際には問題になりませんが、Artifactory または Nexus が複数のリポジトリ (JBoss、Hibernate など) をプロキシしているエンタープライズ ソフトウェアではすぐに問題になります。
たとえば、組織 A は次のxml-apis
ように公開できます。
<groupId>org.apache.xerces</groupId>
<artifactId>xml-apis</artifactId>
<version>2.9.1</version>
一方、組織 B は次のように同じものを発行する場合がありjar
ます。
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.3.04</version>
Bjar
は A よりも下位のバージョンですがjar
、 Maven は が異なるため、それらが同じアーティファクトであることを知りません
groupId
。したがって、競合の解決を実行できず、両方
jar
の が解決された依存関係として含まれます。
クラスローダー地獄
前述のように、JRE は JAXP RI の Xerces に同梱されています。すべての Xerces Maven 依存関係を<exclusion>
s または asとしてマークすると便利ですが、<provided>
依存しているサードパーティのコードは、使用している JDK の JAXP で提供されているバージョンで動作する場合と動作しない場合があります。さらに、競合するサーブレット コンテナに Xerces jar が同梱されています。これにより、多くの選択肢が残されます。サーブレット バージョンを削除し、コンテナーが JAXP バージョンで実行されることを望みますか? サーブレット バージョンを残し、アプリケーション フレームワークがサーブレット バージョンで実行されることを期待する方がよいでしょうか? 上記で概説した未解決の競合の 1 つまたは 2 つが製品に紛れ込んだ場合 (大規模な組織では発生しやすい)、すぐにクラスローダー地獄に陥り、クラスローダーが実行時に Xerces のどのバージョンを選択しているのか、またそれがWindowsとLinuxで同じjarを選択します(おそらくそうではありません)。
ソリューション?
<provided>
すべての Xerces Maven 依存関係をまたは としてマークしようとしまし<exclusion>
たが、成果物に非常に多くのエイリアス ( xml-apis
、xerces
、xercesImpl
、xmlParserAPIs
など) があるため、これを強制するのは (特に大規模なチームでは) 困難です。さらに、サードパーティのライブラリ/フレームワークは、JAXP バージョンまたはサーブレット コンテナーによって提供されるバージョンでは実行できない場合があります。
Maven でこの問題に対処するにはどうすればよいでしょうか? 依存関係をそのようにきめ細かく制御してから、階層化されたクラスローディングに頼る必要がありますか? すべての Xerces 依存関係をグローバルに除外し、すべてのフレームワーク/ライブラリで JAXP バージョンを使用するように強制する方法はありますか?
更新: Joshua Spiewak は、Xerces ビルド スクリプトのパッチを適用したバージョンをXERCESJ-1454にアップロードしました。これにより、Maven Central へのアップロードが可能になります。この問題に投票/監視/貢献して、この問題を完全に修正しましょう。