2009-06-16 8 views
4

Es scheint natürlich, dass ein HttpServlet, das in einer OSGi-Umgebung läuft (d. H. In OSGi HttpService registriert), einige OSGi-Dienste aufrufen würde, um seine Aufgaben zu erledigen. Die Frage ist, wie Referenzen auf diesen OSGi-Service innerhalb des Servlets erhalten werden.Wie erhält man OSGi-Service-Referenzen von einem Servlet, das in OSGi HttpService registriert ist?

Eine Möglichkeit wäre, Abhängigkeiten in die HttpServlet Instanz zu injizieren, der Httpservice wie dies den OSGi registriert wird:

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

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

Ich bin mir nicht sicher, ob dies, da in nicht-OSGi-Umgebung ein gültiger Ansatz ist Der Servlet-Lebenszyklus wird vom Webcontainer verwaltet und daher wird die Servicereferenz für die Servlet-Instanzen, die später erstellt werden, nicht injiziert.

Es gibt eine andere Möglichkeit, dies zu lösen, wenn Sie PAX Web als eine Implementierung des OSGi HttpService verwenden. PAX Web exportiert den OSGi BundleContext als spezielles Attribut "osgi-bundlecontext" in den ServletContext. Die Bundlecontext kann dann dazu verwendet werden, die notwendig Service Referenzen zu erhalten:

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") 
} 

Doch dieser Ansatz ist ziemlich hässlich und bindet Sie an eine konkrete Implementierung der OSGi Httpservice. Kennen Sie eine andere (und möglicherweise bessere) Lösung für dieses Problem?

Antwort

2

Wenn Sie einen Setter für die Abhängigkeit von dem Service verwenden, wie Sie gezeigt haben, kann es auch außerhalb von OSGi arbeiten. Sie müssen nur einen anderen Mechanismus zur Abhängigkeitsinjektion verwenden. Wenn keine vorhanden ist, können Sie eine Unterklasse bereitstellen, die das Servlet mithilfe von JNDI-Suchvorgängen oder aus dem Servletkontext initialisiert.

public class MyServlet_AdapterForMissingDI extends MyServlet{ 

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

} 

Der Punkt ist, dass, wenn Sie DI-Fähigkeiten haben, die setFooService injizieren können, können Sie nur das gleiche Servlet in OSGi verwenden und an anderer Stelle, wenn Sie dies nicht tun (und immer noch wollen, um diesen Fall unterstützen), bieten Ihnen ein Adapter.

In einem verwandten Hinweis, überprüfen Sie Felix SCR, um die Abhängigkeiten Ihres Objekts zu konfigurieren, und Pax Web Extender Whiteboard, die kümmert sich um das Anhängen Ihres Servlet mit dem HttpService.

Insbesondere ohne SCR und Whiteboard müssen Sie über den Fall nachdenken, wenn der fooService später nicht mehr verfügbar ist oder der HttpService nach dem Servlet gestartet wird. In diesen Fällen würde Ihr Servlet einen Verweis auf einen toten Dienst haben, der verhindert, dass das Paket von der Garbage Collection erfasst wird, oder Ihr Servlet würde nicht mit dem HttpService registriert.

Update: Hier ist der SCR-Deskriptor, den ich für eines meiner Servlets verwende. SCR behandelt Servlet Instanziierung, Lebenszyklus, Registrierung (über Whiteboard) und Abhängigkeiten. Es gibt keinen OSGi-spezifischen Code im Servlet. Es gibt nicht einmal die Notwendigkeit einer Bundle mehr (SCR registriert alle Dienste):

<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> 

Die Abhängigkeiten für das Servlet angegeben werden in der reference-Tag. SCR wird die Service-Suche und -Bindung durchführen.

+0

Das Pax Web Extender Whiteboard sieht wie eine nette Lösung für die Registrierung von Servlets aus. Vielen Dank. Die Hauptfrage ist jedoch, wie Service-Referenzen aus dem Servlet in der OSGi-Umgebung bezogen werden. Sie haben JNDI-Lookup erwähnt, aber es ist nicht der richtige Weg, um auf die OSGi-Service-Registry zuzugreifen. Dann haben Sie auch den Servletkontext erwähnt, aber es gibt keine Möglichkeit, Objekte mithilfe der OSGi HttpService-Schnittstelle in den Servletkontext zu stellen. Bitte korrigieren Sie mich, falls ich falsch liege. –

+0

Sie können SCR verwenden, um Abhängigkeiten innerhalb von OSGi zu erhalten. Der Punkt ist, dass Sie nur einen Setter haben (wie setFooService), den Sie verwenden, um die Abhängigkeit zu injizieren. Dieser Setter kann manuell von einem BundleActivator aufgerufen werden (wie Sie in Ihrem Beispiel zeigen), von SCR, von iPojo, von Spring oder was auch immer. Diese Dienste kümmern sich um das Service-Tracking. – Thilo

+0

Noch einmal, der Punkt ist, dass das Servlet selbst seine Abhängigkeiten nicht nachschlägt. Es hat Setter, um sie von irgendwo injiziert zu bekommen. Sie würden JNDI nicht innerhalb von OSGi verwenden. Das war ein Beispiel dafür, wie Sie dasselbe Servlet auch außerhalb von OSGi in Abwesenheit anderer DI-Mechanismen einsetzen können. – Thilo

-1

Sie könnten die Dienste in ein Objekt injizieren, das dann von den Servlets abgefragt wird.

+0

Dies verschiebt das Problem nur um eine Ebene. Wie würde die Referenz auf dieses Objekt aus dem Servlet erhalten? –

2

Kann ein alter Beitrag sein und Sie könnten bereits die Antwort haben .. Sie starten Felix oder was auch immer OSGi Container selbst.Wenn dies der Fall ist, können Sie den Bündelkontext als Attribut für den Servlet-Kontext festlegen.

Was ist falsch bei der Verwendung eines HTTP-Dienstes von PAX. Schließlich werden die Thread-Verwaltung und andere Aspekte von dem Servlet-Container übernommen, in dem Sie diesen http-Dienst ausführen.

Verwandte Themen