基于maven快速搭建自定义的karaf开发调试环境
本文目的
Apache Karaf项目在基于OSGi的组件框架应用开发中为开发者和架构师提供了一个便利的基础运行和部署框架。通过Karaf的Feature定义及Kar打包,开发者可以*的定义OSGi Bundle的分组并按需定制细粒度的打包定义,在系统发布时,通过*组合这些feature及kar,可以快速发布针对性的产品或特定的发布包。
Karaf通过与maven相结合,可以为用户基于OSGi Bundle的模块化开发、测试、集成和持续交付提供方便和快速的解决方案。
本文为主要探讨在开发阶段如何快速搭建基于maven的自定义的karaf开发调试环境提供一种方案,对于想对karaf的配置环境进行自定义和裁剪的开发人员可以参考此方案。
Karaf概念基础
关于Karaf项目为OSGi基础运行环境提供的功能请参考其官方网站。这里,我重点提一下Karaf的Feature定义和Kar打包。
Karaf的Feature定义
Karaf的Feature概念可以看作是一个系统的子系统实现。我们知道OSGi是基于Bundle和Service进行开发的,对于Bundle的粒度控制需要开发人员根据项目和系统功能凭借经验自己控制。在一个大的系统中,可能存在成百上千的Bundle,这么多Bundle如果聚合在一起,如何区分和维护将是一个巨大的挑战,这往往导致一些开发人员和架构师对OSGi模块化望而却步。而通过Karaf的Feature定义,最小单元的OSGi Bundle可以根据功能部分聚合在一起形成一个功能Feature,多个Feature可以聚合在一起形成一个大的Feature,最终所有的OSGi Bundle就有序的组合起来,就可以形成清晰的,可重复利用的一个个功能Feature,实现系统的真正模块化开发和组件的重复利用。
现在,我们来看一个Karaf的Feature定义:
<feature resolver="(obr)" description="Implementation of the OSGI HTTP Service" version="3.0.0-SNAPSHOT" name="http"> <feature version="3.0.4-SNAPSHOT">pax-http</feature> <bundle start-level="30">mvn:org.apache.karaf.http/org.apache.karaf.http.core/3.0.0-SNAPSHOT</bundle> <bundle start-level="30">mvn:org.apache.karaf.http/org.apache.karaf.http.command/3.0.0-SNAPSHOT</bundle> </feature>
从这个Feature定义可以看到,此Feature定义了OSGi中提供Http服务的功能,Feature里有karaf的两个http功能相关的bundle,同时,这个feature也对ops4j的Pax web项目提供的一组bundle组成的feature “pax-http”具有依赖关系。
当Karaf运行时,如果加载了此feature(位于Karaf的standard feature库中)和其所依赖的pax-http feature(位于pax-web-features库中),同时指定启动http featue,则Karaf启动时自动加载并启动这一组相关的bundle集。
Karaf Kar打包
Karaf的Kar打包功能存在于karaf的karaf-maven-plugin插件中。通过此插件,karaf可以将featue定义中的所有bundle及其依赖打包到一个以.kar为后缀的压缩文件中,形成可发布的组件包。通过karaf-maven-plugin插件与maven打包相关的其它插件配合,用户可以*定义发布包的结构。
对于多个已定义的kar分发包,通过maven依赖,可以在一个最终的maven发布工程中打包在一起,形成一个产品的发布包。
基于Maven的Karaf自定义调试环境搭建过程
下面简要讲述一下基于maven的Karaf自定义调试环境的搭建过程。通常,基于OSGi的开发,开发人员往往依赖Eclipse的插件开发环境,实际上,基于maven的OSGi插件开发(Felix的maven-bundle-plugin插件)同样方便、快速和高效,而且不受开发环境的限制。基于maven的OSGi开发,这里推荐使用Netbeans IDE,Netbeans对maven项目具有原生支持,可以自动解析maven的pom构建工程。
第一步,在pom中配置对karaf的依赖和启动配置
<?xml version="1.0" encoding="UTF-8"?> <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> <artifactId>karaf</artifactId> <groupId>ossu.sandbox.karaf</groupId> <version>2.0.0-SNAPSHOT</version> </parent> <groupId>ossu.sandbox.karaf</groupId> <artifactId>karaf.launcher</artifactId> <packaging>pom</packaging> <name>Ossu Sandbox :: Karaf :: Launcher</name> <description>Run karaf instance or debug karaf instance</description> <dependencies> <dependency> <groupId>org.apache.karaf.features</groupId> <artifactId>framework</artifactId> <type>kar</type> </dependency> <dependency> <!-- scope is runtime so the feature repo is listed in the features service config file, and features may be installed using the karaf-maven-plugin configuration --> <groupId>org.apache.karaf.features</groupId> <artifactId>standard</artifactId> <classifier>features</classifier> <type>xml</type> <scope>runtime</scope> </dependency> <dependency> <!-- scope is runtime so the feature repo is listed in the features service config file, and features may be installed using the karaf-maven-plugin configuration --> <groupId>org.apache.karaf.features</groupId> <artifactId>spring</artifactId> <classifier>features</classifier> <type>xml</type> <scope>runtime</scope> </dependency> <dependency> <groupId>ossu.sandbox.karaf</groupId> <artifactId>karaf.boilerplate.framework</artifactId> <type>kar</type> <version>${project.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.karaf.tooling</groupId> <artifactId>karaf-maven-plugin</artifactId> <executions> <execution> <id>process-resources</id> <phase>process-resources</phase> <goals> <goal>install-kars</goal> </goals> </execution> </executions> <configuration> <installedFeatures> <feature>wrapper</feature> </installedFeatures> <bootFeatures> <feature>framework</feature> <feature>standard</feature> <!--<feature>obr</feature>--> <feature>region</feature> <!--<feature>spring</feature>--> </bootFeatures> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <executions> <execution> <goals> <goal>exec</goal> </goals> </execution> </executions> <configuration> <executable>java</executable> <workingDirectory>${project.basedir}/target/assembly</workingDirectory> <arguments> <argument>-classpath</argument> <argument>${project.basedir}/target/assembly/conf${path.separator}${project.basedir}/target/assembly/lib/karaf-jaas-boot.jar${path.separator}${project.basedir}/target/assembly/lib/karaf-jmx-boot.jar${path.separator}${project.basedir}/target/assembly/lib/karaf-org.osgi.core.jar${path.separator}${project.basedir}/target/assembly/lib/karaf.jar</argument> <argument>-Xmx512m</argument> <argument>-XX:MaxPermSize=512m</argument> <argument>-Dkaraf.startRemoteShell=true</argument> <argument>-Djava.net.preferIPv4Stack=true</argument> <argument>-Dderby.system.home=${project.basedir}/target/assembly/data/derby</argument> <argument>-Dderby.storage.fileSyncTransactionLog=true</argument> <argument>-Dcom.sun.management.jmxremote</argument> <argument>-Dkaraf.startLocalConsole=true</argument> <argument>-Djline.WindowsTerminal.directConsole=false</argument> <argument>-Dkaraf.home=${project.basedir}/target/assembly</argument> <argument>-Dkaraf.base=${project.basedir}/target/assembly</argument> <argument>-Dkaraf.etc=${project.basedir}/target/assembly/etc</argument> <argument>-Dkaraf.instances=${project.basedir}/target/assembly/instances</argument> <argument>-Djava.io.tmpdir=${project.basedir}/target/assembly/data/tmp</argument> <argument>-Djava.endorsed.dirs=${project.basedir}/target/assembly/lib/endorsed</argument> <argument>-Dkaraf.data=${project.basedir}/target/assembly/data</argument> <argument>-Djava.util.logging.config.file=${project.basedir}/target/assembly/etc/java.util.logging.properties</argument> <!-- Debug configuration --> <argument>-Xdebug</argument> <argument>-Djava.compiler=NONE</argument> <argument>-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005</argument> <argument>org.apache.karaf.main.Main</argument> </arguments> </configuration> </plugin> </plugins> </build> </project>
通过这个pom,我们既可以在maven环境中启动karaf并进行调试。下面做一下详细说明:
1)依赖部分
主要包括对karaf Framework kar的依赖,这是karaf框架的kar发布包,通过对其依赖,在运行时,karaf的基础目录结构将被创建(位于该pom所在工程的target/assembly下);
对karaf的standard Feature库和spring feature库进行依赖,通过对这两个feature库进行依赖,karaf在运行时可以知道到这两个feature库中查找具体的feature定义
对ossu.sandbox.karaf:karaf.boilerplate.framework这个kar工程的依赖(这个kar是对karaf的具体裁剪,后面会讲到)。
2)编译运行部分
编译运行部分主要包括两个maven插件:karaf-maven-plugin和exec-maven-plugin。
karaf-maven-plugin
此插件对依赖(jar、kar等)进行打包,生成发布kar包,并可以指定启动哪些feature
<bootFeatures> <feature>framework</feature> <feature>standard</feature> <!--<feature>obr</feature>--> <feature>region</feature> <!--<feature>spring</feature>--> </bootFeatures>
exec-maven-plugin
此插件用于在maven工程中启动一个java虚拟机,此处主要是配置了karaf的启动参数并通过org.apache.karaf.main.Main入口启动Karaf。
3)启动Karaf
命令行环境下输入:
mvn clean package exec:exec
输出如下:
在Netbeans IDE环境中启动执行,如下图所示,右键点击工程,在弹出菜单中选择定制——目标:
在弹出窗口中输入:
clean package exec:exec
如下图所示
点击“确定”,执行结果如下图
注意的几点
1)限于篇幅,对于karaf的裁剪和自定义,将在后续文章中探讨。
2)karaf启动时开启了5005调试端口,可以连接上进行代码调试
3)此示例工程代码位于github的https://github.com/xqttrc/sandbox工程下
4)此工程代码对https://github.com/xqttrc/nebula项目下的parent工程有依赖,可以将此工程下的pom拿下来单独编译,也可以自行调整。
上一篇: 请访问http://chrisrc.me关注新的博客
下一篇: 基于Karaf的项目离线打包与发布