11
Java / Mavenで「Xerces hell」を処理しますか?
私のオフィスでは、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 …