卡拉夫特色和OSGi服务:捆绑


在完成一个pairarticles上周在Karaf特性上,我觉得我在解释所有这些捆绑和特色化发生的上下文方面做得很差。相反,我基本上是从中间开始的,假设OSGi捆绑了适当的清单,所有这些都在它们的Maven存储库中。

因此,我将纠正这一点,同时说明另一种很酷的OSGi技术:声明性服务。要做到这一点需要一些时间,并且需要从detailed example

适度快乐的OSGi捆绑包

首先,我们需要知道如何制作OSGi包。在我们费心做这些之前,先来讨论一下什么是捆绑包。

OSGi是一种构建模块化应用程序的方法。其思想是每个模块都非常具体地说明其唯一的名称、版本、它对其他模块的要求,以及它提供的允许其他模块使用的内容。在Java中,这些模块中的每个模块都打包到一个JAR文件中,并在META-INF/MANIFEST.MF文件。此附加信息包括Java包形式的导入和导出。具有正确清单内容的正确打包的JAR文件称为OSGi包。下面是一个简单的示例清单,在构建时打包到JAR中:

Manifest-Version: 1.0
Bnd-LastModified: 1477440189494
Build-Jdk: 1.8.0_91
Built-By: ahohn
Bundle-ManifestVersion: 2
Bundle-Name: Greeter Interfaces
Bundle-SymbolicName: org.anvard.karaf.greeter.interfaces
Bundle-Version: 1.0.0.SNAPSHOT
Created-By: Apache Maven Bundle Plugin
Export-Package: org.anvard.karaf.greeter.api;version="1.0.0.SNAPSHOT"
Tool: Bnd-1.50.0


这里有几点需要注意:

  • Bundle-SymbolicName很重要,而且需要是独一无二的。
  • 我们可以指定一个Bundle-Version以及我们导出的任何包的版本。下一次我们将看到一个包,它导入了这个包;版本很重要。

我们可以自己创建此清单内容,无论我们是否运行jar命令或使用构建工具(如Maven jar插件)。但是这是大量的手动工作,并且涉及到大量的冗余,特别是在我们已经在指定工件名称、版本和依赖项的Maven项目中。幸运的是,OSGi专家Peter Kriens创建了一个名为bnd。BND工具能够扫描Java代码以识别来自模块外部的包导入,并使用更干净的配置文件作为源来为生成正确的OSGi内容META-INF/MANIFEST.MF

更进一步的是maven-bundle-plugin。该插件允许在Maven POM中指定所需的信息,而不是使用单独的配置文件。它还利用Maven依赖关系来确定需要哪些版本的包导入。要获得上面显示的清单,我们需要POM文件中的以下配置:

    <packaging>bundle</packaging>
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>2.3.7</version>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-Name>${project.name}</Bundle-Name>
                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
                        <Export-Package>
                            org.anvard.karaf.greeter.api
                        </Export-Package>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>


请参阅GitHub repository对于完整的pom.xml

捆绑和卡拉芬

现在我们已经有了构建OSGi包的方法,我们可以将其安装到本地Maven存储库,然后使用Karaf从Maven解析包的功能将其加载到Karaf中。

首先,我们使用Maven编译包:

$ mvn clean install

[ Lots of output; Internet downloaded ]

[INFO] --- maven-bundle-plugin:2.3.7:install (default-install) @ interfaces ---
[INFO] Installing org/anvard/karaf/greeter/interfaces/1.0-SNAPSHOT/interfaces-1.0-SNAPSHOT.jar
[INFO] Writing OBR metadata
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.829 s
[INFO] Finished at: 2016-10-25T20:33:25-04:00
[INFO] Final Memory: 19M/212M
[INFO] ------------------------------------------------------------------------


现在我们可以装上卡拉夫了。从一个标准开始Karaf distribution

apache-karaf-4.0.7$ bin/karaf

...

karaf@root()> install mvn:org.anvard.karaf.greeter/interfaces/1.0-SNAPSHOT
Bundle ID: 52
karaf@root()> list
START LEVEL 100 , List Threshold: 50
ID | State     | Lvl | Version        | Name
----------------------------------------------------------
52 | Installed |  80 | 1.0.0.SNAPSHOT | Greeter Interfaces
karaf@root()>


Karaf有一些很好的特性,可以利用OSGi的模块性在OSGi包上进行开发。例如,既然我们已经安装了包,并且知道了它的ID,我们就可以使用update 52从Maven获取最新的快照。这包括停止现有的捆绑包、安装较新的版本和启动较新的版本。这是可行的,因为OSGi小心翼翼地保持包的分离,即使是在单独的类加载器的范围内,因此很容易丢弃包并加载到新的包中,即使类是相同的。

包扎

此时,我们有一个捆绑包,其中包含一些Java代码,但它除了导出代码供其他捆绑包使用外,没有做任何其他事情。下一次,我将稍微讨论一下示例的结构,以及为什么将5个Java文件拆分到4个捆绑包中。