从camel属性占位符填充java.util.Properties

时间:2015-04-21 09:50:42

标签: java apache-camel apache-karaf blueprint-osgi apache-servicemix

我刚开始学习OSGi和驼峰,我正在研究已经实施的一些服务。我有一个配置为在OSMi蓝图的帮助下在Servicemix上运行的包,有点像这样:

<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代码中使用camel context中加载的属性(除了驼峰代码)吗?

如果那是不可能的,那么我应该如何加载位于servicemix类路径中的属性文件,以便在我的当前实现中使用驼峰上下文和java代码,代码更改最少

1 个答案:

答案 0 :(得分:3)

我不鼓励在OSGI环境中使用对Property文件的静态访问。

对我来说,最好的方法是创建一个OSGI服务,公开验证方法或属性本身(使用getter / setter),如下所示:

<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" />

在任何需要访问该属性的OSGI包之后,它可以通过以下方式引用:

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

在使用这种方式之前,我们在bundle之间有很多死锁,因为使用静态方法和LOCK&#39; s。 由于我们使用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;
    }
}