2012-02-14 16 views
1

この質問はBounty!この問題を解決する最初の答えが勝ちます。OSGI CXFシングルトンクラスローディングの問題

私は最近、OSGIのバンドルが100%分離されていないことを発見しました。特に、バンドルがシングルトンを持つ共通バンドルを共有する場合、2つの無関係なバンドルがシングルトンを上書きする可能性があります。この問題は、CXFライブラリで明らかになりました。

私たちはバンドルA、B、および共有バンドルCXFをすべてFuseESB ServiceMix(osgiプラットフォーム)に持っています。 CXFのBusクラスはシングルトンであり、OSGIがバンドルごとに単一のクラスローダーを持つために、CXFを使用するバンドルごとにこのシングルトンを共有します。だから、私はバンドルAとバンドルBのために異なるバスを作ることができないようです。バンドルAはSSLを使用し、バンドルBはSSLを使用すべきではないので、私は重要です。バンドルAとバンドルBが同じServiceMix上に一緒にデプロイされなければならないという点で、バンドルAとバンドルBはお互いに何の関係もないということを考えると、これはさらに難解です。

今私は今この問題にいましたが(1〜2ヶ月)、私はさまざまな解決策をたくさん読んできました。しかし問題は、多くのソリューションでは、ソースコードを完全に制御する必要があります。この場合、私はそうしません。私が作成しているバンドルAは、CXFを使用するXenaraと呼ばれる、独自のサードパーティの非osgiライブラリを使用しています。私のコントロールの範囲を超えてビジネス上の理由から、私はこのサードパーティのライブラリを使用する必要があります。幸いにも、私はこのライブラリが使用するCXF Spring Beanファイルにアクセスできます。

私はこの問題を解決するために、バンドルAがCXFの独自のインスタンスを使用できるようにするか、少なくとも他のバンドルと共有されないCXFバスをインスタンス化できるようにする必要があると考えています。

  1. 私は、バンドルAにCXFを埋め込まれたが、残念ながらクラスローダは、クラスパスに探しての代わりに、バンドルAの外側からCXFを取得保管:ここに私が試したかと考えられてきた方法があります。バンドルAの外で検索する前にバンドルAのCXFを最初に検索する方法を決して考えませんでした。

  2. バンドルAをサービスにすることを提案しました。私はある誤解があり、シングルトンがCXFではなくAにあると人々は考えました。私はそれを試しても問題は解決しませんでした。

  3. CXFクラスをロードするためにバンドルAが別のクラスローダーを使用するように、クラスローディングをオーバーライドします。私はこれに関するロジックを完全に理解していませんが、CXFバスとhttp-conduitを作成するためにSpring Beanが使用されていることを考えると、非常に扱いにくいものになるでしょう。より良いアイデアを得るには、下の(4)を参照してください。

  4. CXFには、特定のスレッドコンテキストのCXFバスとhttpコンジットを設定する方法があります。私は本当にこのソリューションを使いたいですが、CXF Beanファイルを同等のJavaコードに変換する方法を理解できません。以下に、CXF Spring Beanファイルを示します。注このHTTPコンジットを使用してソースコードにアクセスすることはできません。なぜなら、SOAPService、wsdlなどへのアクセス権がないため、「Javaコードの使用」でthis link hereの例を使用していないからです。 ...

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> 
        <property name="searchSystemEnvironment" value="true" /> 
        <property name="ignoreUnresolvablePlaceholders" value="true" /> 
    </bean> 
    
    <cxf:bus> 
        <cxf:outInterceptors>   
         <bean class="com.xenara.messaging.security.IdentityAssertingOutInterceptor" 
           scope="singleton" /> 
        </cxf:outInterceptors> 
    
        <cxf:features> 
         <wsa:addressing xmlns:wsa="http://cxf.apache.org/ws/addressing"/> 
        </cxf:features> 
    </cxf:bus> 
    
    <http-conf:conduit name="*.http-conduit"> 
        <http-conf:client AllowChunking="false" Connection="Keep-Alive" /> 
        <http-conf:tlsClientParameters disableCNCheck="true" secureSocketProtocol="TLS"> 
         <sec:keyManagers keyPassword="${javax.net.ssl.keyStorePassword}"> 
          <sec:keyStore type="JKS" password="${javax.net.ssl.keyStorePassword}" 
                file="${javax.net.ssl.keyStore}" /> 
         </sec:keyManagers> 
         <sec:trustManagers> 
          <sec:keyStore type="JKS" password="${javax.net.ssl.trustStorePassword}" file="${javax.net.ssl.trustStore}" /> 
         </sec:trustManagers> 
         <sec:cipherSuitesFilter> 
          <sec:include>SSL_RSA_WITH_3DES_EDE_CBC_SHA</sec:include> 
          ... 
         </sec:cipherSuitesFilter> 
        </http-conf:tlsClientParameters> 
    </http-conf:conduit> 
    
+0

この問題では多くの時間が浪費され、最終的な解決策は、悲しいかな、私たちのFuseESB ServiceMix環境の外でプログラムを実行し、ActiveMQを通じてFuseESB Servicemixと話すことでした。 – Thirlan

答えて

2

これは私にとってのOSGiの基本的なpremisseように聞こえる:アイソレーションが提供されていますが、定期的なOSGiの中で何をすることができますの多くを行うことができます。クラスの静的メンバーを変更したり、そのクラスをすべて共有したり(おそらくA、B、Cがそれをインポートします)、他の人は気付くでしょう。

ほとんどの状況では、静的なクラス状態を使用しないことをお勧めします。これは、他のバンドルのために何かを混乱させるためです。

あなたの状況では、バンドルAは実際の使用がフレームワークで共有されていないライブラリです。ライブラリをパッケージ化してください。のバンドルを使用してください。実際のアイソレーションが必要な場合はオーバーヘッドについて心配する必要はありません。

