Felix 未开始捆绑

Felix not starting bundle

无法将捆绑包加载到 felix 中。我使用

下载了 Felix 6.0.1,运行
> java -jar bin/felix.jar
____________________________
Welcome to Apache Felix Gogo

g! 

我在 eclipse 中创建了一个 MavenProject TestA:

  1. 我按照提供的方式添加了对 felix (6.0.1) 的依赖。
  2. 我在 TestA/src/main/java/testa/impl/Activator.java 中创建了一个 class。
  3. 我将 class testa.impl.Activator 扩展为 org.osgi.framework.BundleActivator
  4. 我覆盖 public void start(BundleContext bc) throws Exception 以打印出 Hello World!

这是 java 来源:

package testa.impl;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator {

    public void start(BundleContext arg0) throws Exception {
        System.out.println("Hello World!");
    }

    public void stop(BundleContext arg0) throws Exception {
        System.out.println("stop");
    }
}

这是我的 pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test</groupId>
    <artifactId>testa</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.apache.felix.main</artifactId>
            <version>6.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <defaultGoal>clean install org.apache.felix:maven-bundle-plugin:bundle</defaultGoal>
    </build>
</project>

然后我使用 mvn 编译成 jar 并使用

加载
g! install file:/C:/xxx/TestA/target/testa-0.0.1-SNAPSHOT.jar                              
Bundle ID: 20

然后我使用 lb

列出所有包
g! lb                                                                                                           15:51:56
START LEVEL 1
   ID|State      |Level|Name
    0|Active     |    0|System Bundle (6.0.1)|6.0.1
    1|Active     |    1|jansi (1.17.1)|1.17.1
    2|Active     |    1|JLine Bundle (3.7.0)|3.7.0
    3|Active     |    1|Apache Felix Bundle Repository (2.0.10)|2.0.10
    4|Active     |    1|Apache Felix Gogo Command (1.0.2)|1.0.2
    5|Active     |    1|Apache Felix Gogo JLine Shell (1.1.0)|1.1.0
    6|Active     |    1|Apache Felix Gogo Runtime (1.1.0)|1.1.0
   20|Installed  |    1|testa (0.0.1.SNAPSHOT)|0.0.1.SNAPSHOT
g!                                                                                                              

无论如何,我使用 start:

启动捆绑包
g! start 20
g!

我希望打印 "Hello World" 但 什么都没有显示

我现在很困惑,想看看bundle是否真的启动了。

g! lb                                                                                                           15:51:56
START LEVEL 1
   ID|State      |Level|Name
    0|Active     |    0|System Bundle (6.0.1)|6.0.1
    1|Active     |    1|jansi (1.17.1)|1.17.1
    2|Active     |    1|JLine Bundle (3.7.0)|3.7.0
    3|Active     |    1|Apache Felix Bundle Repository (2.0.10)|2.0.10
    4|Active     |    1|Apache Felix Gogo Command (1.0.2)|1.0.2
    5|Active     |    1|Apache Felix Gogo JLine Shell (1.1.0)|1.1.0
    6|Active     |    1|Apache Felix Gogo Runtime (1.1.0)|1.1.0
   20|Active     |    1|testa (0.0.1.SNAPSHOT)|0.0.1.SNAPSHOT
g!                                                                                                              15:51:58

已启动,但我的代码尚未执行。

问题

为什么 Hello World 没有打印在控制台上?

您似乎是在手动创建清单。您应该使用像 bnd-maven-plugin 这样的工具来完成它。由于您手动创建了清单,因此它看起来是错误的。您不导入您在代码中使用的包。即org.osgi.framework.

另外,不要从其他人的代码中扩展激活器 class,因为您通常无法导入他们的实现包。自己实现就好了:

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class TestA implements BundleActivator {

Hello World 没有打印在控制台上,因为您创建的 jar 实际上不是一个包。 奇怪的是,felix 允许您启动一个清单中没有任何 OSGI 相关信息的 jar。 我不清楚开始这样的捆绑包意味着什么?也许 类 发表了,也许没有。

大多数 java 框架扫描 jar 中的文件并使用反射或字节码分析来查找相关 类。 对于普通框架,扫描 jar 的开销仅在启动时产生一次。 OSGI 被设计为轻量级的,也用于移动设备。 此外,由于在 OSGI 中捆绑包可以来来去去,因此他们设计了一种更有效的方法。 OSGI 包将元数据存储在清单中。 这是一个简单的文本文件,始终位于同一位置(在 jar 中):"META-INF/MANIFEST.MF"。 如果您使用 zip 工具检查 jar 中的文件,您应该看到如下内容:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: Peter Rader
Build-Jdk: 1.8.0_111

对于未来的 OSGI 故障排除,我建议您检查(和 post)创建的清单。

有效的 OSGI 清单看起来像这样:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: Peter Rader
Build-Jdk: 1.8.0_111
Bundle-Name: testa
Bundle-SymbolicName: testa.impl
Bundle-Version: 1.0.0
Bundle-Activator: testa.impl.Activator
Import-Package: org.osgi.framework

当 felix 读取此清单时,它使用 "Bundle-Activator" 条目查找激活器(如果有)。 替换清单,bundle 应该可以正常部署了。
只需在相对于 jar 的位置创建一个名为 "META-INF/MANIFEST.MF" 的文本文件,其中包含上述文本。 接下来用以下 linux 命令(或您最喜欢的压缩工具)替换 jar 中的清单文件:

zip testa-0.0.1-SNAPSHOT.jar -u META-INF/*

zip 命令的预期输出:

updating: META-INF/MANIFEST.MF (deflated 36%)

一定要打开带有压缩文件的 jar 并检查内容是否已更改。 现在,如果您安装并启动包,它应该打印 "Hello World!".

虽然这解决了问题,但这不是一个非常干净的解决方案。
jar 规范有一些相当奇怪的规则,关于清单中的条目应该如何格式化:
https://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Manifest_Specification
最值得注意的是:

No line may be longer than 72 bytes (not characters), in its UTF8-encoded form.
If a value would make the initial line longer than this, 
it should be continued on extra lines (each starting with a single SPACE).

因此,您不想手动编辑此文件。 正如其他人所说,您有多种选项可以自动生成 OSGI 清单。 和以前一样,您可以检查生成的 jar 中的清单以验证它是否正确生成。