web-dev-qa-db-ja.com

使用するJAXBコンテキストファクトリ初期化クラスを設定します

プロジェクト(Websphere8.5で実行されているJavaEEベース)を更新して、社内フレームワークの新しいリリース(および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構成の可能性についてすべて読むつもりだと言う必要はありませんが、何がうまくいかなかったのかについて最初の洞察を持っているか、そのリソースを手伝ってくれるなら(それは私が探さなければならない実際のファイルですか?)たくさん。どうもありがとう!

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

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

実際(少し驚いていますが)フレームワークには、カスタマイズされたeclipselink-2.4.1-.jarがEAR内にあり、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」リソースの存在をさまざまな場所で検索します。これらの場所のすべてが使用するコンテキストファクトリを表示しない場合、クラス自体にハードコードされているdeaultファクトリがロードされています。

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アプリケーションがエラーにつながるという事実の間に)、一般的な答えはありませんが、定義されたJAXBContextFactoryがクラスパスに存在する必要があります(なんて不思議です...)。リソースが不足しているため(実際の原因です)、または以下の回答に従った定義を含む上記のプロパティファイルのいずれかで間違ったJAXBContextFactoryが定義されているため、ClassNotFoundエラーが発生します。

素晴らしいコメントとサポートに感謝します。本当に感謝しています!

7
JBA

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

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

詳細情報

5
bdoughan

もう1つの迅速で汚い解決策(実際には回避策)は、MavenビルドにJAXB実装を明示的に含めることです。例えば

<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クラスローダーが最後に親に設定されている場合にのみ機能します。

3
schnatterer