Felix 未开始捆绑
Felix not starting bundle
无法将捆绑包加载到 felix 中。我使用
下载了 Felix 6.0.1,运行
> java -jar bin/felix.jar
____________________________
Welcome to Apache Felix Gogo
g!
我在 eclipse 中创建了一个 MavenProject TestA
:
- 我按照提供的方式添加了对 felix (6.0.1) 的依赖。
- 我在
TestA/src/main/java/testa/impl/Activator.java
中创建了一个 class。
- 我将 class
testa.impl.Activator
扩展为 org.osgi.framework.BundleActivator
。
- 我覆盖
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 中的清单以验证它是否正确生成。
无法将捆绑包加载到 felix 中。我使用
下载了 Felix 6.0.1,运行> java -jar bin/felix.jar
____________________________
Welcome to Apache Felix Gogo
g!
我在 eclipse 中创建了一个 MavenProject TestA
:
- 我按照提供的方式添加了对 felix (6.0.1) 的依赖。
- 我在
TestA/src/main/java/testa/impl/Activator.java
中创建了一个 class。 - 我将 class
testa.impl.Activator
扩展为org.osgi.framework.BundleActivator
。 - 我覆盖
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 中的清单以验证它是否正确生成。