Первое, что нужно сказать, что вы должны зарегистрировать этот объект в другом расслоении активатором в качестве службы OSGi. В этом случае вы сможете получить доступ к нему почти повсеместно.
Другой вопрос: как получить к нему доступ с другой стороны? Есть много возможностей, некоторые из них лучше, некоторые из них хуже.
простой, но на самом деле не красивое решение:
Bundle bundle = FrameworkUtil.getBundle(this.getClass());
// Getting the service and using it based on the bundle
Проблема с этим решением, что для каждого запроса вы должны получить услугу OSGi из реестра OSGi услуг, основанный на фильтрах и уничтожать в зародыше это после того, как вызов функции - лишние накладные расходы.
Решение основано на ServiceTracker:
Если вы используете трекер службы вы столкнулись с проблемой, которую вы должны открыть и закрыть его где-нибудь. Открытие в конструкторе может быть решением, однако вы не найдете места в своем классе отдыха, где вы можете его закрыть. Решением может быть то, что вы создаете прослушиватель сервлета, вы открываете и закрываете там трекер и отправляете трекер службы в карту атрибутов контекста сервлета. В вашей функции REST вы можете получить доступ к контексту сервлета и получить трекер службы в каждом вызове, чем вы можете вызвать tracker.getService(). Эта функция вернет вам нужный объект или null, если он еще не зарегистрирован.
Решение, которое не было необходимости ставить OSGi код, относящийся к REST класса:
Это вероятность того, что вы не хотите использовать ServiceTracker в коде REST, как вы не хотите зависеть от OSGi есть. В этом случае вы можете использовать очень простую библиотеку, которую я реализовал :). Он доступен по адресу https://github.com/everit-org/osgi-servicereference.
Методика такая же. Вы пишете Listener, который: - Создает ServiceReference - Вы вызываете getProxtInstance of serviceReference в ServletContext . Вы получаете прокси-объект на основе интерфейса, который вы предоставили в своей функции REST, и вызываете методы на нем.
ServiceReference был реализован как часть реализации Blueprint.Поэтому он работает так же, как тег работает в XML-файле проекта. Вы можете создать ссылку на службу и открыть ее (после того, как будут открыты службы OSGi). Вы можете получить объект, который реализует необходимые интерфейсы (предоставленные вами) с помощью метода getProxyInstance.
Когда вызов функции производится на объекте на основе вашего интерфейса:
- Если служба OSGi доступен вызов функции будет делегирована к этой службе
- Если нет службы OSGi не доступна функция вызов будет удерживаться до таймаута (простой поток .wait). Если есть служба OSGi до таймаута, вызов функции будет делегирован. Если нет, будет выведено исключение ServiceUnavailableException. Вы можете переопределить поведение тайм-аута, установив другой обработчик тайм-аута для объекта ServiceReference.
Вызов нормальной функции выглядит так:
Вызывающий -> OSGiService.function
Вызов функции с помощью объекта ServiceReference прокси выглядит следующим образом:
вызывающему -> ServiceReference.proxyObject - > OSGiService.function (если доступна OSGiService)
Теперь решение на практике:
Вы должны написать слушателя для веб-приложения:
private Reference reference;
@Override
public void contextInitialized(final ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
BundleContext bundleContext = (BundleContext) servletContext.getAttribute("osgi-bundlecontext");
try {
Filter filter = bundleContext.createFilter("(objectClass=" + MyInterface.class.getName() + ")");
// MyInterface is the interface the OSGi service implements (there can be multiple) and the timeout until function calls will wait is 5s.
reference = new Reference(bundleContext, new Class<?>[] { MyInterface.class }, filter, 5000);
// Opening the reference is necessary to track services
reference.open();
// Taking the proxy object into the servlet context attributes
servletContext.setAttribute("myService", reference.getProxyInstance());
} catch (InvalidSyntaxException e) {
LOGGER.error(e.getMessage(), e);
}
}
@Override
public void contextDestroyed(final ServletContextEvent sce) {
if (reference != null) {
reference.close();
sce.getServletContext().removeAttribute("myService");
}
}
После того, как этот приемник вы можете получить прокси-объект, как следующее везде в ваших кодов (где вы можете получить доступ к контексту сервлета):
MyInterface myService = servletContext.getAttribute("myService");
myService.foo();
Какова конкретная причина, по которой вы не хотите объявлять услугу как singleton? Я думаю, вы можете зарегистрировать объекты в Джерси, чтобы они были предоставлены в качестве службы REST. У вас нет возможности определить фабрику или что-то, что используется для создания экземпляра объекта для каждого запроса. Другой вопрос: как создается экземпляр объекта в другом пакете? Какую технологию или механизм вы используете для создания экземпляра? Вы делаете это в Активаторе или со специальной технологией? Какое событие вызывает другой экземпляр для создания экземпляра этого объекта? –
Является активатором да. Я создаю экземпляр другого объекта, когда пучок, содержащий его, запускается, в активаторе этот объект «настроен», а затем мне нужно ввести его в службу REST. Я подумал, что есть возможность сказать этой службе, чтобы взять этот объект или использовать Джерси, причал или другой пакет или библиотеку, чтобы вводить объект каждый раз, когда создается экземпляр службы. – Koalk
Почему вы хотите создать экземпляр службы несколько раз? Почему это не хорошо, если вы устанавливаете его и создаете экземпляр части, которая отличается для каждого запроса в качестве локальной переменной внутри вашей функции? Как вы регистрируете свое обслуживание в Джерси? Вы настраиваете его в webapp web.xml или используете HTTP-сервис для его программного программирования? У меня такое чувство, что решение было бы довольно простым для вас, но было бы неплохо узнать немного раньше ответа. –