您的位置:首页 > 其它

Karaf教程之Config Admin服务的使用

2017-12-20 13:26 204 查看

目录

摘要

配置管理服务规范

如何使配置生效

引入简单的可配置类

动手实践。使用OSGi接口方式实现配置

例子运行

深入Karaf配置命令

使用Blueprint配置

部署配置文件

总结和展望未来

参考文献

摘要

在Karaf教程的第一部分,我们学习了如何使用maven和blueprint提供和使用pojo服务,以及如何使用http服务发布一个servlet。

在第二部分,我们关注OSGi bundles的配置。和servlet容器不同,对于配置OSGi包含了一个非常好的规范:来自OSGi企业规范的配置管理服务。在该教程中,将涉及分别通过OSGi和blueprint方式来使用配置管理服务,以及如何使配置文件和bundles自动化部署。

教程的代码可以在github查阅,地址Here

配置管理服务规范

首先我们看下配置服务规范概览。这里使用到主要有以下两个接口:

ConfigurationAdmin -允许检索和改变配置。这个服务是配置管理服务实现提供的接口。

ManagedService -配置发生改变的时候,允许做出响应。你不得不实现这个接口,并且把它注册为一个服务来获取通告。

所以基本上在配置管理服务中的配置是一个字典,这个字典包含了属性和相应的值。字典被一个持久化标识符(persistent identifier (pid))标识.标识是一个简单的字符串,且唯一的标识该配置。

如何使配置生效

可以通过使用ConfigurationAdmin.getConfiguration接口检索一个配置,但不推荐这么做。OSGi是动态的以至于可能发生这样的情况,bundles在config admin服务或者config admin服务还没有读取配置之前启动了。所以有时可能获取到一个null配置。

因此推荐的方式是使用ManagedService服务来监听更新。如果因为没有配置bundle不能启动,则可在第一次更新消息被接收的时,通过创建一个可配置的pojo对象是一个不错的主意。

引入简单的可配置类

按照需求,可配置的类应该是pojo。虽然可以简单地实现ManagedService接口并直接使用Dictionary,这需要依赖于OSGi和当前的Config Admin Service规范。因此改用一个具有title属性的简单bean类。另外添加了一个刷新方法,在配置项被更改之后应该被调用。

public class MyApp {

String title;

public void setTitle(String title) {
this.title = title;
}

public void refresh() {
System.out.println("Configuration updated (title=" + title + ")");
}
}


我们的目的是配置tilte,当配置改变的时候要调用refresh方法。我们将使用OSGi方式和blueprint两种方式实现。

动手实践。使用OSGi接口方式实现配置

首先在本节展示通过使用OSGi接口如何使用config admin服务。然而这绝不可能是你以后要这么实现。这仅仅是帮助你理解在钩子下发生了什么。

