2017-10-03 5 views
0

osgi環境(Liferay DXP)でJAXB 2.2.11を使用しようとしています。 JAXBContextの作成に問題があります。 thisthisのような研究中に発見されたいくつかの他のソースに基づいて、私はosgiコンテナで、JAXBがコンテキストをインスタンス化するための正しいクラスローダを提供する必要があると判断しました。私はcontextがヌルでなければならないことがわかりますosgi(Liferay DXP)でJAXB 2.2.11を使用する方法

Caused by: java.lang.NullPointerException 
    at javax.xml.bind.ContextFinder.handleClassCastException(ContextFinder.java:129) 
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:201) 
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:146) 
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:371) 
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:446) 
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:409) 

ContextFinderのソースを見てみると:

ClassLoader cl package.with.jaxb.objects.ObjectFactory.class.getClassLoader(); JAXBContext jc = JAXBContext.newInstance("package.with.jaxb.objects ", cl);

このコードは、次のスタックトレースとnullポインタ例外が発生します。だから私は、このようなコードを持っていますライン129上:

throw handleClassCastException(context.getClass(), JAXBContext.class);

私はperhap思いました問題は私のモジュールがjaxb-api 2.2.11に依存していたことですが、jaxb-implクラスは実行時にrt.jarによって提供され、Liferay DXPがJDK 1.8上で動作するため、おそらく2.2.11より新しいです。この問題を回避するために、jaxb-impl.jar 2.2.11をosgiモジュールの依存関係として含めてみました。jaxb-api & jaxb-implバージョンが一致すると考えています。その後、次のエラーが発生し、上記と同じコードを使用してJAXBContentを作成しようとしている:このメッセージのルックスによって

ClassCastException: attempting to cast jar:file:/C:/Program%20Files/Java/jdk1.8.0_144/jre/lib/rt.jar!/javax/xml/bind/JAXBContext.class to bundleresource://623.fwk616113009:13/javax/xml/bind/JAXBContext.class. Please make sure that you are specifying the proper ClassLoader. 

、インスタンス化取得されたJAXBContextを経由してロードされたJAXBContextのバージョンからですrt.jar。私のモジュールにjaxb-impl.jarを組み込んで使用したので、私のモジュールのクラスローダーによってロードされたJAXBContextのバージョンが期待され、私のモジュールのクラスローダーを指定しましたので、これは私にとって非常に混乱しています。 JAXBContext.newInstanceへの私の呼び出し。誰かがjaxb 2.2.11をosgiコンテナで動作させる方法についていくつかの光を当てることができますか?

* JAXBコードは実際にjaxb 2.2.11を必要とするサードパーティ製のジャーにあるため、私のモジュールで使用されているjaxb-apiのバージョンをアップグレードできませんのでご注意ください。(サードパーティのジャーをテストJAXBコードを書くことによって、今の方程式です)。

答えて

0

大規模な調査の結果、次の解決策が見つかりました。 this postの受け入れられた答えで示唆されているようにバンドルクラスローダーを渡すように思えたので、私はそれを試みたときになぜNullPointerExceptionを取得したのかを理解する道をたどった。慎重にNullPointerExceptionのスタックトレースを追跡するためにJAXB-APIのソースコード上で見た後、私はJAXB-APIコードがあるため(classLoaderは私のバンドルのクラスローダである

classLoader.loadClass("com.sun.xml.internal.bind.v2.ContextFactory")

のようなものをしていること見ることができましたこれは私が渡したものです)、ContextFactoryは実際にはjaxb-implのクラスであり、ブートストラップクラスローダーによってロードされます。私の バンドルのクラスローダーは、ブートストラップクラスローダーによってロードされたクラスを見ることができないため、問題がどこにあるのでしょうか。クラスローダーがosgiでどのように動作するかに慣れていないので、これはしばらく私を投げ捨てました。私は誤って、私はデベロップメントがある場所のWebアプリケーションクラスの読み込みに慣れているので、ブートストラップクラスローダによってロードされるクラスが可視であると考えていました。 osgiクラスローダー では、互いに完全に分離されています。エクスポートされたオブジェクトのみが表示されます。私が見つけた問題を回避するにはsomehelpfulpostsは類似の問題について話しています。 osgiには、ブートストラップクラスローダー経由で常にロードされるクラス/パッケージのリストを指定できるコンセプト があります。 JAXBContextのを取得するためのコードを呼び出す前に、あなたのバンドルのクラスローダにスレッドのクラスローダの切り替え)

