【问题标题】:OSGI HttpService couldn't be initialized / injected properlyOSGI HttpService 无法正确初始化/注入
【发布时间】:2014-06-11 00:19:48
【问题描述】:

我想在我的 OSGI 项目中为我的 servlet 使用声明式服务功能。详细说明:用户可以在主应用程序上手动安装模块,选择一些 *.jar 文件,主应用程序有嵌入式 OSGI 服务器,当 OSGI 模块被激活时,它应该为一些请求注册 比如这样:

protected void startup() {
  MyServlet servlet = new MyServlet();
  if (httpService != null)  {
    httpService.registerServlet("/req", servlet, null, null); **//OK!**
  }
}

不幸的是,我无法初始化 httpService 实例,这就是问题所在。以下是问题 servlet 模块代码清单:

@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 bundle插件设置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();
    }
}

我的灵感来自 Peter Fries 博客 (http://www.peterfriese.de/osgi-servlets-flexibility-by-simplicity/) 中的示例,但我无法初始化 httpService 实例。 App 模块甚至只有在 @Reference 注释被移除或被注释覆盖的情况下才能启动,否则模块将不会被激活。

我怀疑我的嵌入式 OSGI 没有一些必需的模块,但无法获取有关它的详细信息 - 日志控制台没有说任何内容。

更新

感谢 Balasz 的提示!
有我的错误:
0.&lt;Embed-Dependency&gt;!org.osgi.core&lt;/Embed-Dependency&gt;声明时httpService不能通过@Reference注解自动绑定,所以bind = "bindHttpService", unbind = "unbindHttpService"没用。我删除了&lt;Embed-Dependency&gt; 声明,它有助于像我想要的那样绑定httpService(通过bindHttpService)。

  1. 在 OSGI 服务器上安装 bundle 之前应该指定 jetty 设置:

    System.setProperty("jetty.port","8080");
    System.setProperty("jetty.home.bundle", "org.eclipse.jetty.osgi.boot");

  2. 在我的情况下,嵌入式 OSGI 服务器上必须安装的 jar 太多

    // 强制捆绑包 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.equinox.ds_1.4.200.v20131126-2331.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\javax.servlet-api-3.0.1.jar"));

            // 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 对象,现在我想注册我的 servlet 实例

@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")
   }
}

上面的代码 sn-p 将显示“Greetings”消息,但如果我尝试注册 servlet 并取消注释“BAD PLACE”,则不会显示该消息,没有任何反应。也无法捕获异常;看起来“启动”方法被忽略了。有什么想法吗?

【问题讨论】:

  • 你收集的捆绑包对我来说似乎有点奇怪。您可以从 Jetty 版本 8.0.4 和 Jetty 版本 8.1.12 获得捆绑包。您还可以从 Equinox 获得一些捆绑包。您的 OSGi 容器中是否可能有两次 org.osgi.service.http 包?在这种情况下,您的 Bundle 可能会连接到其中一个,而 HttpService 对象是基于另一个实例化的。我建议您应该检查我发送的链接上的依赖关系,因为它确实有效(使用 Jetty 9.1.0)。
  • 谢谢@BalazsZsoldos 确实有很多不必要的捆绑包要安装,所以我修改了我的示例[我的答案如下]。对于您的示例,您使用的是 Jetty 9.1.0,它取决于 javax.servlet 3.1.0 版本。不幸的是,org.eclipse.equinox.http.servlet_1.1.400.v20130418-1354 包有一个约束:javax.servlet; version="[2.3.0,3.1.0)"' 并且此捆绑包是 org.eclipse.jetty.osgi.httpservice_9.1.0.v20131115 与 HttpService 实现的约束。这就是为什么我必须使用 javax.servlet 3.0.1 版本和 Jetty 8.0.4 - 这组依赖项没有任何问题。

标签: java servlets osgi apache-felix osgi-bundle


【解决方案1】:

我没有看到您添加任何包含任何 servlet 容器(jetty 或 tomcat)的包。我也没有在您的列表中看到包含 HttpService 实现的包。

如果您需要一个工作示例,请参阅“使用 HTTP 服务的 Jetty”部分下的依赖项 here。如果您将这些依赖项及其依赖项传递导入,您将拥有一个带有 HttpService 的 Jetty 服务器。在示例中,依赖项被注释掉,因为它们仅在开发时使用。请注意,您必须以定义以下系统属性的方式启动嵌入式 servlet 容器:

jetty.port=8080
jetty.home.bundle=org.eclipse.jetty.osgi.boot

如果你用谷歌搜索,你可以找到 Tomcat 或 Jetty 的其他捆绑包。

【讨论】:

  • 感谢 Balasz,现在我可以初始化一个 httpService。但是 servlet 注册不起作用。我用最近的更改更新了我的帖子
【解决方案2】:

所以,安装包列表如下

// 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 一起使用,但无法解决依赖 org.eclipse.equinox.http.servlet 的 jetty-httpservice 的问题(也许有一些版本的这个 jar 适用于 javax.servlet 3.1.0 但我没有找到它)

我在 bitbucket 上发布了一个带有 HttpService 的嵌入式 OSGI 服务器的小代码示例,也许有人觉得它有用: https://bitbucket.org/vbashur/diff/src/

【讨论】:

  • 注意 在 Eclipse IDE 下使用 Java 6 运行代码对 OSGI 服务不起作用,因此请确保为 jdk1.7 配置了构建路径
猜你喜欢
  • 2015-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多