从骆驼 属性 占位符填充 java.util.Properties
Populate java.util.Properties from camel property placeholder
我刚开始学习 OSGi 和 camel,我正在研究一些已经实现的服务。在 OSGi 蓝图的帮助下,我有一个在 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 代码除外)中使用 camel 上下文中加载的属性吗?
如果那不可能,那么我应该如何加载位于 servicemix 类路径中的 属性 文件以在 camel 上下文和 java 代码中使用, 使用最少的代码在我当前的实现中更改。
我不鼓励在 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" />
在任何需要访问 属性 的 OSGI bundle 之后,可以通过以下方式引用:
<reference id="myConfig" interface="com.mycompany.services.common.api.MyConfig"
activation="eager" availability="mandatory" />
在使用这种方式之前,由于使用了静态方法和 LOCK,我们在 bundle 之间遇到了很多死锁。
由于我们使用 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 of 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;
}
}
我刚开始学习 OSGi 和 camel,我正在研究一些已经实现的服务。在 OSGi 蓝图的帮助下,我有一个在 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 代码除外)中使用 camel 上下文中加载的属性吗?
如果那不可能,那么我应该如何加载位于 servicemix 类路径中的 属性 文件以在 camel 上下文和 java 代码中使用, 使用最少的代码在我当前的实现中更改。
我不鼓励在 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" />
在任何需要访问 属性 的 OSGI bundle 之后,可以通过以下方式引用:
<reference id="myConfig" interface="com.mycompany.services.common.api.MyConfig"
activation="eager" availability="mandatory" />
在使用这种方式之前,由于使用了静态方法和 LOCK,我们在 bundle 之间遇到了很多死锁。 由于我们使用 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 of 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;
}
}