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

从camel属性占位符填充java.util.Properties,java,apache-camel,apache-karaf,blueprint-osgi,apache-servicemix,Java,Apache Camel,Apache Karaf,Blueprint Osgi,Apache Servicemix,我刚刚开始学习OSGi和camel,并且正在研究一些已经实现的服务。我有一个bundle,它被配置为在OSGi blueprint的帮助下在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

我刚刚开始学习OSGi和camel,并且正在研究一些已经实现的服务。我有一个bundle,它被配置为在OSGi blueprint的帮助下在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>
<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" />

。。。这种配置工作得非常好

我面临的问题是,这个属性文件还通过java.util.properties在多个位置使用,该文件作为简单文件加载在util文件的静态代码块中

我可以在Java代码(骆驼代码除外)中使用骆驼上下文中加载的属性吗


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

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

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

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

org.osgi.service.cm.ManagedService
com.mycompany.services.common.api.MyConfig
在任何需要访问属性的OSGI捆绑包中,可以通过以下方式引用它:

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

在使用这种方法之前,由于使用静态方法和锁的方法,捆绑包之间有很多死锁。 因为我们使用OSGI服务,所以在刷新/部署捆绑包时,它工作得非常好,没有问题

我假设您希望通过任何其他OSGI包访问属性文件,而不是通过OSGI上下文中的外部代码。 如果您想在OSGI上下文之外访问属性文件,我建议您在提到的接口上创建一个(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;
    }
}
公共类MyConfigImpl实现MyConfig,ManagedService{
//这只是属性键
私有最终静态字符串COLORS=“my.valid.COLORS”;
私有最终静态字符串PROP1=“my.property.1”;
私有最终静态字符串PROP2=“my.property.2”;
私有最终静态字符串PROP3=“my.property.3”;
//用于根据某些属性进行验证
私有列表颜色=新的ArrayList();
//用于提取属性的子集
私有字符串prop1;
私有字符串prop2;
私有字符串prop3;
//作为字典发布的整套操作系统属性(也可以在地图中转换)
私人字典道具;
@重写//实现MyConfig.isValidColor(字符串颜色)
公共布尔值isValidColor(字符串颜色){
if(颜色.包含(颜色)){
返回true;
}否则{
返回false;
}
}
@重写//实现MyConfig.getPropertyOne()
公共字符串getPropertyOne(){
返回prop1;
}
@重写//实现MyConfig.getPropertyTwo()
公共字符串getPropertyTwo(){
返回prop2;
}
@重写//实现MyConfig.getPropertyTree()
公共字符串getPropertyTree(){
返回prop3;
}
@重写//实现MyConfig.getProperties()
公共字典getProperties(){
返回道具;
}
//这将实现ManagedService.updated()
@凌驾
public void updated(@SuppressWarnings(“rawtypes”)字典属性)引发ConfigurationException{
debug(“读取属性:{}”,属性);
如果(属性==null){
返回;
}
更新配置(属性);
}
私有void updateConfiguration(字典属性){
//MyUtil.asListOfString只是一个将逗号分隔的字符串转换为字符串列表的助手
//这只是一个例子
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=属性;
}
}

我认为我不完全理解您的实现。这个Myconfig接口是什么?我如何使用它来提取属性??你能详细说明一下,或者给我举一些例子吗?用例子更新。如果您需要许多属性,我认为最好的方法是导出字典或将其转换为地图。其他方法仅用于示例,不一定是最佳实践。实现源自两个接口。。您需要公开您想要的方法(在您的例子中,您可能只需要像
mapgetproperties();
和ManagedService(OSGI)这样的东西来读取属性和更新Bean。