Comment obtenir des références de service OSGi à partir d'un servlet enregistré dans OSGi HttpService?

StackOverflow https://stackoverflow.com/questions/1002813

Question

Il semble naturel qu'un HttpServlet s'exécutant dans un environnement OSGi (c'est-à-dire enregistré dans OSGi HttpService ) voudrait appeler certains services OSGi pour accomplir ses tâches. La question est de savoir comment obtenir des références à ces services OSGi dans le servlet.

Une solution consiste à injecter des dépendances dans l'instance HttpServlet en cours d'enregistrement sur OSGi HttpService comme suit:

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

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

Je ne sais pas si cette approche est valide car, dans un environnement non OSGi, le cycle de vie du servlet est géré par le conteneur Web. Par conséquent, la référence de service ne serait pas injectée pour les instances de servlet créées ultérieurement.

Il existe un autre moyen de résoudre ce problème en utilisant PAX Web en tant que implémentation du OSGi HttpService. PAX Web exporte le BundleContext OSGi dans le ServletContext en tant qu’attribut spécial "osgi-bundlecontext". BundleContext peut ensuite être utilisé pour obtenir les références de service nécessaires:

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

Cependant, cette approche est plutôt laide et vous lie à une implémentation concrète de OSGi HttpService. Connaissez-vous une autre (et éventuellement une meilleure) solution à ce problème?

Était-ce utile?

La solution

Si vous utilisez un setter pour la dépendance au service, comme vous l'avez montré, cela peut également fonctionner en dehors d'OSGi. Vous devez juste utiliser un autre mécanisme d'injection de dépendance. S'il n'y en a pas, vous pouvez fournir une sous-classe qui initialise le servlet à l'aide de recherches JNDI ou à partir du contexte de servlet.

public class MyServlet_AdapterForMissingDI extends MyServlet{

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

}

Le fait est que si vous disposez de fonctionnalités DI pouvant injecter setFooService , vous pouvez simplement utiliser le même servlet dans OSGi et ailleurs, si vous ne le faites pas (et souhaitez toujours prendre en charge ce cas), vous fournissez un adaptateur.

Sur une note connexe, consultez Felix SCR pour configurer les dépendances de votre objet, ainsi que Pax Web Extender Whiteboard, qui s’occupe de relier votre servlet au service HttpService.

Plus précisément, sans SCR et tableau blanc, vous devez prendre en compte le cas où le service fooService sera indisponible ultérieurement ou le service HttpService démarré après votre servlet. Dans ce cas, votre servlet aurait une référence à un service inactif empêchant le regroupement d'être collecté, ou votre servlet ne serait pas enregistré avec HttpService.

Mettre à jour: voici le descripteur SCR que j'utilise pour l'un de mes servlets. SCR gère l'instanciation des servlets, le cycle de vie, l'enregistrement (via le tableau blanc) et les dépendances. Il n'y a pas de code spécifique à OSGi dans le servlet. Il n’ya même plus besoin d’un BundleActivator (SCR enregistre tous les services):

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

Les dépendances du servlet sont spécifiées dans la balise reference . SCR se chargera de la recherche et de la liaison du service.

Autres conseils

Peut-être un ancien post et vous auriez peut-être déjà la réponse .. Lancez-vous felix ou un conteneur OSGi vous-même? Si tel est le cas, vous pouvez définir le contexte de l'ensemble en tant qu'attribut du contexte du servlet.

Quoi de mal à utiliser un service http par PAX. en fin de compte, la gestion des threads et d’autres aspects sont pris en charge par le conteneur de servlets dans lequel vous exécutez ce service http.

Vous pouvez injecter les services dans un objet, qui est ensuite interrogé par les servlets.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top