Camel Blueprint Testing - 如何动态替换/代理Blueprint中引用的远程服务以防止使用真实服务?

时间:2015-02-28 03:01:26

标签: apache-camel blueprint-osgi

我有以下情况:

我有一个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

1 个答案:

答案 0 :(得分:3)

您是否尝试在测试中覆盖CamelBlueprintTestSupport的{​​{1}}(请参阅“在启动时添加服务”http://camel.apache.org/blueprint-testing.html)?

在你的情况下:

addServicesOnStartup