OSGi enRoute – 2.3_5 – OSGi 运行时
在本章中你将学到什么
在本章中我们首先会定义一个运行时环境。一个OSGi运行时环境由一个classpath、一个框架、以及框架的一些配置属性组成。与Application Server Model相比,运行时对Application来说是独一无二的。在本章中,我们将会展示如何创建一个包含了所有依赖的可执行JAR。
运行一个框架需要对Application进行编译,这个过程中需要选择一些合适的Bundle并定义框架的上下文。
这需要选择运行时的初始需求(initial requirements ),然后bnd会将它们解析为一系列的可运行的Bundle(Run Bundles)。一旦我们获取到了这些Run Bundles,就可以将它Export到一个可执行的JAR或其他格式的文件中。
确保你处在顶层文件夹中:
1 |
$ cd ~/workspaces/osgi.enroute.examples.eval |
POM文件
在 osgi.enroute.examples.eval文件夹中,我们需要在一个新建的bndrun文件夹中创建 pom.xml文件。
1 2 3 4 |
osgi.enroute.examples.eval $ mkdir bndrun osgi.enroute.examples.eval $ cd bndrunbnd run $ vi pom.xml // 增加如下文件: |
1 2 3 4 5 6 7 8 9 10 |
<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> <parent> <groupId>org.osgi</groupId> <artifactId>osgi.enroute.examples.eval</artifactId> <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>osgi.enroute.examples.eval.bndrun</artifactId> <packaging>jar</packaging> |
我们将会在一个bndrun文件中定义OSGi运行时环境。这个文件包含了定义一个OSGi运行时所需的大量细节。例如类路径、Bundle清单、系统属性、框架配置等等。我们将会使用 bnd-export-maven-plugin。这个插件会将bndrun文件作为输入并生成一个可执行JAR。这个JAR中包含了所有运行所需的依赖。
1 2 3 |
<build> <plugins> <plugin> |
我们使用3.4.0-SNAPSHOT版,因为本教程中需要3.3版中没有的新的功能。
1 2 3 |
<groupId>biz.aQute.bnd</groupId> <artifactId>bnd-export-maven-plugin</artifactId> <version>3.4.0-SNAPSHOT</version> |
我们需要配置该插件。
1 2 |
<resolve>true</resolve> <bndruns> |
<bndrun>osgi.enroute.examples.eval.bndrun</bndrun>这里我们可以指定一个或多个bndrun文件。我们将会在后续讨论这个文件的格式。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
</bndruns> <targetDir>.</targetDir> </configuration> <executions> <execution> <goals> <goal>export</goal> </goals> </execution> </executions> </plugin> </plugins> </build> |
我们需要将Provider添加到运行时依赖中:
1 2 3 4 5 6 |
<dependencies> <dependency> <groupId>org.osgi</groupId> <artifactId>osgi.enroute.examples.eval.simple.provider</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> |
我们还需要一个发行版(distro)。到目前为止,我们已经使用基于OSGi enRoute的API对API进行了编译。然而,我们现在需要添加服务实现。服务实现可以有不同的来源,例如IBM websphere,Karaf,Knopflerfish,Apache Felix等等。不过OSGi enRoute工程已经创建了一个由多个开源工程组成的distro来展示OSGi的互操作性。
1 2 3 4 5 6 7 |
<dependency> <groupId>org.osgi</groupId> <artifactId>osgi.enroute.pom.distro</artifactId> <version>2.0.0</version> </dependency> </dependencies> </project |
我们必须在父pom.xml中将bndrun添加为module,例如,在已有的api和simple.provider module之后。
Bndrun文件
osgi.enroute.examples.eval.bndrun bndrun文件包含了OSGi运行时的规范。一个OSGi运行时需要相当多的信息,而我们将这些信息全都放到了这个文件中。
1 2 |
bndrun $ vi osgi.enroute.examples.eval.bndrun // 添加如下文件内容 |
指令-standalone表示不是运行在bndtools中,而是作为一个独立定义。
1 |
-standalone: |
bndrun文件通过Bnd Pom仓库来使得我们访问此工程的所有依赖。然后我们需要定义snapshot URL和release URL的清单。
1 2 3 4 5 6 7 |
-plugin.examples.eval = \ aQute.bnd.repository.maven.pom.provider.BndPomRepository; \ snapshotUrls=https://oss.sonatype.org/content/repositories/osgi/; \ releaseUrls=https://repo1.maven.org/maven2/; \ pom=${.}/pom.xml; \ name=examples.eval; \ location=${.}/target/cached.xml |
在-runrequires部分,我们列出了运行时需要的OSGi依赖清单。最初我们仅需要运行Provider。-runrequires的语法和OSGi requirement的语法一样,与OSGi Require-Capability数据头中的用法相同。其中的每一个子句都是由一个命名空间(namespace)和一个过滤器(filter)组成。namespace定义了一些属性(Properties)而filter是基于这些Properties的声明(assertion)。在本例中我们使用身份命名空间(Identity namespace)来指定特定的Bundle,即Provider Bundle。对应的属性名是 osgi.identity ,后面紧跟着的命名空间和BSN(Bundle Symbolic Name)是osgi.enroute.examples.eval.simple.provider。
1 2 3 |
-runrequires: \ osgi.identity; \ filter:='(osgi.identity=osgi.enroute.examples.eval.simple.provider)' |
指令-runfw指定了我们准备使用的框架。
1 2 |
-runfw: org.eclipse.osgi;version='[3.10.100.v20150529-1857,3.10.100.v20150529-1857]' |
我们可以控制运行期间的日志信息。让我们暂时关闭这个开关:
1 |
-runtrace: false |
在本例中我们使用了Equinox,它有一些习惯性用法。例如,它有一个内置的shell,不过建议定义使用标准的OSGi shell。这里不会对这些设置进行进一步的解释。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# # OSGi enRoute设置。这些设置解决了一些Equinox默认情况下的一些问题 # -runee: JavaSE-1.8 -resolve.effective: resolve, active -runproperties.eqnx: \ osgi.console.enable.builtin=false, \ osgi.console=, \ org.osgi.service.http.port=8080 -runpath.eqnx: osgi.enroute.equinox.log.adapter -runrequires.eqnx: \ osgi.identity;filter:='(osgi.identity=org.apache.felix.log)' -runsystempackages.eqnx: javax.script -runsystemcapabilities.dflt: ${native_capability} |
如何获得 -runbundles
到目前为止的定义并不能运行。我们需要解析bndrun文件。解析过程会使用-runrequires指令、Bundle仓库、并计算一个Bundle闭包。这个闭包就是在 –runbundles中列出的我们在运行时中会用到的Bundle。
我们可以通过Maven来解析对应的Requirements,并且通过在此工程中运行mvn install命令来获得Bundle清单。这个命令会尝试解析对应的初始需求(Initial Requirements)和Bundle清单。如果这个清单与-runbundles设置的不同则install会失败,不过命令会给出计算出来的Bundle清单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
bndrun $ mvn install ... -runbundles: \ org.apache.felix.configadmin; version='[1.8.8,1.8.9)',\ org.apache.felix.log; version='[1.0.1,1.0.2)',\ org.apache.felix.scr; version='[2.0.2,2.0.3)',\ org.eclipse.equinox.metatype; version='[1.4.100,1.4.101)',\ org.osgi.service.metatype; version='[1.3.0,1.3.1)',\ osgi.enroute.examples.eval.simple.provider; version='[1.0.0,1.0.1)' [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE ... [INFO] ------------------------------------------------------------------------ |
现在你可以将这个清单复制粘贴到 osgi.enroute.examples.eval.bndrun文件的末尾。确保在bndrun文件中仅有一个 –runbundles指令。
注意:如果你希望更新会自动进行,则你可以在bnd-export-maven-plugin配置项中添加false值。
如果现在我们再次运行Maven,运行成功后会在工程文件夹中创建一个JAR文件。
1 2 3 4 5 6 7 |
bndrun $ vi osgi.enroute.examples.eval.bndrun // 增加/替换 –runbundles的内容 bndrun $ mvn install ... bndrun $ ls osgi.enroute.examples.eval.bndrun pom.xml target osgi.enroute.examples.eval.jar src |
运行
现在我们可以按照如下指令来运行应用程序:
1 2 3 4 5 |
bndrun $ java -version java version "1.8.0_25" Java(TM) SE Runtime Environment (build 1.8.0_25-b17) Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode) bndrun $ java -jar osgi.enroute.examples.eval.jar |
输出的信息会有一些令人尴尬……
尽管让人失望,但是由于我们并未创建能给出可视化信息的Bundle,这些输出还是有意义的。不难理解并没有太多的输出信息。
你可以使用Ctrl+C来退出应用程序。
跟踪
由于我们没有看到任何输出信息,因此如果能知道程序行是否正常是很有用的。我们可以在osgi.enroute.examples.eval.bndrun文件中将-runtrace指令设置为true,这样可以查看运行的情况:
1 |
-runtrace: true |
如果我们构建并运行应用程序,将会按到如下信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
bndrun $ vi osgi.enroute.examples.eval.bndrun // set -runtrace: true bndrun $ mvn install ... bndrun $ java -jar osgi.enroute.examples.eval.jar # properties {launch.name=bndrun, osgi.console=, launch.noreferences=false, ... ... Id State Modified Location 0 ACTIV <> System Bundle 1 ACTIV <> jar/org.apache.felix.configadmin-1.8.8.jar 2 ACTIV <> jar/org.apache.felix.log-1.0.1.jar 3 ACTIV <> jar/org.apache.felix.scr-2.0.2.jar 4 ACTIV <> jar/org.eclipse.equinox.metatype-1.4.100.v20150408-1437.jar 5 ACTIV <> jar/org.osgi.service.metatype-1.3.0.jar 6 ACTIV <> jar/osgi.enroute.examples.eval.provider-1.0.0-SNAPSHOT.jar # framework=org.eclipse.osgi.launch.Equinox@7c0e2abd # registered launcher with arguments for syncing # will wait for a registered Runnable |
Gogo Shell输出的信息很多,如果你在运行时遇到了问题,我们会很感谢将这些信息以及Bug报告告诉我们。
Gogo Shell
到目前为止我们尚未讲解使得我们能看到运行时内部情况的shell。最流行的OSGi shell是Gogo shell。我们可以将它作为初始运行需求(initial run requirement)添加到osgi.enroute.examples.eval.bndrun 文件中:
1 2 3 |
-runrequires: \ osgi.identity;filter:='(osgi.identity=osgi.enroute.examples.eval.simple.provider)',\ osgi.identity;filter:='(osgi.identity=osgi.enroute.gogo.shell.provider)' |
我们现在需要解析bndrun文件。我们可以运行mvn install命令,不过由于bundle的新清单与当前的bundle清单不一致会导致运行失败。然后我们需要将-runbundles复制到osgi.enroute.examples.eval.bndrun文件中并替换掉已有的清单。(确保在文件中不要有多个 –runbundles指令。)你可能还希望将-runtrace设置为false来减少输出信息。我们将会获得一个shell;根据它的正常运行我们可以认为框架运行正常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
bndrun $ vi osgi.enroute.examples.eval.bndrun // add the -runrequires for Gogo bndrun $ mvn install .... -runbundles: \ org.apache.felix.configadmin; version='[1.8.8,1.8.9)',\ org.apache.felix.gogo.runtime; version='[0.16.2,0.16.3)',\ org.apache.felix.log; version='[1.0.1,1.0.2)',\ org.apache.felix.scr; version='[2.0.2,2.0.3)',\ org.eclipse.equinox.metatype; version='[1.4.100,1.4.101)',\ org.osgi.service.metatype; version='[1.3.0,1.3.1)',\ osgi.enroute.examples.eval.provider; version='[1.0.0,1.0.1)',\ osgi.enroute.gogo.shell.provider; version='[2.0.0,2.0.1)' .... [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ bndrun $ vi osgi.enroute.examples.eval.bndrun // copy the -runbundles from the output of mvn into the file // replacing the existing -runbundles bndrun $ mvn install ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ bndrun $ java -jar osgi.enroute.examples.eval.jar ____ _ ___ _ __ | _ \ ___ _ _| |_ ___ / _ \ '_ \| |_) / _ \| | | | __/ _ \ | __/ | | | _ < (_) | |_| | |_ __/ \___|_| |_|_| \_\___/ \__,_|\__\___| http://enroute.osgi.org/ G! |
Gogo中有很多命令,你可以在 Gogo App Note这里找到相关介绍。例如:
1 2 3 4 5 6 7 8 9 10 11 |
G! bundles 0|Active | 0|org.eclipse.osgi (3.10.100.v20150529-1857) 1|Active | 1|org.apache.felix.configadmin (1.8.8) 2|Active | 1|org.apache.felix.gogo.runtime (0.16.2) 3|Active | 1|org.apache.felix.log (1.0.1) 4|Active | 1|org.apache.felix.scr (2.0.2) 5|Active | 1|org.eclipse.equinox.metatype (1.4.100.v20150408-1437) 6|Active | 1|org.osgi.service.metatype (1.3.0.201505202024) 7|Active | 1|osgi.enroute.examples.eval.provider (1.0.0.201610030911) 8|Active | 1|osgi.enroute.gogo.shell.provider (2.0.0.201608121439-SNAPSHOT) G! |
用户友好的命令
现在我们运行的是原始的简单Gogo shell。这意味着它可以运行BundleContext之上的命令(即bundles命令被映射到BundleContext.getBundles()),这里有很多对用户友好的命令。很多这样的命令在org.apache.felix.gogo.command bundle中进行了实现。因此我们可以将这个bundle添加到 –runrequires指令之中:
1 2 3 4 |
-runrequires: \ osgi.identity;filter:='(osgi.identity=osgi.enroute.examples.eval.simple.provider)',\ osgi.identity;filter:='(osgi.identity=osgi.enroute.gogo.shell.provider)',\ osgi.identity;filter:='(osgi.identity=org.apache.felix.gogo.command)' |
因此现在你可以重新解析bndrun文件,并且我们可以在Gogo shell中运行help命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
bndrun $ vi osgi.enroute.examples.eval.bndrun // replace the -runrequires bndrun $ mvn install ... -runbundles: ... ... bndrun $ vi osgi.enroute.examples.eval.bndrun // replace -runbundles bndrun $ java -jar osgi.enroute.examples.eval.jar ____ _ ___ _ __ | _ \ ___ _ _| |_ ___ / _ \ '_ \| |_) / _ \| | | | __/ _ \ | __/ | | | _ < (_) | |_| | |_ __/ \___|_| |_|_| \_\___/ \__,_|\__\___| http://enroute.osgi.org/ G! help felix:bundlelevel felix:cd felix:frameworklevel felix:headers ... scr:config scr:disable scr:enable scr:info scr:list G! |
我们学到了什么?
在本章中,通过创建一个bndrun文件, 我们创建了一个OSGi运行时。然后我们学习了如何添加Requirements到文件之中并解析它,因此我们学习了如何使用-runbundles。然后我们学习了如何将这些-runbundles添加到bndrun文件之中,使得它们可以被export到一个可执行jar文件中。
然后我们执行了这个JAR并且添加了一个Gogo shell。


from: 新闻快报(2018-04-15) | JavaFX、OSGi、Eclipse开源资料