2015-04-21 30 views
1

我剛開始學習OSGi和駱駝,我正在研究一些已經實現的服務。我有一個被配置爲使用OSGi藍圖的幫助下有點像這對ServiceMix的運行包:從駱駝屬性佔位符中填充java.util.Properties

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel-cxf="http://camel.apache.org/schema/blueprint/cxf" 
xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/blueprint/core" 
xsi:schemaLocation=" 
    http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd 
    http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd 
    http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd 
    http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd"> 

<camelContext id="ctx1" 
    xmlns="http://camel.apache.org/schema/blueprint" 
    xsi:schemaLocation="http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd"> 
    <propertyPlaceholder location="properties/config.properties"/> 
    <routeBuilder ref="..." /> 
</camelContext> 

目前,config.properties位於包內,但我想它外部化。

於是,我改變了我的藍圖:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel-cxf="http://camel.apache.org/schema/blueprint/cxf" 
xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/blueprint/core" 
xsi:schemaLocation=" 
    http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd 
    http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd 
    http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd 
    http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd"> 

<camelContext id="ctx1" 
    xmlns="http://camel.apache.org/schema/blueprint" 
    xsi:schemaLocation="http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd"> 
    <propertyPlaceholder location="${karaf.home}/etc/config.properties"/> 
    <routeBuilder ref="..." /> 
</camelContext> 

...這配置工作完全正常。

我面臨的問題是,該屬性文件也通過java.util.properties在多個位置中使用,該文件作爲簡單文件加載到util文件中的靜態代碼塊中。

我可以在我的Java代碼(駱駝代碼除外)中使用在駱駝上下文中加載的屬性嗎?

如果這是不可能的,我應該那麼如何加載位於ServiceMix的類路徑中屬性文件要在這兩個背景下的駱駝和Java代碼中使用,用最少的代碼在我的當前實現改變

回答

2

我不鼓勵在OSGI環境中使用對Property文件的靜態訪問。

對於我的最佳方式是創建一個OSGI服務,其暴露這樣的驗證方法或屬性本身(與的getter/setter):其中需要訪問屬性的任何OSGi包

<service ref="myConfig"> 
    <interfaces> 
     <value>org.osgi.service.cm.ManagedService</value> 
     <value>com.mycompany.services.common.api.MyConfig</value> 
    </interfaces> 
    <service-properties> 
     <entry key="service.pid" value="config.properties" /> 
    </service-properties> 
</service> 

<bean id="myConfig" class="com.mycompany.services.common.config.MyConfigImpl" /> 

後,它可以通過引用:

<reference id="myConfig" interface="com.mycompany.services.common.api.MyConfig" 
    activation="eager" availability="mandatory" /> 

使用這種方法,我們有很多因爲靜態方法和鎖的鎖的使用束之間死鎖之前。 由於我們使用OSGI服務,因此在刷新/部署軟件包時它可以毫無問題地工作。

我假設你想通過任何其他OSGI包訪問你的屬性文件,而不是外部代碼形式的OSGI上下文。 如果要訪問OSGI上下文之外的屬性文件,我建議通過所提及的接口(<reference>)創建(REST)Web服務。

實現的例子:

public class MyConfigImpl implements MyConfig, ManagedService { 

    // This is just the property keys 
    private final static String COLORS = "my.valid.colors"; 
    private final static String PROP1 = "my.property.1"; 
    private final static String PROP2 = "my.property.2"; 
    private final static String PROP3 = "my.property.3"; 

    // For validating against some properties 
    private List<String> colors = new ArrayList<>(); 

    // For extracting a subset of properties 
    private String prop1; 
    private String prop2; 
    private String prop3; 

    // The whole set os properties published as Dictionary (could be transformed in Map as well) 
    private Dictionary props; 

    @Override // Implements MyConfig.isValidColor(String color) 
    public Boolean isValidColor(String color) { 
     if (colors.contains(color)) { 
      return true; 
     } else { 
      return false; 
     } 
    } 

    @Override // Implements MyConfig.getPropertyOne() 
    public String getPropertyOne(){ 
     return prop1; 
    } 

    @Override // Implements MyConfig.getPropertyTwo() 
    public String getPropertyTwo(){ 
     return prop2; 
    } 

    @Override // Implements MyConfig.getPropertyThree() 
    public String getPropertyThree(){ 
     return prop3; 
    } 

    @Override // Implements MyConfig.getProperties() 
    public Dictionary getProperties(){ 
     return props; 
    } 


    // This implements the ManagedService.updated() 
    @Override 
    public void updated(@SuppressWarnings("rawtypes") Dictionary properties) throws ConfigurationException { 

     log.debug("Reading properties: {}", properties); 
     if (properties == null) { 
      return; 
     } 

     updateConfiguration(properties); 

    } 

    private void updateConfiguration(Dictionary properties) { 

     // MyUtil.asListOfString is just a helper to convert comma separated string to list of String 
     // This is just an example 
     this.colors = MyUtil.asListOfStrings((String) properties.get(COLORS)); 

     this.prop1 = properties.get(PROP1); 
     this.prop2 = properties.get(PROP2); 
     this.prop3 = properties.get(PROP3); 
     this.props = properties; 
    } 
} 
+0

我不認爲我完全理解你的實現。這是什麼Myconfig接口,我如何使用它來提取屬性?你可以請詳細說明或者可以指點我一些例子嗎? – ishan

+0

以示例更新。如果您需要很多屬性,我認爲最好的方法是導出字典或將其轉換爲Map 。其他方法只是爲了舉例,不一定是最佳實踐。 –

+0

該實現派生自兩個接口..你公開你想要的方法(在你的情況下,也許你只需要像'Map getProperties()')和ManagedService(OSGI)來讀取屬性並更新Bean。 –