OSGi enRoute – 2.3_6 – Command 工程
在本章你将学到什么
到目前为止,Provider已经在框架中注册了一个Eval Service,但并没有人来调用它。在本章中,我们将会开发一个简单的Gogo命令,它使得我们可以调用这个Service,并且能够通过命令行来测试它。
一个Gogo命令是一个带有一些有趣的属性(Properties)的简单Service。它可以实现多个命令。
确保你位于顶层文件夹中:
1 |
$ cd ~/workspaces/osgi.enroute.examples.eval |
创建一个 POM
我们需要在 osgi.enroute.examples.eval文件夹中创建一个名为command的文件夹。在这个文件夹中我们需要创建一个pom.xml文件。这个POM现在是标准化的内容:
1 2 3 4 |
osgi.enroute.examples.eval $ mkdir command osgi.enroute.examples.eval $ cd command command $ vi pom.xml // 添加pom.xml |
增加如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<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> <packaging>jar</packaging> <artifactId>osgi.enroute.examples.eval.command</artifactId> <dependencies> <dependency> <groupId>org.osgi</groupId> <artifactId>osgi.enroute.examples.eval.api</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> </dependencies> </project> |
我们还必须在Parent pom.xml中将Command添加为Module,和我们在这个教程中之前的步骤一样。
命令(Command)
Gogo Shell非常聪明,它监听带有2个“魔法”属性(Property)的服务。 osgi.command.scope服务属性为Command定义了一个scope。 osgi.command.function包含了一个命令清单。它们会映射到Service Object的方法上。这些Service Property Key被定义在OSGi enRoute API的Debug类中。
我们的命令实现会将命令行中所有给出的字符串连接起来,并且调用计算器Eval Service。在Gogo中,Command仅返回命令的value。Gogo将会以最佳的方式自动格式化结果。也就是说,不要使用返回String的main方法的风格来编写Command。Command方法是普通的方法,并非为shell进行了特殊设计。例如,Gogo会尝试使用bean命名的方式来将类似foo的名称映射到getFoo、setFoo、isFoo方法之上,等等。
我们设计的Command组件依赖Eval Service。因此我们使用DS来向一个实例属性增加一个@Reference注解。这会帮我们在Eval Service可用的时候将其注入。
下面的代码实现了一个带有eval scop和function的Command。
1 2 3 |
command $ mkdir -p src/main/java/osgi/enroute/examples/eval/command command $ vi src/main/java/osgi/enroute/examples/eval/command/EvalCommand.java // 增加Java代码 |
下面是代码内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package osgi.enroute.examples.eval.command; import java.util.stream.Collectors; import java.util.stream.Stream; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import osgi.enroute.debug.api.Debug; import osgi.enroute.examples.eval.api.Eval; @Component(property= { Debug.COMMAND_SCOPE+"=eval", Debug.COMMAND_FUNCTION+"=eval" }, service=EvalCommand.class) public class EvalCommand { @Reference Eval greeter; public double eval(String ... name) throws Exception { return greeter.eval(Stream.of(name).collect(Collectors.joining(" "))); } } |
bnd.bnd 文件
现在不需要bnd.bnd文件,因为默认情况下所有的在工程之内的包都会被放到Bundle之中。这正是我们想要的!
构建
下面我们来安装我们的Bundle:
1 2 |
command $ mvn install ... |
将Command Bundle添加到Runtime中
在bndrun工程中,我们现在必须将Command工程添加到pom之中,以便它称为一个依赖项。除此之外,我们还应该添加Gogo shell,因为它并未被包含在enRoute的发布包中。
1 2 3 |
command $ cd ../bndrun bndrun $ vi pom.xml // 更新dependency部分,新增我们的Command |
在bndrun pom.xml文件中的dependency部分应该看起来如下所示:
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.simple.provider</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>osgi.enroute.pom.distro</artifactId> <version>2.0.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>osgi.enroute.examples.eval.command</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> </dependencies> |
我们还需要将Bundle添加到osgi.enroute.examples.eval/bndrun 文件夹中的bndrun文件的initial Requirements部分:
1 2 |
bndrun $ vi osgi.enroute.examples.eval.bndrun // 替换-runrequires部分 |
1 2 3 4 5 |
-runrequires: \ osgi.identity;filter:='(osgi.identity=osgi.enroute.examples.eval.simple.provider)',\ 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)' |
然后我们运行对应的命令来进行解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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='[1.0.0,1.0.1)',\ org.apache.felix.gogo.runtime; version='[0.16.2,0.16.3)',\ org.apache.felix.gogo.shell; version='[1.0.0,1.0.1)',\ 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)' [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE ... [INFO] ------------------------------------------------------------------------ bndrun $ vi osgi.enroute.examples.eval.bndrun // replace the -runbundles with the given list |
然后将osgi.enroute.examples.eval.bndrun文件中的-runbundles替代为Maven提供的清单。
然后我们应该再次运行Maven来获得我们的JAR。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
bndrun $ mvn install ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS ... [INFO] ------------------------------------------------------------------------ bndrun $ java -jar osgi.enroute.examples.eval.jar ____ _ ___ _ __ | _ \ ___ _ _| |_ ___ / _ \ '_ \| |_) / _ \| | | | __/ _ \ | __/ | | | _ < (_) | |_| | |_ __/ \___|_| |_|_| \_\___/ \__,_|\__\___| http://enroute.osgi.org/ G! eval 3 + 4 7.0 G! |
成功啦!
我们学到了什么?
在本章中我们学习了如何创建一个Gogo shell 命令。我们创建了一个注册了服务的Bundle,并从Gogo shell进行了调用。然后我们使用这个Command对Bundle进行了测试。

