2015-04-21 31 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。 –