Как получить ссылки на службы OSGi из сервлета, зарегистрированного в OSGi HttpService?

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

Вопрос

Кажется естественным, что 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. Знаете ли вы другое (и, возможно, лучшее) решение этой проблемы?

Это было полезно?

Решение

Если вы используете установщик для зависимости от сервиса, как вы показали, он может работать и вне 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 и доски вы должны подумать о случае, когда 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 выполнит поиск и привязку службы.

Другие советы

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top