我有以下情况:
我有一个OSGI包,它在蓝图XML中定义了一个引用远程包中接口的服务引用,以及一个使用impl方法之一填充Properties对象的bean。
来自Bundle#1的XML(消费者)的相关片段:
...
<!-- other bean definitions, namespace stuff, etc -->
<!-- reference to the fetching service -->
<reference id="fetchingService" interface="company.path.to.fetching.bundle.FetchingService" />
<!-- bean to hold the actual Properties object: the getConfigProperties method is one of the overridden interface methods -->
<bean id="fetchedProperties" class="java.util.Properties" factory-ref="fetchingService" factory-method="getProperties" />
<camelContext id="contextThatNeedsProperties" xmlns="http://camel.apache.org/schema/blueprint">
<propertyPlaceholder id="properties" location="ref:fetchedProperties" />
...
<!-- the rest of the context stuff - routes and so on -->
</camelContext>
Remote Bundle的blueprint.xml:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/blueprint"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<cm:property-placeholder id="config-properties" persistent-id="company.path.configfetcher" />
<bean id="fetchingService" class="company.path.to.fetching.bundle.impl.FetchingServiceImpl" scope="singleton" init-method="createLoader" depends-on="config-properties">
<property name="environment" value="${environment}" />
<property name="pathToRestService" value="${restPath}" />
</bean>
<service ref="fetchingService" interface="company.path.to.fetching.bundle.FetchingService" />
<!-- END TESTING -->
</blueprint>
来自Impl Class:
public synchronized Properties getProperties() {
if(!IS_RUNNING) {
// timer task that regularly calls the REST api to check for updates
timer.schedule(updateTimerTask, 0, pollInterval);
IS_RUNNING = true;
}
//Map<String, Properties> to return matching object if it's there
if(PROPERTIES_BY_KEY.containsKey(environment)) {
return PROPERTIES_BY_KEY.get(environment);
}
/* if nothing, return an empty Properties object - if this is the case, then whatever bundle is relying on these
* properties is going to fail and we'll see it in the logs
*/
return new Properties();
}
问题:
我有一个测试类(扩展CamelBlueprintTestSupport),并且有许多移动部件,以至于我无法真正改变事物的顺序。不幸的是,在启动CamelContext之前调用属性bean方法。没那么大的交易,因为在测试环境中没有配置文件来读取必要的属性,因此检索失败并且我们返回一个空的属性对象[注意:我们用假货覆盖属性组件,因为它不是那个类正在测试中,但在一个完美的世界里,我希望能够做两件事:
1)用新的Impl()
替换服务2)拦截对getProperties方法的调用或将bean绑定到新服务,以便调用从伪impl返回属性
思想?
编辑#1:
这是我现在正在做的一项解决方法:
try {
ServiceReference sr = this.getBundleContext().getServiceReference(FetchingService.class);
if(sr != null) {
((FetchingServiceImpl)this.getBundleContext().getService(sr)).setEnvironment(env);
((FetchingServiceImpl)this.getBundleContext().getService(sr)).setPath(path);
}
} catch(Exception e) {
log.error("Error getting Fetching service: {}", e.getMessage());
}
这里最大的问题是我必须等到调用createCamelContext才能存在 BundleContext ;因此,getProperties调用已经发生过一次。正如我所说,因为在测试环境中没有FetchingService类的配置来提供环境和路径字符串,所以第一次调用将失败(导致一个空的Properties对象)。第二次,上面的代码已经在impl类中设置了属性,我们即将参加比赛。这不是一个无效的问题。相反,它是一个更好,更优雅的解决方案,可以应用于其他场景。
哦,并且在任何人问之前澄清一下,这个服务的重点是我们不必为部署到我们的Servicemix实例的每个OSGI包都有一个.cfg文件 - 这个中央服务将去取得配置其他捆绑包需要,唯一需要存在的.cfg文件是Fetcher。
其他相关细节:
Camel 2.13.2 - 希望它是2.14,因为他们已经为该版本添加了更多属性占位符工具,这可能会使这更容易
Servicemix - 5.3.1
答案 0 :(得分:3)
您是否尝试在测试中覆盖CamelBlueprintTestSupport
的{{1}}(请参阅“在启动时添加服务”http://camel.apache.org/blueprint-testing.html)?
在你的情况下:
addServicesOnStartup