Pergunta

Parece natural que um HttpServlet em execução no ambiente OSGi (isto é registrado em OSGi HTTPService ) gostaria de chamar alguns serviços OSGi para realizá-lo de tarefas. A questão é como obter referências a estes serviços OSGi dentro do servlet.

Uma forma seria para injetar dependências para a instância HttpServlet que está sendo registrado no OSGi HTTPService assim:

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

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

Eu não tenho certeza se isso é uma abordagem válida já que em ambiente não-OSGi o ciclo de vida do servlet é gerido pela Web Container e, portanto, a referência de serviço não seria injetado para as instâncias servlet criados mais tarde.

Há uma outra maneira de resolver isto quando utilizar PAX Web como um implementação do OSGi HTTPService. PAX Web exporta o OSGi BundleContext no ServletContext como um atributo especial "osgi-BundleContext". O BundleContext pode então ser usado para obter referências de serviço necessário:

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

No entanto, esta abordagem é bastante feio e os laços que para uma implementação concreta da OSGi HTTPService. Você sabe qualquer outra solução (melhor e possivelmente) para este problema?

Foi útil?

Solução

Se você usar um setter para a dependência do serviço, como você mostrou, ele pode trabalhar fora da OSGi também. Você só precisa usar algum outro mecanismo de injeção de dependência. Se não houver nenhum, você poderia fornecer uma subclasse que inicializa o servlet usando consultas JNDI ou do contexto do servlet.

public class MyServlet_AdapterForMissingDI extends MyServlet{

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

}

O ponto é que se você tem recursos de DI que podem injetar setFooService, você pode simplesmente usar o mesmo servlet em OSGi e em outros lugares, se você não fizer isso (e ainda querem apoiar neste caso), você fornecer um adaptador.

Em uma nota relacionada, veja Felix SCR para configurar as dependências do seu objeto, e Pax Web Extender Whiteboard, que cuida de conectar seu servlet-se com o HTTPService.

Especificamente, sem SCR e Whiteboard, você precisa pensar sobre o caso quando o FooService ficar indisponível depois, ou o HTTPService é iniciada após o seu servlet. Nestes casos, o servlet teria uma referência a um serviço de mortos que impede que o pacote de ser, ou o seu servlet não ser registrado com o HTTPService.

coleta de lixo

Update: Aqui é o descritor SCR eu uso para um dos meus servlets. alças SCR instanciação servlet, ciclo de vida, de registo (via Whiteboard) e dependências. Não há nenhum código específico do OSGi no servlet. Não há nem mesmo a necessidade de mais um BundleActivator (SCR registra todos os serviços):

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

As dependências para o servlet são especificados na tag reference. SCR irá fazer o lookup serviço e vinculativo.

Outras dicas

Pode ser um post antigo e você já poderia ter conseguido a resposta .. Você está lançando felix ou qualquer OSGi recipiente si mesmo. Se for esse o caso, você pode definir o contexto pacote como um atributo para o contexto servlet.

O que está errado em usar um serviço http por PAX. em última análise, o gerenciamento de threads e outros aspectos são atendidos pelo servlet container em que você executar este serviço http.

Você pode injetar os serviços em algum objeto, que é, então, consultado pelos servlets.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top