Pregunta

Parece natural que un HttpServlet se ejecute en un entorno OSGi (es decir, registrado en OSGi HttpService ) querría llamar a algunos servicios OSGi para realizar sus tareas. La pregunta es cómo obtener referencias a estos servicios OSGi dentro del servlet.

Una forma sería inyectar dependencias en la instancia de HttpServlet que se está registrando en el OSGi HttpService de esta manera:

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

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

No estoy seguro de que este sea un enfoque válido, ya que en un entorno que no es OSGi, el ciclo de vida del servlet es administrado por el contenedor web y, por lo tanto, la referencia de servicio no se inyectaría para las instancias de servlet creadas más adelante.

Hay otra forma de resolver esto cuando se utiliza PAX Web como Implementación del OSGi HttpService. PAX Web exporta el OSGi BundleContext al ServletContext como un atributo especial "osgi-bundlecontext". El BundleContext se puede usar para obtener las referencias de servicio necesarias:

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

Sin embargo, este enfoque es bastante feo y lo vincula a una implementación concreta del OSGi HttpService. ¿Conoces alguna otra solución (y posiblemente mejor) a este problema?

¿Fue útil?

Solución

Si usa un setter para la dependencia del servicio, como ha mostrado, también puede funcionar fuera de OSGi. Solo necesita usar algún otro mecanismo de inyección de dependencia. Si no hay ninguno, puede proporcionar una subclase que inicialice el servlet utilizando búsquedas JNDI o desde el contexto del servlet.

public class MyServlet_AdapterForMissingDI extends MyServlet{

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

}

El punto es que si tiene capacidades de DI que pueden inyectar setFooService , simplemente puede usar el mismo servlet en OSGi y en otros lugares, si no lo hace (y aún quiere admitir este caso), usted proporciona un adaptador.

En una nota relacionada, consulte Felix SCR para configurar las dependencias de su objeto, y Pax Web Extender Whiteboard, que se encarga de conectar su servlet con el HttpService.

Específicamente, sin SCR y Whiteboard, debe pensar en el caso cuando el fooService no esté disponible más tarde, o el HttpService se inicie después de su servlet. En estos casos, su servlet tendría una referencia a un servicio muerto que impide que el paquete se recoja, o su servlet no se registrará con el HttpService.

Actualización: Aquí está el descriptor SCR que uso para uno de mis servlets. SCR maneja la instanciación de servlets, el ciclo de vida, el registro (a través de Whiteboard) y las dependencias. No hay ningún código específico de OSGi en el servlet. Ya ni siquiera existe la necesidad de un BundleActivator (SCR registra todos los servicios):

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

Las dependencias para el servlet se especifican en la etiqueta reference . SCR realizará el servicio de búsqueda y enlace.

Otros consejos

Puede ser una publicación antigua y es posible que ya tengas la respuesta ... ¿Estás lanzando Felix o cualquier contenedor OSGi? Si ese es el caso, puede establecer el contexto del paquete como un atributo para el contexto del servlet.

¿Qué tiene de malo utilizar un servicio http de PAX? en última instancia, la gestión de subprocesos y otros aspectos son atendidos por el contenedor de servlet en el que ejecuta este servicio http.

Puede inyectar los servicios en algún objeto, que luego es consultado por los servlets.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top