Как получить ссылки на службы OSGi из сервлета, зарегистрированного в OSGi HttpService?
-
05-07-2019 - |
Вопрос
Кажется естественным, что 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.
Вы можете внедрить службы в некоторый объект, который затем запрашивается сервлетами.