你可以在这个子目录下configapp找到实现(https://github.com/cschneider/Karaf-Tutorial/tree/master/configadmin/configapp)

首先我们需要一个pom文件用于maven编译。你最好从例子中configapp的pom开始看起。

如果你才刚开始,你将不得不使用maven-bundle-plugin编译你的工程为一个OSGi bundle,且你需要添加两个依赖:

<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.2.0</version>
</dependency>


第一个依赖是用于config admin服务相关接口,第二个依赖是用于创建Activator和包含基本的OSGi相关的接口。

现在我们将专注修订MyApp类。下面的类达到了目的。我们实现了ManagedService接口用于和Config Admin服务交互。无论什么时候配置发生变化,ConfigUpdater都被调用。

第一件事是检查是否为null,这个情况是可能发生的,当config被移除的时候。关于这个步骤我们可以停掉MyApp运行,但是为了保持简单我们仅仅是忽略了这些问题。下一步是创建一个MyApp实例。

正常情况,你将在Activator完成这个步骤,但是你将不得不考虑空配置的情况,这种情况不是我们期望的。最后一步是简单地从config获取一个值传入setter方法并调用,且在设置完所有配置后调用refresh方法。

private final class ConfigUpdater implements ManagedService {

public void updated(Dictionary config) throws ConfigurationException {
if (config == null) {
return;
}

if (app == null) {
app = new MyApp();
}

app.setTitle((String)config.get("title"));
app.refresh();
}
}


当然这样还没有完成所有事情,最后一步是在Activator.start注册ConfigUpdater。类似其他服务一样我们简单地使用了registerService。唯一特别的事情是你不得不设置属性SERVICE_PID到你的配置pid,这样Config Admin服务就知道你想要监听的是什么配置了。

Hashtable<String, Object> properties = new Hashtable<String, Object>();
properties.put(Constants.SERVICE_PID, CONFIG_PID);
serviceReg = context.registerService(ManagedService.class.getName(), new ConfigUpdater() , properties);


例子运行

运行mvn install编译工程.

启动一个新的Karaf实例

从target目录复制configapp.jar bundle到Karaf deploy目录

现在我们注意到好像什么事都没发生。在Karaf控制台调用list你应该能够看到bundle实际上是已经启动,但是却没有任何输出,因为没有配置。我们仍然需要创建配置文件和设置tilte。

- 复制已经存在的文件/configadmin-features/src/main/resources/ConfigApp.cfg 到Karaf实例中的/etc目录

这里重要的部分是文件名必须是.cfg。这样config admin服务能够发现它。

现在fileinstall bundle将在etc目录下侦测到新的文件。当以.cfg结尾的文件将被当作配置管理资源且根据文件名pid来创建或者更新对应的Config Admin服务配置。

所以现在你应该在Karaf控制台能看到如下输出。这显示了配置的变化被检测和转发。如果你现在用编辑器修改文件内容和保存修改,修改将被通告。

Configuration updated (title=" + title + ")


深入Karaf配置命令

在Karaf控制台输入如下:

> config:list
Pid:            ConfigApp
BundleLocation: file:/C:/java/apache-karaf-2.2.3/deploy/configapp.jar
Properties:
service.pid = ConfigApp
felix.fileinstall.filename = file:/C:/java/apache-karaf-2.2.3/etc/ConfigApp.cfg
title = my Title


在配置列表中你应该能够找到配置ConfigApp。这个配置显示配置文件从哪里加载的,pid标识符和在文件中设置的所有属性。

我们也可以修改配置:

> config:edit ConfigApp
> config:propset title "A better title"
> config:proplist
service.pid = ConfigApp
felix.fileinstall.filename = file:/C:/java/apache-karaf-2.2.3/etc/ConfigApp.cfg
title = A better title
> config:update
Configuration updated (title=A better title)


我们发现修订直接通告到bundle,如果你查看etc下配置文件,你可以发现修订也被持久化到文件了。所以在重启Karaf后修订仍然生效。

使用Blueprint配置

继我们用OSGi实现和Config Admin服务交互后,现在我们将看下使用Blueprint怎么实现相同的功能。幸运地是这种方式十分的简单,Blueprint做了大部分的事情。

简单的定义一个cm:property-placeholder元素。类似文件中的属性占位符但是这个是和Config Admin服务起作用。我们需要提供config PID和更新策略。当我们选择reload策略,这意味着一个修订发生,blueprint的上下文环境会重新加载反映这个修订。当config PID没有找到或者属性不存在,将设置为默认属性值。

和bean类集成通常是一个简单的bean定义,这个bean是定义了title属性和分配了一个占位符。通过使用config admin服务解析这个占位符。唯一特别是的事情是init-method。

这被用于在配置修订后,我们机会去做相应的事情。例如上面的OSGi例子。

因为blueprint我们不需要任何maven依赖,因此java代码仅是一个Java bean时。通过把它放在OSGI-INF/blueprintblueprint目录和blueprint extender被加载,环境很容易被激活。因为在Karaf中blueprint总是被加载,所以我们不需要做其他事情。

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
[http://www.osgi.org/xmlns/blueprint/v1.0.0] [http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd]
[http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0] [http://svn.apache.org/repos/asf/aries/trunk/blueprint/blueprint-cm/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.1.0.xsd]
">
<cm:property-placeholder persistent-id="ConfigApp" update-strategy="reload" >
<cm:default-properties>
<cm:property name="title" value="Default Title"/>
</cm:default-properties>
</cm:property-placeholder>

<bean id="myApp" init-method="refresh">
<property name="title" value="$\{title\}"></property>
</bean>
</blueprint>


上面xml请删除title附近的反斜杠。这个仅仅是了避免当wiki macro解析错误的影响。

部署配置文件

在我们已经成功地使用Config Admin服务后,进入产品环境唯一的事情就是部署bundle和一个默认配置。这个可以通过使用一个Karaf的feature文件来完成。我们根据需要的bunldes定义一个feature,和简单添加一个configfile元素。这个使得Karaf部署指定文件到karaf安装的etc目录下。如果文件已经存在,它不会被覆盖。

<feature name="tutorial-configadmin" version="${pom.version}">
<bundle>mvn:net.lr.tutorial.configadmin/configapp/${pom.version}</bundle>
<bundle>mvn:net.lr.tutorial.configadmin/configapp-blueprint/${pom.version}</bundle>
<configfile finalname="/etc/ConfigApp.cfg">mvn:net.lr.tutorial.configadmin/configadmin-features/${pom.version}/cfg</configfile>
</feature>


最后一个问题是怎么部署配置到maven使得configfile能够发现它。这个有点类似feature和build-helper-maven-plugin关系,详情请看pom文件怎么使用它。

总结和展望未来

在这个教程中,我们已经学习了Config Admin服务是怎么工作的以及如何使用OSGi和blueprint。我们也明白了如何编译及如何把文档和我们的工程部署在一起。

然而这里还是有一些非常有用的小细节没有涉及到。第一个细节是configfile不总是和config admin服务一致。实事上Karaf没有使用config admin服务去部署文件。我们所看到的是,已经存在的config元素不仅写配置到config admin服务中,而且持久化了它。幸运的是我的同事Jean Baptiste已经在研究这方面相关的,请访问Here

另外一个细节是对于企业环境,第一,需要定制化的config admin服务。例如需要在整网集中的地方设置配置和友好的UI界面。第二,是你不仅仅想要部署默认配置,而是部署对于系统管理确实需要的配置。所以针对安装的bunldes和feature和必要配置的修订,我认为你应该定一个部署计划。如果这个被正确的完成。将有利于部署和配置修订的检查,同时也有利于在某些配置错误的情况下去回滚修订。我希望我们可以在下一个Talend ESB EE发行版本提供一些相关功能。

参考文献

Using the Configuration Admin Service

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: