OSGi enRoute – 2.3_7 – Dependencies
在本章中你将学到什么?
在本章中我们将会将之前那个非常简单的解析器替换成Maven Central库中的一个外部依赖项。这个依赖项是Parsii,它是一个非常轻量的表达式解析器。
确认你位于顶层文件夹中:
1 |
$ cd ~/workspaces/osgi.enroute.examples.eval |
创建工程
在osgi.enroute.examples.eval文件夹中的 parsii.provider文件夹中,为osgi.enroute.examples.parsii.provider创建一个新的工程,pom.xml文件应该如下所示:
1 2 3 4 |
osgi.enroute.examples.eval $ mkdir parsii.provider osgi.enroute.examples.eval $ cd parsii.provider parsii.provider $ vi pom.xml // 增加下面的pom |
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 |
<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.parsii.provider</artifactId> <description>Eval Provider based on Parsii library</description> <dependencies> <dependency> <groupId>com.scireum</groupId> <artifactId>parsii</artifactId> <version>2.3</version> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>osgi.enroute.examples.eval.api</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> </dependencies> </project> |
这个与我们之前提供的简单Provider很像,不过现在多了一个外部依赖项Parsii Parser。
源码
我们可以使用如下源码:
1 2 3 |
parsii.provider $ mkdir -p src/main/java/osgi/enroute/examples/eval/parsii/provider parsii.provider $ vi src/main/java/osgi/enroute/examples/eval/parsii/provider/EvalImpl.java //增加下面的代码 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package osgi.enroute.examples.eval.parsii.provider; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.osgi.service.log.LogService; import osgi.enroute.examples.eval.api.Eval; import parsii.eval.Parser; @Component(name = "osgi.enroute.examples.eval.parsii.provider") public class EvalImpl implements Eval { @Reference LogService log; @Override public double eval(String expression) throws Exception { return Parser.parse(expression).evaluate(); } } |
日志服务的引用没有被用到。添加这行的目的是为了解决bnd中的一个bug,它很快会被修复。问题在于对于一个非常简单的DS,依赖项osgi.extender没有被包含进来。
Bundle的布局
这里的bnd.bnd文件比我们以前创建的要稍微复杂一些。原因在于我们添加的依赖项不是一个Bundle,因此我们不能在运行时依赖这个JAR。在本例中,需要使用两种不同的方法。你可以封装(wrap)或包含(include)这个Bundle。对一个Bundle进行wrap意味着创建一个新的工程并提供OSGi元数据。Include对应的JAR则意味着通过bnd的Private-Package指令从JAR中将所需的包都Include进来,
在本例中我们选择了后者,因此bnd.bnd文件将会如下所示:
1 2 |
parsii.provider $ vi bnd.bnd // 添加如下的 bnd.bnd |
1 2 3 4 5 |
Export-Package: osgi.enroute.examples.eval.api Private-Package: \ parsii.*, \ osgi.enroute.examples.eval.parsii.provider |
与在simple provider中一样,我们已经export了API。不过,与在simple provider中我们默认使用工程中所有的类不同,在这里我们精确列出了希望使用的包。
在build过程中,Maven不会自动清理classes文件夹。这意味着只有在执行了mvn clean命令之后,你才可以确保内容的正确性。在实际情况中,在该文件夹下一般会存放着长期实验过程中产生的类文件和bnd.bnd文件。
构建
再次提醒下,不要忘记在parent pom文件中添加parsii.provider的module信息。
现在我们来构建对应的bundle:
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 |
parsii.provider $ mvn install ... parsii.provider $ bnd print target/osgi.enroute.examples.eval.parsii.provider-1.0.0-SNAPSHOT.jar [MANIFEST osgi.enroute.examples.eval.parsii.provider-1.0.0-SNAPSHOT] Bnd-LastModified 1475601027531 Build-Jdk 1.8.0_25 Built-By aqute Bundle-ManifestVersion 2 Bundle-Name osgi.enroute.examples.eval.parsii.provider Bundle-SymbolicName osgi.enroute.examples.eval.parsii.provider Bundle-Version 1.0.0.201610041710 Created-By 1.8.0_25 (Oracle Corporation) Export-Package osgi.enroute.examples.eval.api;version="1.0.0" Import-Package osgi.enroute.examples.eval.api;version="[1.0,1.1)" Manifest-Version 1.0 Private-Package parsii.tokenizer,parsii.eval,osgi.enroute.examples.eval.parsii.provider Provide-Capability osgi.service;objectClass:List<String>="osgi.enroute.examples.eval.api.Eval" Require-Capability osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))" Service-Component OSGI-INF/osgi.enroute.examples.eval.parsii.provider.xml Tool Bnd-3.3.0.201609221906 [IMPEXP] Import-Package osgi.enroute.examples.eval.api {version=[1.0,1.1)} Export-Package osgi.enroute.examples.eval.api {version=1.0.0, imported-as=[1.0,1.1)} |
在信息中显示出了bnd添加的Private-Package header,它清晰地显示出我们已经添加了在bundle中找到的parsii包。我们在bnd.bnd文件中为Private-Packages指定了一个通配符,但是在manifest中我们可以清晰地看到在类路径中的包是parsii.tokenizer 和 parsii.eval。
运行
我们现在应该切换到bndrun工程中。
1 2 3 |
parsii.provider $ cd ../bndrun parsii.provider $ vi pom.xml // 使用下面的dependencies替换这句话 |
我们首先需要在此工程中的pom.xml中将simple provider替换为新的eval parser,使得它可以被解析器使用到。因此dependencies元素应该看起来如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<dependencies> <dependency> <groupId>org.osgi</groupId> <artifactId>osgi.enroute.examples.eval.parsii.provider</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.apache.felix</groupId> <artifactId>org.apache.felix.gogo.shell</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>osgi.enroute.examples.eval.command</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>osgi.enroute.pom.distro</artifactId> <version>2.0.0</version> </dependency> </dependencies> |
在bndrun工程中的osgi.enroute.examples.eval.bndrun文件中,我们需要修改-runrequires,使用parsii.provider来替代simple provider:
1 2 3 |
parsii.provider $ cd ../bndrun bndrun $ vi osgi.enroute.examples.eval.bndrun // 替代-runrequires |
1 2 3 4 5 |
-runrequires: \ osgi.identity;filter:='(osgi.identity=org.apache.felix.gogo.shell)',\ osgi.identity;filter:='(osgi.identity=org.apache.felix.gogo.command)',\ osgi.identity;filter:='(osgi.identity=osgi.enroute.examples.eval.command)',\ osgi.identity;filter:='(osgi.identity=osgi.enroute.examples.eval.parsii.provider)' |
然后进行解析,看起来应该如下所示
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.gogo.command; version='[0.16.0,0.16.1)',\ 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.command; version='[1.0.0,1.0.1)',\ osgi.enroute.examples.eval.parsii.provider; version='[1.0.0,1.0.1)',\ org.apache.felix.gogo.shell; version='[2.0.0,2.0.1)' ... |
然后使用返回的 -runbundles信息来更新osgi.enroute.examples.eval.bndrun 文件,然后再次运行mvn install。
然后我们可以运行应用程序:
1 2 3 4 5 6 7 8 9 10 11 12 |
bndrun $ java -jar osgi.enroute.examples.eval.jar ____ _ ___ _ __ | _ \ ___ _ _| |_ ___ / _ \ '_ \| |_) / _ \| | | | __/ _ \ | __/ | | | _ < (_) | |_| | |_ __/ \___|_| |_|_| \_\___/ \__,_|\__\___| http://enroute.osgi.org/ G! eval sin(pi) 1.2246467991473532E-16 G! eval cos(pi) -1.0 G! |
在本章中我们学到了什么?
我们创建了一个新的provider,它使用了一个外部dependency。我们需要将这个dependency中的代码包含到我们的新bundle之中,因为Parsii JAR中没有OSGi元数据。然后我们将这个新的工程添加到了module信息之中并更新了bndrun工程,其中使用了新的Parsii provider。
然后它们正常工作了!

