Karaf教程第2部分 使用Configuration Admin服务

来源:互联网 发布:原生Js获取滚动条高度 编辑:程序博客网 时间:2024/06/06 01:59

Karaf教程第2部分使用Configuration Admin服务

    Karaf教程的第1部分,我们学习了如何使用mavenblueprint提供和使用pojo服务,如何使用http服务发布servlet

    在第2部分,我们集中精力关注OSGi bundle的配置。不像servlet容器,OSGi容器包含一个非常好的配置规范:来自企业级规范的Config Admin服务。在本教程中,我们将在纯OSGiblueprint使用Config Admin服务,学习如何在bundle自动部署配置文件。

    这个教程的练习可以在github上找到:https://github.com/cschneider/Karaf-Tutorial/tree/master/configadmin

2.1 Configuration Admin服务规范

我们首先快速概览一下Configuration Admin服务规范。对于我们来说,主要有两个接口可以使用:

1ConfigurationAdmin:允许获取和改变配置。这个服务由Config Admin服务实现提供。

2ManagedService:允许对配置改变产生影响。必须实现这个接口,并将它注册给要被通知的服务。

    所以,基本上在Config Admin服务中的配置是一个字典,这个字典包含了属性和他们的值。字典由持久性标识PID标识。PID就是一个简单的字符串,它唯一标识了配置。

2.2 如何处理配置?

    虽然你可以使用ConfigurationAdmin.getConfiguration接口获取配置,但是我不推荐你这么做。OSGi是动态的,所以有可能发生bundleConfig Admin服务之前启动或者Config Admin服务还没有读取这个bundle的配置。所以有时候你获取的配置可能为null

    所以,推荐的方式是使用ManagedService,并对更新做出反应。如果你的bundle没有配置无法启动,那么在收到第一个更新时创建一个要被配置的pojo类是个好主意。

2.3 介绍要被配置的非常简单的类

    由于我们想要实现一个整洁风格的配置,那么要被配置的类应该是纯pojo。虽然可以简单的实现ManagedService接口,直接使用Dictionary,但这将使你依赖于OSGi和当前的Config Admin规范。所以,替代做法是我们使用一个具有title熟悉的简单的bean类。另外,我增加了一个刷新方法,当配置发生改变的时候来调用刷新方法。

public class MyApp {    String title;    public void setTitle(Stringtitle) {        this.title =title;    }    public void refresh() {         System.out.println("Configuration updated (title=" +title +")");     }}



所以我们的目标就是当配置发生改变时,配置title,然后调用refresh方法。我们将在纯OSGiblueprint中做这件事。

2.4 练习一下:使用纯OSGi接口处理配置

    本教程的第1个练习演示如何只用OSGi接口使用Config Admin服务。虽然这可能不是你以后使用的方式,但这种方式可以帮助你理解更深层次的东西。

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

    所以首先我们需要一个pom文件用于maven构建。你最好从configapp示例程序的pom文件开始。如果你新建了新的工程,你必须是使用maven-bundle-plugin插件使你的工程成为一个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服务交互。所以无论什么时候,配置发生改变,我们的方法都会被调用。第一件事是检查是否为null,当config被移除时这是有可能发生的。这时我们可以停止MyApp,但为了简单起见,我们只是忽略它。下一步是创建MyApp类。通常你可能会在Activator中实例化它,但是你不得不处理空配置,这是我们不希望的。最后是简单地用从config中获取的值调用setter方法,在所有的设置完成后再调用refresh方法。

private final class ConfigUpdaterimplements ManagedService {    @SuppressWarnings("rawtypes")    @Override    public void updated(Dictionaryconfig) 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_PIDconfig 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);

2.5 运行这个简单的示例

mvn install命令构建这个工程

启动一个全新的karaf实例

configapp.jartarget目录复制到Karafdeploy目录

    现在我们注意到似乎没有发生任何事情。在Karaf控制台调用list,你会看到这个bundle确实已经启动了,但是它没有任何输出,因为它还没有配置。我们仍然需要创建配置文件,并设置title