1::だから最終的な結果は、2つのステップである

ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); 

try {   
    // ObjectFactory here is in the same package as my classes to be marshalled 
    ClassLoader objectFactoryClassLoader = ObjectFactory.class.getClassLoader();    
    Thread.currentThread().setContextClassLoader(objectFactoryClassLoader); 
    // JAXB code goes here 
} finally { 
    Thread.currentThread().setContextClassLoader(currentClassLoader); 
} 

2)ブートを使用してロードするパッケージを指定します委任メカニズムこのリストには、ロードする必要があるクラスの推移的な依存関係を含める必要があります。私の場合、私はLiferayを使用しているので、リスト はLiferayに固有であり、portal-ext.properties構成ファイルに入っています。

module.framework.properties.org.osgi.framework.bootdelegation=\ 
    __redirected,\ 
    com.liferay.aspectj,\ 
    com.liferay.aspectj.*,\ 
    com.liferay.portal.servlet.delegate,\ 
    com.liferay.portal.servlet.delegate*,\ 
    com.sun.ccpp,\ 
    com.sun.ccpp.*,\ 
    com.sun.crypto.*,\ 
    com.sun.image.*,\ 
    com.sun.jmx.*,\ 
    com.sun.jna,\ 
    com.sun.jndi.*,\ 
    com.sun.mail.*,\ 
    com.sun.management.*,\ 
    com.sun.media.*,\ 
    com.sun.msv.*,\ 
    com.sun.org.*,\ 
    com.sun.syndication,\ 
    com.sun.tools.*,\ 
    com.sun.xml.*,\ 
    com.yourkit.*,\ 
    org.eclipse.persistence.internal.jaxb,\ 
    org.eclipse.persistence.internal.jaxb.*,\ 
    javax.xml.*,\ 
    sun.* 

参考リンク:

Why can't JAXB find my jaxb.index when running inside Apache Felix?

What is the difference between bootdelegation and DynamicImport-Package in osgi

https://web.liferay.com/web/user.26526/blog/-/blogs/liferay-dxp-and-weblogic-

https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/bundle-classloading-flow

幸いにも私は、誰かが私のためにほとんどの作業を行っていた this postを見つけました

http://apache-felix.18485.x6.nabble.com/Classloading-for-JAXB-td4834670.html

0

どのように行うべきかを知る最も良い場所はApache Karafです。 JAXB-APIバンドルはインストールされません。代わりに、lib/endorsedディレクトリ内にorg.apache.servicemix.specs.jaxb-api-2.2-2.7.0.jarが使用されます。

この方法では、rt.jarで提供されるJAXB-APIを使用しません。実装のために

- それはJAXBバンドルのServiceMixのバージョンを使用するのが最善です:

  • org.apache.servicemix.bundles:org.apache.servicemix.bundles.jaxb-のimpl:2.2.11_1
  • 組織を.apache.servicemix.bundles:org.apache.servicemix.bundles.jaxb-xjc:2.2.11_1
+0

Grzegorzさんにお返事ありがとうございます。残念ながら、私の記事の最後で述べたように、JAXBコードはサードパーティのライブラリにあるので、実際にはどのように記述されているのかはわかりません.STIX(https://github.com/STIXProject/java) -stix)、STIX libはjaxb-apiを使用しています。 – clav

関連する問題