Я хотел бы использовать функцию декларативных услуг в моем проекте OSGI для своих сервлетов. Подробнее: пользователь может установить модуль вручную в главном приложении, выбрав некоторый файл *.jar, основное приложение имеет встроенный сервер OSGI, а когда модуль OSGI активирован, он должен быть зарегистрирован для некоторых запросов. Например, следующим образом:
protected void startup() {
MyServlet servlet = new MyServlet();
if (httpService != null) {
httpService.registerServlet("/req", servlet, null, null); **//OK!**
}
}
К сожалению, я не могу инициализировать экземпляр httpService и проблему. Здесь приведен код ошибки модуля сервлета:
@Component(name="app", immediate=true)
@Service(value=App.class)
public class App {
@Reference(name = "httpService", referenceInterface = HttpService.class, bind = "bindHttpService", unbind = "unbindHttpService")
private HttpService httpService;
@Activate
protected void startup() {
MyServlet servlet = new MyServlet();
if (httpService != null) {
httpService.registerServlet("/req", servlet, null, null);
//OK!
} else {
//Not OK!
}
}
protected void bindHttpService(HttpService httpService) {
this.httpService = httpService;
}
protected void unbindHttpService(HttpService httpService) {
this.httpService = null;
}
// some more code.........
}
Настройки плагина Maven pom.xml
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>app</Bundle-SymbolicName>
<Embed-Dependency>!org.osgi.core</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
<Import-Package>
<![CDATA[
org.osgi*,
com.mynamespace
]]>
</Import-Package>
</instructions>
</configuration>
</plugin>
И вот упрощенный код для встроенного OSGI-сервера в основном приложении:
public static void main(String[] args)
{
FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
Map<String, String> config = new HashMap<String, String>();
config.put(Constants.FRAMEWORK_STORAGE_CLEAN, "onFirstInit");
config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "javax.microedition.io");
Framework framework = frameworkFactory.newFramework(config);
framework.start();
BundleContext context = framework.getBundleContext();
List<Bundle> installedBundles = new LinkedList<Bundle>();
// install prerequisites
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.equinox.util_1.0.500.v20130404-1337.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.osgi.services_3.4.0.v20131120-1328.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.equinox.ds_1.4.200.v20131126-2331.jar"));
//install servlet module
installedBundles.add(context.installBundle("file:///MY_PATH\\app.jar"));
for (Bundle bundle : installedBundles) {
bundle.start();
}
}
Я был вдохновлен примером из блога Питера Фриса (http://www.peterfriese.de/osgi-servlets-flexibility-by-simplicity/), но я не могу инициализировать экземпляр httpService. Модуль App даже можно запустить, только если аннотация @Reference удалена или закрыта комментарием, в другом случае модуль не будет активирован.
Я подозреваю, что мой встроенный OSGI не имеет какого-то обязательного модуля, но не может получить информацию об этом - консоль журнала ничего не говорит.
Спасибо за подсказку Балаш!
Есть мои ошибки:
0. Когда <Embed-Dependency>!org.osgi.core</Embed-Dependency>
httpService не может быть автоматически привязана через @Reference annotatoin, поэтому bind = "bindHttpService", unbind = "unbindHttpService"
бесполезен. Я удалил объявление <Embed-Dependency>
и он помогает связать httpService, как будто я хочу его (через bindHttpService).
Прежде чем устанавливать пакеты на OSGI, необходимо указать параметры причала сервера:
System.setProperty( "jetty.port", "8080");
System.setProperty("jetty.home.bundle", "org.eclipse.jetty.osgi.boot");
На встроенный сервер OSGI должно быть установлено слишком много банок, в моем случае
//Установлены обязательные связкиBundles.add(context.installBundle("file:///MY_PATH\org.eclipse.equinox.util_1.0.500.v20130404-1337.jar")); installedBundles.add(( "Файл:///my_path\org.eclipse.equinox.ds_1.4.200.v20131126-2331.jar" context.installBundle)); installedBundles.add(( "Файл:///my_path\org.eclipse.osgi.services_3.4.0.v20131120-1328.jar" context.installBundle)); installedBundles.add(( "Файл:///my_path\javax.servlet-апи-3.0.1.jar" context.installBundle));
// Container bundles
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.jetty.security_8.1.12.v20130726.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.jetty.servlet_8.1.12.v20130726.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.jetty.continuation_8.1.12.v20130726.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.jetty.server_8.1.12.v20130726.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.jetty.util_8.1.12.v20130726.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.jetty.io_8.1.12.v20130726.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.jetty.http_8.1.12.v20130726.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.equinox.http.servlet_1.1.400.v20130418-1354.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.equinox.http.jetty_3.0.200.v20131021-1843.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.equinox.http.servletbridge_1.0.300.v20130327-1442.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.equinox.servletbridge_1.3.0.v20130927-1541.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.equinox.common_3.6.200.v20130402-1505.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.equinox.registry_3.5.400.v20130717-1325.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.eclipse.equinox.http.registry_1.1.300.v20130402-1529.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\org.osgi.service.obr-1.0.2.jar"));
// Service bundles
installedBundles.add(context.installBundle("file:///MY_PATH\\jetty-httpservice-8.0.4.v20111024.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\ow2-httpservice-1.2-spec-1.0.0.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\jetty-osgi-boot-8.0.4.v20111024.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\jetty-deploy-8.0.4.v20111024.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\jetty-webapp-8.0.4.v20111024.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\jetty-security-8.0.4.v20111024.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\jetty-http-8.0.4.v20111024.jar"));
installedBundles.add(context.installBundle("file:///MY_PATH\\jetty-xml-8.0.4.v20111024.jar"));
// Finally, required OSGI bundle
installedBundles.add(context.installBundle("file:///MY_PATH\\app.jar"));
Поэтому с этими изменениями у меня есть инициализированный объект httpService, и теперь я хочу зарегистрировать свой экземпляр сервлета
@Activate
protected void startup() {
MyServlet servlet = new MyServlet();
if (httpService != null) {
System.out.println("Greetings! I just want to be sure that service isn't null!")
//httpService.registerServlet("/req", servlet, null, null); // BAD PLACE
} else {
System.out.println("Something goes wrong")
}
}
В приведенном выше фрагменте кода будет отображаться сообщение "Приветствия", но если я попытаюсь зарегистрировать сервлет и раскомментировать "ПЛОХОЕ МЕСТО", сообщение не будет показано, ничего не происходит. Исключение также не может быть уловлено; похоже, что метод "запуска" игнорируется. Какие-нибудь идеи, что неправильно?
Я не вижу, что вы добавляете пакет, содержащий любой контейнер сервлетов (причал или кошка). Я также не вижу в списке список, содержащий реализацию HttpService.
Если вам нужен рабочий пример, см. Зависимости здесь в разделе "Jetty with HTTP service". Если вы импортируете эти зависимости с их зависимостями транзитивно, у вас будет сервер Jetty с HttpService. В примере зависимости закомментированы, поскольку они используются только во время разработки. Обратите внимание, что вы должны запустить встроенный контейнер сервлета таким образом, чтобы были определены следующие системные свойства:
jetty.port=8080
jetty.home.bundle=org.eclipse.jetty.osgi.boot
Если вы google, вы можете найти другие комплекты комплектов для Tomcat или Jetty.
Таким образом, список установленных пакетов следующий:
// without these bundles http service won't be initialized
context.installBundle(libsDirectoryURL + "org.eclipse.equinox.util_1.0.500.v20130404-1337.jar");
context.installBundle(libsDirectoryURL + "org.eclipse.equinox.ds_1.4.200.v20131126-2331.jar");
context.installBundle(libsDirectoryURL + "org.eclipse.osgi.services_3.4.0.v20131120-1328.jar");
context.installBundle(libsDirectoryURL + "org.eclipse.equinox.http.servlet_1.1.400.v20130418-1354.jar");
context.installBundle(libsDirectoryURL + "javax.servlet-api-3.0.1.jar");
context.installBundle(libsDirectoryURL + "jetty-httpservice-8.0.4.v20111024.jar");
context.installBundle(libsDirectoryURL + "jetty-server-8.0.4.v20111024.jar");
context.installBundle(libsDirectoryURL + "jetty-osgi-boot-8.0.4.v20111024.jar");
context.installBundle(libsDirectoryURL + "jetty-deploy-8.0.4.v20111024.jar");
context.installBundle(libsDirectoryURL + "jetty-continuation-8.0.4.v20111024.jar");
context.installBundle(libsDirectoryURL + "jetty-servlet-8.0.4.v20111024.jar"));
context.installBundle(libsDirectoryURL + "jetty-webapp-8.0.4.v20111024.jar");
context.installBundle(libsDirectoryURL + "jetty-server-8.0.4.v20111024.jar");
context.installBundle(libsDirectoryURL + "jetty-security-8.0.4.v20111024.jar");
context.installBundle(libsDirectoryURL + "jetty-http-8.0.4.v20111024.jar");
context.installBundle(libsDirectoryURL + "jetty-io-8.0.4.v20111024.jar");
context.installBundle(libsDirectoryURL + "jetty-util-8.0.4.v20111024.jar");
context.installBundle(libsDirectoryURL + "jetty-xml-8.0.4.v20111024.jar");
Я хотел бы использовать javax.servlet 3.1.0 с jetty 9.1.0, но не смог решить проблему с jetty-httpservice, которая зависит от org.eclipse.equinox.http.servlet (возможно, есть версия этого банку, которая отлично работает с javax.servlet 3.1.0, но я не нашел его)
Я разместил небольшой пример кода встроенного сервера OSGI с HttpService на bitbucket, может быть, кто-то найдет его полезным: https://bitbucket.org/vbashur/diff/src/