复制已有的文件/configadmin-features/src/main/resources/ConfigApp.cfgKaraf/etc目录

    这里重要的部分是文件名必须是<pid>.cfg。这样config admin服务才能找到它。

    现在fileinstall bundle会在etc目录检测到新的文件。由于文件结尾是.cfg,它认为这是一个config admin资源,创建或更新由文件名确定的pidConfig Admin服务配置。

所以现在在Karaf控制台你应该能看到下面的打印。这个打印显示了配置改变被正确地检测和转发。如果你现在用编辑器改变了这个文件并保存,那么这个变化也会被传播。

 

2.6 使用Karaf config命令探究配置

Karaf控制台键入如下命令:

 

在其他的配置中,你应该找到上面的配置"ConfigApp"。这个配置显示它从哪儿加载的,pid,当然还有在文件中设置的所有属性。

我们也可以改变这个配置:

 

我们看到这个修改直接传播到了我们的bundle。如果你看看etc下面的配置文件,你会发现这个改变已经持久化到了这个文件。所以如果我们重启了Karaf,修改还是生效的。

2.7 使用Blueprint配置

    在纯OSGi环境中处理了Config Admin服务之后,现在我们将看一看如何在Blueprint中实现同样的功能。幸运地是,这是相当容易,就Blueprint为我们做的大多数的工作一样。

    我们仅仅定义了一个cm:property-placeholder元素。这个处理文件的属性占位符的功能很相似,但是这里是处理Config Admin服务。我们需要提供一个配置的PID和更新策略。更新策略我们选择“reload”。这意味着在配置改变之后,blueprint上下文会被重新加载或反射改变。我们也设置了默认的属性,当配置的PID找不到或者属性不存在的时候,就会使用这些默认值。

    集成我们的bean类通常是一个简单的bean定义。在这个类中我们定义了title熟悉,分配一个占位符,这个占位符会使用config admin服务进行解析。唯一特别的是初始化方法。这个给了我们机会以便对配置改变之后做出反应,就像纯OSGi示例中一样。

对于bluenprint来说,我们不需要任何maven的依赖,因为我们的Java代码是纯Java bean。只要将Blueprint上下文放在OSGI-INF/blueprint目录中并且blueprint extender加载了,那么blueprint上下文就被会简单地激活。由于As blueprint总是在Karaf中被加载,所以我们什么都不需要做。

<?xml version="1.0" encoding="UTF-8"?><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" class="net.lr.tutorial.configadmin.MyApp" init-method="refresh"><property name="title" value="${title}"></property></bean></blueprint>

2.8 Deploying config files

在我们成功地使用了Config Admin服务之后,剩下要做的唯一一件事就是部署带默认配置的bundle。这可以使用Karaf feature文件实现。我们定义一个feature,带有它需要的bundle,简单地添加一个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,让configfileonfig元素能够找到它。这好像属于Karaf中的the build-helper-maven-plugin的特性。请参见pom文件了解使用细节。

 

2.9 Summing it up and a look into the future

    在本教程中,我们学习了如何使用Config Admin服务以及如何在纯OSGiblueprint中使用该服务。我们也看到了如何构建和部署我们的工程。

    虽然这已经很有用了,但在我看来,有一点点小问题。第一个问题是configfile似乎看起来与config admin不一致。实际上,Karaf不使用config admin服务部署文件。所以我想要看到的是已经存在的config元素不仅仅是为了写入配置,而且还用于持久化。幸运地是,我的同事Jean Baptiste正在研究这个问题。参见https://issues.apache.org/jira/browse/KARAF-888

    另一个问题是对于企业级环境,需要具有附加特性的config admin服务。一件是要可能在整个服务器网络中进行配置,具有配置的中心源和友好的UI。另一件事是你不仅想要部署默认的配置,而且要部署管理员真正想要为系统进行的配置。所以,我想你能够定义一个部署计划,不仅要安装bundlefeature,还需要配置的改变。如果这个正确的完成,将允许部署、配置改变的良好检查,也允许管理员一旦在出错的情况下回滚配置的变化。我希望我们可以在下一个Talend ESB EE发布版中提供这样的计划。

阅读全文
0 0
原创粉丝点击