Как получить ссылки на службы OSGi из сервлета, зарегистрированного в OSGi HttpService? - PullRequest
4 голосов
/ 16 июня 2009

Кажется естественным, что HttpServlet, работающий в среде OSGi (т.е. зарегистрированный в OSGi HttpService ), хотел бы вызвать некоторые службы OSGi для выполнения своих задач. Вопрос в том, как получить ссылки на эти службы OSGi внутри сервлета.

Один из способов - внедрить зависимости в экземпляр HttpServlet, который регистрируется в OSGi HttpService, следующим образом:

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

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

Я не уверен, что это правильный подход, поскольку в среде, отличной от OSGi, жизненный цикл сервлета управляется веб-контейнером, и, следовательно, ссылка на службу не будет внедряться для экземпляров сервлета, созданных позже.

Существует другой способ решения этой проблемы при использовании PAX Web в качестве реализации OSGi HttpService. PAX Web экспортирует OSGi BundleContext в ServletContext в виде специального атрибута «osgi-bundlecontext». Затем 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. Знаете ли вы другое (и, возможно, лучшее) решение этой проблемы?

Ответы [ 3 ]

2 голосов
/ 17 июня 2009

Если вы используете установщик для зависимости от сервиса, как вы показали, он может работать и за пределами OSGi. Вам просто нужно использовать какой-то другой механизм внедрения зависимостей. Если его нет, вы можете предоставить подкласс, который инициализирует сервлет с помощью поиска JNDI или из контекста сервлета.

public class MyServlet_AdapterForMissingDI extends MyServlet{

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

}

Дело в том, что если у вас есть возможности DI, которые могут вводить setFooService, вы можете просто использовать один и тот же сервлет в OSGi и в других местах, если вы этого не делаете (и все еще хотите поддерживать этот случай), вы предоставляете адаптер.

В соответствующей заметке посмотрите Felix SCR для настройки зависимостей вашего объекта и Pax Web Extender Whiteboard, которая заботится о подключении вашего сервлета к HttpService.

В частности, без SCR и Whiteboard вам нужно подумать о случае, когда fooService станет недоступным позже или HttpService запускается после вашего сервлета. В этих случаях ваш сервлет будет иметь ссылку на неработающую службу, которая препятствует сборке мусора в пакете, иначе ваш сервлет не будет зарегистрирован в HttpService.

Обновление: Вот дескриптор SCR, который я использую для одного из моих сервлетов. SCR обрабатывает создание экземпляров сервлетов, жизненный цикл, регистрацию (через доску) и зависимости. В сервлете нет специфичного для 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 выполнит поиск и привязку службы.

2 голосов
/ 02 марта 2011

Может быть старый пост, и вы уже могли получить ответ .. Вы запускаете felix или любой другой OSGi-контейнер самостоятельно. В этом случае вы можете установить контекст пакета как атрибут для контекста сервлета.

Что плохого в использовании службы http PAX. в конечном итоге управление потоками и другие аспекты решаются контейнером сервлета, в котором вы запускаете эту службу http.

0 голосов
/ 16 июня 2009

Вы можете внедрить службы в некоторый объект, который затем запрашивается сервлетами.

...