1. 程式人生 > >Karaf教程第2部分 使用Configuration Admin服務

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

    Karaf教程的第1部分,我們學習瞭如何使用mavenblueprint提供和使用pojo服務,如何使用http服務釋出servlet

    在第2部分,我們集中精力關注OSGi bundle的配置。不像servlet容器,OSGi容器包含一個非常好的配置規範:來自企業級規範的Config Admin服務。在本教程中,我們將在純OSGiblueprint使用Config Admin服務,學習如何在bundle自動部署配置檔案。

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釋出版中提供這樣的計劃。