パッケージ内で、インデックスを作成する必要があります。それでも、私が電話するとき
_JAXBContext jc = JAXBContext.newInstance("my.package.name");
_
私はそれを言ってJAXBExceptionを取得します
「my.package.name」にObjectFactory.classまたはjaxb.indexが含まれていません
両方が含まれていますが。
うまくいくが、私が望んでいるものではない
_JAXBContext jc = JAXBContext.newInstance(my.package.name.SomeClass.class);
_
他のさまざまな人々からのこの質問は、かなりのメーリングリストやフォーラムに掲載されていますが、回答は得られていないようです。
これをOpenJDK 6で実行しているので、ソースパッケージを取得し、デバッガーをライブラリにステップインしました。 jaxb.propertiesを検索することから開始し、システムプロパティを検索し、見つからない場合、com.Sun.internal.xml.bind.v2.ContextFactoryを使用してデフォルトコンテキストを作成しようとします。そこでは、例外がスローされます(ContextFactor.createContext(String ClassLoader, Map)
内)が、ソースがここにないため、何が起こっているのかわかりません。
[〜#〜] eta [〜#〜]:
ContentFactoryのソースコードから判断すると、 here が見つかりました。これはおそらく、意図したとおりに動作しないコードの一部です。
_/**
* Look for jaxb.index file in the specified package and load it's contents
*
* @param pkg package name to search in
* @param classLoader ClassLoader to search in
* @return a List of Class objects to load, null if there weren't any
* @throws IOException if there is an error reading the index file
* @throws JAXBException if there are any errors in the index file
*/
private static List<Class> loadIndexedClasses(String pkg, ClassLoader classLoader) throws IOException, JAXBException {
final String resource = pkg.replace('.', '/') + "/jaxb.index";
final InputStream resourceAsStream = classLoader.getResourceAsStream(resource);
if (resourceAsStream == null) {
return null;
}
_
私の previousexperience から、これが実行されているOSGiコンテナのクラスローディングメカニズムに関係していると推測しています。残念ながら、私はまだ少しですここで私の深さから。
OK、これはかなり掘り下げましたが、答えはそれほど驚くことではなく、それほど複雑でもありません:
JAXBは、デフォルトでnewInstance(String)
が現在のスレッドのクラスローダー(Thread.getContextClassLoader()
によって返される)を使用するため、jaxb.indexを見つけることができません。 OSGiバンドルとフレームワークのスレッドには別個のクラスローダーがあるため、Felix内では機能しません。
解決策は、どこかから適切なクラスローダーを取得し、newInstance(String, ClassLoader)
を使用することです。 jaxb.index
を含むパッケージのクラスの1つから適切なクラスローダーを取得しました。柔軟性の理由から賢明な選択はおそらくObjectFactory
です。
ClassLoader cl = my.package.name.ObjectFactory.class.getClassLoader();
JAXBContext jc = JAXBContext.newInstance("my.package.name", cl);
Bundle
インスタンスが使用しているクラスローダーを取得することもできたかもしれませんが、その方法がわかりませんでした。上記の解決策は安全だと思われます。
私が取り組んでいるプロジェクトでも同様の問題に直面しました。 http://jaxb.Java.net/faq/index.html#classloader を読んだ後、JAXBContextがjaxb.indexを含むパッケージを見つけることができないことに気付きました。
これをできる限り明確にしようとします。
我々は持っています
Bundle A
-- com.a
A.Java
aMethod()
{
B.bMethod("com.c.C");
}
MANIFEST.MF
Import-Package: com.b, com.c
Bundle B
-- com.b
B.Java
bmethod(String className)
{
Class clazz = Class.forName(className);
}
Export-Package: com.b
Bundle C
-- com.c
C.Java
c()
{
System.out.println("hello i am C");
}
Export-Package: com.c
関連する[〜#〜] jaxb [〜#〜]。 クラスBはJAXBContext、bMethodはnewInstance()
OSGiパッケージの制限に精通している場合、Bundle Bがパッケージをインポートしていないことを非常に明確にする必要がありますcom.c ie class C is not visible to class Bしたがって、Cをインスタンス化できません。
解決策は、ClassLoaderをbMethodに渡すことです。このClassLoaderはcom.cをインポートしているバンドルから取得する必要があります。この場合、A.class.getClassLoader()を渡すことができますバンドルAはcom.cをインポートしています
これがお役に立てば幸いです。
同じ問題について、パッケージを手動でインポートすることで解決しました。
プロジェクトでmavenを使用している場合は、次のライブラリを使用します。
<dependency>
<groupId>com.Sun.xml.bind</groupId>
<artifactId>jaxb-osgi</artifactId>
<version>2.2.7</version>
</dependency>
Glasfishサーバー用に作成されていますが、Tomcatでも動作します(チェック済み)。このライブラリを使用すると、OSGIバンドルでJAXBを簡単に使用できます。
私はちょうどこの問題に遭遇しました。私にとっての解決策は、Oracleの代わりにIBMのJREを使用することでした。 JAXB実装は、その中でよりOSGIフレンドリーであるようです。
この問題を引き起こす別のシナリオがあるかもしれません。
Jaxb.indexまたはobjectFactory.Javaを含むパッケージをエクスポートするバンドルをインストールして開始するとき
次に、クラスをインポートするバンドルが停止していること、または正しいパッケージ名を指していることを確認してください。
また、pom.xmlのexportおよびimportステートメントを確認します
Servicemix(karaf)osgiコンテナーで同様の問題に直面
ObjectFactory
を含む生成されたクラスのパッケージを、バンドル定義の<Private-Package>
部分に加えて、org.jvnet.jaxb2_commons.*
を追加することで、これを正常に解決しました。
私にとって問題は、私が開発したモジュールに関係のない単体テストがpom.xmlに私のモジュールに依存していないことでした。 UTは、共有構成ファイルからパッケージリストを取得するため、モジュールをまだ認識しています。
UTを実行すると、新しいモジュールがコンパイルされなかったため、ObjectFactory.Javaが生成されなかったため、モジュールをコンパイルしたときにObjectFactoryを確認できたにもかかわらず、エラーが発生しました.Java
次の依存関係を追加しました。
<dependency>
<groupId>com.myCompany</groupId>
<artifactId>my-module-name</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
編集2:
かつて、アプリケーションで同様の奇妙なクラス読み込みの問題が発生しました。通常のアプリケーションとして実行した場合、すべては問題ありませんでしたが、Windowsサービスとして起動すると、ClassNotFoundExceptionsで失敗し始めました。分析の結果、スレッドのクラスローダーはなんとなくnullであることがわかりました。 SystemClassLoaderをスレッドに設定することで問題を解決しました。
// ...
thread.setContextClassLoader(ClassLoader.getSystemClassLoader());
thread.start();
// ...
ただし、コンテナがこの種の変更を許可しているかどうかはわかりません。