私のオフィスでは、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(
xerces.jar
)としてリリースされていましたが、1つはAPI(xml-apis.jar
)を含み、もう1つはそれらのAPIの実装を含む()の2つのjarに分割されましたxercesImpl.jar
。多くの古いMaven POMは、依然としてへの依存を宣言していxerces.jar
ます。過去のある時点で、XercesもとしてリリースされましたxmlParserAPIs.jar
。これは、一部の古いPOMも依存しています。jarをMavenリポジトリーにデプロイする人がxml-apisおよびxercesImpl jarに割り当てたバージョンは、多くの場合異なります。たとえば、どちらもXerces 2.8.0からのものであっても、xml-apisにはバージョン1.3.03が与えられ、xercesImplにはバージョン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など)は、Xercesとともに1つ以上の
/lib
フォルダで出荷されます。
問題
紛争解決
上記の理由のいくつか、またはおそらくすべてのために、多くの組織は、自分の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>
B jar
はAよりも低いバージョンですがjar
、Mavenはが異なるため、それらが同じアーティファクトであることを認識していません
groupId
。したがって、競合の解決は実行できず、両方
jar
のが解決された依存関係として含まれます。
クラスローダー地獄
上記のように、JREはJAXP RIのXercesに同梱されています。すべてのXerces Maven依存関係を<exclusion>
sまたは<provided>
、依存するサードパーティのコードは、使用しているJDKのJAXPで提供されるバージョンで動作する場合と動作しない場合があります。さらに、Xerces jarがサーブレットコンテナに同梱されており、これに対処する必要があります。これにはいくつかの選択肢があります。サーブレットのバージョンを削除して、コンテナがJAXPバージョンで実行されることを望んでいますか?サーブレットバージョンを残し、アプリケーションフレームワークがサーブレットバージョンで実行されることを望んでいますか?上記で概説した1つまたは2つの未解決の競合が製品に侵入した場合(大規模な組織で起こりやすい)、クラスローダーの地獄にすぐに気づき、実行時にクラスローダーが選択しているXercesのバージョンと、そのバージョンかどうかを疑問に思います。 WindowsとLinuxで同じjarを選択します(おそらくそうではありません)。
ソリューション?
私たちは、全てのXerces Mavenの依存関係をマーキングしようとした<provided>
かのように<exclusion>
アーティファクトが非常に多くの別名(持っていることを考えると(特に大規模なチームで)が、これは強制することは困難であるxml-apis
、xerces
、xercesImpl
、xmlParserAPIs
、など)。さらに、サードパーティのlibs / frameworksは、JAXPバージョンまたはサーブレットコンテナによって提供されるバージョンでは実行できない場合があります。
Mavenでこの問題にどのように対処すればよいでしょうか?依存関係をこのように細かく制御してから、階層型クラスローディングに依存する必要がありますか?すべてのXerces依存関係をグローバルに除外し、すべてのフレームワーク/ライブラリに強制的にJAXPバージョンを使用させる方法はありますか?
更新:Joshua Spiewakが、XercesビルドスクリプトのパッチバージョンをXERCESJ-1454にアップロードしました。これにより、Maven Centralへのアップロードが可能になります。この問題に投票/監視/貢献し、この問題を一度だけ修正しましょう。