2009-06-16 11 views
4

OSGi環境で動作するHttpServlet(つまり、OSGi HttpServiceに登録されている)は、タスクを達成するためにいくつかのOSGiサービスを呼び出したいと思うのは当然です。問題は、サーブレット内のこれらのOSGiサービスへの参照を取得する方法です。私は、これは非OSGiの環境であるため、有効なアプローチであるかどうかわからないんだけどOSGi HttpServiceに登録されているサーブレットからOSGiサービス参照を取得する方法は?

MyServlet servlet = new MyServlet(); 
servlet.setFooService(fooService); 

httpService.registerServlet("/myservlet", servlet, initparams, context); 

一つの方法は、このようなOSGiのHTTPServiceのに登録されているHttpServletのインスタンスに依存性を注入することであろうサーブレットのライフサイクルはWebコンテナによって管理されるため、後で作成されたサーブレットインスタンスに対してはサービス参照が注入されません。

PAX WebをOSGi HttpServiceの実装として使用する場合、これを解決する別の方法があります。 PAX WebはOSGi BundleContextを特別な属性 "osgi-bundlecontext"としてServletContextにエクスポートします。 BundleContextは、必要に応じてサービス参照を取得するために使用することができます。

public void init(ServletConfig servletConfig) throws ServletException { 

    ServletContext context = servletConfig.getServletContext() 
    BundleContext bundleContext = 
     (BundleContext) context.getAttribute("osgi-bundlecontext"); 

    ServiceReference serviceRef = 
     bundleContext.getServiceReference("com.foo.FooService") 
} 

しかし、このアプローチはかなり醜いですとOSGi HTTPServiceのの具体的な実装にあなたを結び付けます。あなたはこの問題の他の(そしておそらくもっと良い)解決策を知っていますか?

答えて

2

あなたが示したように、サービス依存関係のためにセッターを使用すると、OSGiの外でも動作できます。他の依存性注入機構を使うだけでいいです。存在しない場合は、JNDIルックアップまたはサーブレットコンテキストを使用してサーブレットを初期化するサブクラスを提供できます。

public class MyServlet_AdapterForMissingDI extends MyServlet{ 

    public void init(ServletConfig config){ 
     setFooService(getItFromSomewhere()); 
    } 

} 

あなたがsetFooServiceを注入できるDI機能を持っている場合は、(このケースをサポートしたいとまだ)ない場合は、あなただけの、OSGiの中で、他の場所と同じサーブレットを使用することができるということでポイント、あなたが提供アダプタ。

Felix SCRでオブジェクトの依存関係を設定し、サーブレットをHttpServiceに接続するPax Web Extender Whiteboardをチェックしてください。

具体的には、SCRとホワイトボードがない場合、fooServiceが後で使用できなくなった場合、またはHttpServiceがサーブレットの後に開始された場合について考える必要があります。 これらの場合、サーブレットは、バンドルがガベージコレクションされない、またはサーブレットがHttpServiceに登録されないようなデッドサービスへの参照を持ちます。

更新:ここに私のサーブレットの1つに使用するSCR記述子があります。 SCRは、サーブレットのインスタンス化、ライフサイクル、登録(Whiteboard経由)、および依存関係を処理します。サーブレットにOSGi固有のコードはありません。 BundleActivatorの必要性は(SCRはすべてのサービスを登録する)もうさえありません:サーブレットの

<component name="oracle.statusServlet" > 
<implementation class="mypackage.DataSourceStatusServlet"/> 
<property name="service.description" value="Oracle DataSource status servlet" /> 
<property name="alias" value="/OracleDataSourceStatus" /> 
<property name="servlet-name" value="Oracle DataSource status servlet" /> 
<service> 
    <provide interface="javax.servlet.Servlet" /> 
</service> 
    <reference name="DATASOURCES" 
      interface="javax.sql.DataSource" 
      cardinality="0..n" policy="dynamic" 
      bind="bindDataSource" unbind="unbindDataSource"/> 

</component> 

依存関係はreferenceタグで指定されています。 SCRはサービス検索とバインディングを行います。

+0

Pax Web Extender Whiteboardは、サーブレットを登録するための素晴らしいソリューションのようです。ありがとう。しかし、主な問題は、OSGi環境でサーブレット内からサービス参照を取得する方法です。 あなたはJNDIルックアップについて言及しましたが、OSGiサービスレジストリにアクセスする正しい方法とは感じられません。次に、サーブレット・コンテキストについても触れましたが、OSGi HttpServiceインタフェースを使用してサーブレット・コンテキストにオブジェクトを配置する方法はありません。私が間違っているなら、私を修正してください。 –

+0

SCRを使用すると、OSGi内で依存関係を取得できます。要点は、依存関係を注入するために使用するsetter(setFooServiceなど)があることです。そのセッターはBundleActivator(あなたの例で示すように)、SCR、iPojo、Spring、または何でも手動で呼び出すことができます。これらのサービスはサービストラッキングを担当します。 – Thilo

+0

ここでも、サーブレット自体がその依存関係を検索しないことがポイントです。それは彼らがどこかから注射されるようになっています。 OSGiの内部ではJNDIを使用しません。これは、他のDIメカニズムがない場合でも、同じサーブレットをOSGiの外部で動作させる方法の例です。 – Thilo

-1

サーブレットによって照会されるオブジェクトにサービスを注入できます。

+0

これは、問題を1レベルだけシフトします。サーブレット内からこのオブジェクトへの参照を取得するにはどうすればよいでしょうか? –

2

古いポストかもしれませんし、すでに回答があるかもしれません。 あなたはfelixやOSGiコンテナを自分で起動していますか?この場合、バンドルコンテキストをサーブレットコンテキストの属性として設定できます。

PAXによるhttpサービスの使用には何が間違っていますか。最終的にスレッド管理などの側面は、このhttpサービスを実行するサーブレットコンテナによって処理されます。

関連する問題