9

プロジェクト (Websphere 8.5 で実行される Java EE ベース) を更新して、社内フレームワーク (および 2.x ではなく Ejb 3.x デプロイメント記述子) の新しいリリースを使用するようにしました。それ以来、私の統合テストは次の例外で失敗します:

 [java.lang.ClassNotFoundException: com.ibm.xml.xlxp2.jaxb.JAXBContextFactory]

以前のフレームワーク リリースでアプリケーションをビルドでき、すべて正常に動作します。デバッグ中に、ContextFinder (javax.xml.bind) 内に 2 つの異なる動作があることに気付きました。

  1. 以前のバージョン (すべて正常に動作): どの場所でもファクトリ クラスが呼び出されないため、com.sun.xml.internal.bind.v2.ContextFactory であるデフォルトのファクトリ クラスがロードされます (クラス内で文字列定数として定義されます)。 .

  2. アップグレードされたバージョン (ClassNotFound): リソース "META-INF/services/javax.xml.bind.JAXBContext" が正常にロードされ、最初の行が読み取られると、ContextFinder は "com.ibm.xml.xlxp2.jaxb. JAXBContextFactory" がエラーの原因です。

2 つの質問があります。

  1. そのリソースはどのようなものですか?EAR 内には 2 つの WAR があり、これら 2 つのいずれにも META-INF ディレクトリにフォルダ サービスが含まれていないためです。

  2. そうでなければ、その値はどこから来るのでしょうか? filediff で新しいプロパティ ファイルや変更されたプロパティ ファイルが表示されなかったからです。

JAXB 構成の可能性についてすべて読むつもりであると言う必要はありませんが、何がうまくいかなかったのか、またはそのリソースについて私を助けてくれる最初の洞察があれば (それは私が探す必要がある実際のファイルですか?) id に感謝します多く。どうもありがとう!

編集(コメント入力/質問による):

好奇心から、あなたのフレームワークには JAXB JAR が含まれていますか? 古いバージョンのフレームワークには jaxb.properties が含まれていましたか?

確かに (私は少し驚いています)、フレームワークには EAR 内にカスタマイズされた eclipselink-2.4.1-.jar があり、JAXB 実装と、両方のバージョンで次のエントリを示す jaxb.properties ファイルが含まれています (ファクトリと例外をスローするもの):

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

これは現在の問題とは何の関係もないと思います。これは、jar が両方の EAR (実行されるものと期待されるもの) でまったく同じままだったためです。

フレームワークの古いバージョンが com.sun 実装を選択していた理由も明確ではありません

JAXBContextFactory の初期化を担当するクラス javax.xml.bind.ContextFinder があります。このクラスは、jaxb.properties ファイルまたは「javax.xml.bind.JAXBContext」リソースの存在をさまざまな場所で検索します。これらのすべての場所で使用するコンテキスト ファクトリが表示されない場合は、クラス自体にハードコードされたデフォルト ファクトリがロードされています。

private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory";

今私の問題に戻ります:

以前のバージョンのフレームワーク (および EJB 2.x デプロイメント記述子) でビルドすると、すべて正常に動作します)。デバッグ中に、構成が見つからず、上記のデフォルトのファクトリがロードされていることがわかります。

新しいバージョンのフレームワーク (およびデプロイ可能な EJB 3.x デプロイメント記述子) でビルドすると、テストケースのみが失敗しますが、残りの機能は機能します (Web サービスにリクエストを送信でき、エラーをトリガーしないなど)。デバッグ中に、構成が見つかったことがわかります。このリソースの名前は「META-INF/services/javax.xml.bind.JAXBContext」です。このリソースがどのようにして「com.ibm.xml.xlxp2.jaxb.JAXBContextFactory」をロードしようとし、ClassNotFoundException をスローするかを示す最も重要な行を以下に示します。これは、前述の javax.xml.bind.ContextFinder クラスの単純化されたソースです。

URL resourceURL = ClassLoader.getSystemResource("META-INF/services/javax.xml.bind.JAXBContext");

BufferedReader r = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "UTF-8"));

String factoryClassName = r.readLine().trim();  

フィールド factoryClassName の値は「com.ibm.xml.xlxp2.jaxb.JAXBContextFactory」になりました

これは非常に大きな質問になっているので、報奨金も追加します :) 一日中これに取り組み、ニュースがある場合はお知らせします。

更新/解決策

この質問は解決されました。元の問題は、エラーが発生したコンポーネントで使用できない JAXBFactory の定義を含む、カスタマイズされた Eclipse リンク jar の更新バージョンを 1 つの依存関係が使用する、複雑にビルドされたマルチ モデル Maven プロジェクトの構成ミスが原因で発生しました。ほとんどの場合、JAXB コンテキスト ファクトリの設定は、同じ定義を含む jaxb.propertie ファイルまたは JAXBContext ファイルで構成されます。適切な JAXBContextFactory の詳細なロード プロセスは、javax.xml.bind.ContextFinder で行われます。

エラーはまだ解決されておらず (4 つ以上の主要な EE/SE アプリケーションがエラーにつながるという事実の間)、一般的な答えはありませんが、定義された JAXBContextFactorys がクラスパスに存在する必要があります (すごい不思議です...)。リソースが不足している(これが実際の原因です)か、以下の回答による定義を含む上記のプロパティファイルのいずれかで間違った JAXBContextFactory が定義されているため、その ClassNotFound エラーが発生します。

素晴らしいコメントとサポートをありがとう、本当に感謝しています!

4

2 に答える 2

6

jaxb.propertiesドメイン モデルと同じパッケージにファイルを含めて、使用する JAXB ( JSR-222 ) 実装を指定できます。たとえば、EclipseLink MOXyを JAXB プロバイダーとして指定する場合は、次のようになります。

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

詳細については

于 2013-11-01T17:14:12.293 に答える
4

私にとってうまくいったもう1つの手っ取り早い解決策(実際には回避策)は、JAXB実装をmavenビルドに明示的に含めることです。例えば

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.2.7</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.2.7</version>
</dependency>

JAXB は明らかに各 JRE >= バージョン 6 の一部であるため、これによりビルドに不要な依存関係が追加されることに注意してください。

ほとんどの場合、これは WAS クラスローダーが最後に親に設定されている場合にのみ機能します。

于 2014-01-14T14:02:27.007 に答える