このような状況は、Servicemixとはまったく関係がありません。基本的なJavaです。つまり、同じクラスについて話していて、誰かが静的なプロパティを変更すると、他の人が気付くでしょう。このような状況があなたを混乱させる場合は、OSGiのクラスローディングと共有メカニズムについて少しお読みください。

+0

私はJavaスタティックがどのように動作するのか知っています。私はServicemixで最初に作業したときに、バンドルが独自のコンテキストにあって、他のコンテキストとは完全に分離しているという印象を受けました。 Servicemixフレームワークがすべてを特別な方法で一緒に接着していたことを望んで考えました。 – Thirlan

+0

私はこれを試しましたが、不可能でした。私が瓶を埋め込むとすぐに、それはあらゆる種類の他のパッケージを求め始めました。私たちはMavenを使ってOSGIバンドルを構築し管理し、マニフェストファイルのインポートを3倍にし、Beanシェルパッケージからjunitに至るまで、あらゆる種類のパッケージを要求し始めました。サービス。私は時間があるときにそれを試してみます。 – Thirlan

+0

本当に、パッケージングの「巨大ライブラリ」は、しばしばやっかいな作業です。これについてのもう一つの最近の質問がありますが、これはあなたにいくつかの助けを与えるかもしれません。 http://stackoverflow.com/questions/9292642/problems-with-maven-built-osgi-including-dependencies/9292749#9292749実際にそれをサービスにすることは、ライブラリの種類に応じて別の可能性があります。 –

2

あなたが直面している問題は、かなり不可欠で基本的です。サポートしているライブラリCXFには静的な状態がありますが、CXFを使用するライブラリの共有インスタンスが必要です。共有ライブラリを変更することはできません(サイズが大きいため)、CXF(クローズドソース?)を変更することはできません。これらの共有ライブラリFooとBarを呼び出しましょう。

では、次のクラスがあるとします。

CXF#1 
Foo#1, using CXF#1 
Bar#1, using CXF#1 
WebApp#1, using Foo#1 and Bar#1 

私が正しく理解していれば、あなたは今、別のアプリケーションが同じ基本ライブラリCXF#1を使用せずに、fooとbarの同じインスタンスを使用します。これは次のような状況になります。

CXF#2 
CXF#1 
Foo#1, using CXF#1 when called by App#1, using CXF#2 when called by App#2 
Bar#1, using CXF#1 when called by App#1, using CXF#2 when called by App#2 
WebApp#1, using Foo#1 and Bar#1 
WebApp#2, using Foo#1 and Bar#1 

これはまったく不可能です。 OSGiではなく、Javaフレームワークでもありません。 既存のクラスを別のクラスに動的にバインドすることはできません。呼び出し元のバンドルに基づいて選択を行います。ライブラリを変更せずにこれを行うための唯一の方法は、サポートライブラリを複製することです:

CXF#2 
CXF#1 
Foo#1, using CXF#1 
Bar#1, using CXF#1 
Foo#2, using CXF#2 
Bar#2, using CXF#2 
WebApp#1, using Foo#1 and Bar#1 
WebApp#2, using Foo#2 and Bar#2 

は確かに、これは多くの努力であり、ディスク上やメモリ内のパッケージの数が爆発します。 CXFパッケージを単一のアプリケーションでしか使用できない場合、最も論理的な解決策は、パッケージを複製し、使用するあらゆる場所にパッケージを埋め込むことです。はい、これにはパッケージが依存するすべてのライブラリが含まれます。

これを解決するためのハッキリ/危険な方法は次のとおりです。 CXFクラスを逆コンパイルできるはずです。これにより、次のようにクラスを変更することができます。

class CXF { 
    [...] 
    public static CXF getInstance() { 
     // based on the current Stack frame, determine which instance to return. Remember, the instance should be based on the WebApp bundle (while you still have shared libraries in between!) 
    } 
} 

これは絶対確実ではありません。あなたのWebAppがライブラリAから発信されたコールバック・スレッドを開始したとします。このスレッドはCXF.getInstance()を呼び出します - >getInstance()メソッドは、どのWebAppがコールバック・スレッドを開始したかを判別する方法がありません。

正しい解決策は、シングルトンパターンを使用しないようにすべてのライブラリを変更することです。おそらく、特別なクラスローダーを実装することで、問題を回避することができますが、これは他のワームの缶全体を開きます。

- EDIT - CXFを読んだ後、CXFがシングルトンクラスを公開することは非常に奇妙なようです。事はOSGiのために作られています!おそらく、CXFメーリングリストの質問をする方が良いでしょう。彼らは特別な砂糖のすべてを知り、シングルトンのインスタンスを作る理由があり、おそらくすでにこのユースケースを考えていたでしょう。

+0

恩恵を受けたときに返答した唯一の人であることを奨励します。あなたのEDITには、私は実際にCXFフォーラムに行きました。そして悲しいことに、私ができないFooとBarのソースを修正することが含まれています。上記のように、CXFライブラリを組み込むことは、数多くの問題で数回試行されています。好奇心をそそる擬似シングルトンはhttp://cxf.apache.org/javadoc/latest/org/apache/cxf/BusFactory.htmlにあります。思考せずにプログラムすると、あなたのバンドルはバスを変更したり、同じ方法で書かれた他のバンドルに影響を与える可能性があります。 – Thirlan

+0

非常に煩わしい!元の開発者を説得することで、問題のクラスを使用すべきではないと幸運を祈っています... CXFは、このような静的クラスを宣伝してはいけません。少なくとも、バンドル固有の/ OSGiサービスにしてはいけません。 – parasietje

関連する問題