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

原文地址  http://blog.csdn.net/wusandi/article/details/78172920

    

  在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类。另外,我增加了一个刷新方法,当配置发生改变的时候来调用刷新方法。

[java]  view plain  copy
  1. public class MyApp {  
  2.   
  3.     String title;  
  4.   
  5.     public void setTitle(Stringtitle) {  
  6.   
  7.         this.title =title;  
  8.   
  9.     }  
  10.   
  11.     public void refresh() {  
  12.   
  13.          System.out.println("Configuration updated (title=" +title +")");  
  14.    
  15.     }  
  16. }  



所以我们的目标就是当配置发生改变时,配置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,你需要添加两个依赖:

[html]  view plain  copy
  1. <dependency>  
  2.   
  3.     <groupId>org.osgi</groupId>  
  4.   
  5.     <artifactId>org.osgi.compendium</artifactId>  
  6.   
  7.     <version>4.2.0</version>  
  8.   
  9. </dependency>  
  10.   
  11. <dependency>  
  12.   
  13.     <groupId>org.osgi</groupId>  
  14.   
  15.     <artifactId>org.osgi.core</artifactId>  
  16.   
  17.     <version>4.2.0</version>  
  18.   
  19. </dependency>  


 

    第一个依赖用于获取config admin服务接口,第二个依赖用于创建Activator,它包含基本的OSGi接口。

    现在,我们关心如何更新MyApp类。下面这个类解决了这个问题。我们实现了ManagedService接口,来与Config Admin服务交互。所以无论什么时候,配置发生改变,我们的方法都会被调用。第一件事是检查是否为null,当config被移除时这是有可能发生的。这时我们可以停止MyApp,但为了简单起见,我们只是忽略它。下一步是创建MyApp类。通常你可能会在Activator中实例化它,但是你不得不处理空配置,这是我们不希望的。最后是简单地用从config中获取的值调用setter方法,在所有的设置完成后再调用refresh方法。

[java]  view plain  copy
  1. private final class ConfigUpdaterimplements ManagedService {  
  2.   
  3.     @SuppressWarnings("rawtypes")  
  4.   
  5.     @Override  
  6.   
  7.     public void updated(Dictionaryconfig) throws ConfigurationException {  
  8.   
  9.         if (config ==null) {  
  10.   
  11.             return;  
  12.     
  13.         }  
  14.   
  15.         if (app ==null) {  
  16.   
  17.             app = new MyApp();  
  18.   
  19.         }  
  20.   
  21.         app.setTitle((String)config.get("title"));  
  22.   
  23.         app.refresh();  
  24.   
  25.     }  
  26.   
  27. }  

    当然,这还是什么事情都没做。最后一步就是在Activator.start方法中注册ConfigUpdater。我们简单地使用registerService方法,就像每一个其他的服务一样。唯一特殊的地方是你必须设置SERVICE_PIDconfig pid,这样Config Admin服务就知道你想要监视的配置了。

[java]  view plain  copy
  1. Hashtable<String, Object> properties =new Hashtable<String, Object>();  
  2.   
  3. properties.put(Constants.SERVICE_PID,CONFIG_PID);  
  4.   
  5. 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中被加载,所以我们什么都不需要做。

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"  
  4.   
  5.  xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"  
  6.   
  7.  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  8.   
  9.  xsi:schemaLocation="  
  10.   
  11.  http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd  
  12.   
  13.  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  
  14.   
  15.  ">  
  16.   
  17. <cm:property-placeholder persistent-id="ConfigApp" update-strategy="reload" >  
  18.   
  19. <cm:default-properties>  
  20.   
  21. <cm:property name="title" value="Default Title"/>  
  22.   
  23. </cm:default-properties>  
  24.   
  25. </cm:property-placeholder>  
  26.   
  27.    
  28.   
  29. <bean id="myApp" class="net.lr.tutorial.configadmin.MyApp" init-method="refresh">  
  30.   
  31. <property name="title" value="${title}"></property>  
  32.   
  33. </bean>  
  34.   
  35. </blueprint>  

2.8 Deploying config files

在我们成功地使用了Config Admin服务之后,剩下要做的唯一一件事就是部署带默认配置的bundle。这可以使用Karaf feature文件实现。我们定义一个feature,带有它需要的bundle,简单地添加一个configfile元素。这使得Karaf部署给定的文件到Karaf安装位置的etc目录。如果这个文件已经存在,那么它不会被覆盖。

[html]  view plain  copy
  1. <feature name="tutorial-configadmin" version="${pom.version}">  
  2.   
  3. <bundle>mvn:net.lr.tutorial.configadmin/configapp/${pom.version}</bundle>  
  4.   
  5. <bundle>mvn:net.lr.tutorial.configadmin/configapp-blueprint/${pom.version}</bundle>  
  6.   
  7. <configfile finalname="/etc/ConfigApp.cfg">mvn:net.lr.tutorial.configadmin/configadmin-features/${pom.version}/cfg</configfile>  
  8.   
  9. </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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值