2017-04-03 38 views
2

通常我们正在部署基于骆驼/蓝图的服务一次。每个服务都有自己的属性占位符和骆驼上下文是绑定到它:如何使用不同的属性占位符多次部署骆驼/蓝图服务

<cm:property-placeholder id="service-name.placeholder" persistent-id="service-name.blueprint"> 
    <cm:default-properties> 
     ... 
    </cm:default-properties> 
</cm:property-placeholder> 
... 
<camelContext id="service-name-service-camel" xmlns="http://camel.apache.org/schema/blueprint" 
    useMDCLogging="true"> 
    <propertyPlaceholder id="properties" location="blueprint:service-name.placeholder" /> 
    <routeBuilder ref="mainRoute"/> 
</camelContext> 

现在,我们创建了我们想要部署多次的服务。每个实例应该使用自己的一组属性值。 我看到的唯一方法是在编译时设置属性占位符名称(maven过滤器),但这会导致不同的工件 - 不好。

有没有办法设置属性占位符在运行时或开始时间使用?

回答

1

你可以用ManagedServiceFactory和几行代码来完成。

为Factory定义一个bean,并注入BundleContext。选择一个PID以后识别和配置此厂:

<bean id="myServiceFactory" class="org.my.MyServiceFactory" init-method="init" destroy-method="destroy"> 
    <property name="bundleContext" ref="blueprintBundleContext"/> 
    <property name="configurationPid" value="org.my.pid"/> 
</bean> 

实现服务工厂(不工作的代码,只是给你一个想法):

public class MyServiceFactory implements ManagedServiceFactory { 

    private BundleContext bundleContext; 

    private String configurationPid; 

    public void setConfigurationPid(String configurationPid) { 
     this.configurationPid = configurationPid; 
    } 

    public void setBundleContext(BundleContext bundleContext) { 
     this.bundleContext = bundleContext; 
    } 

    public void init() { 
     // your setup goes here 
    } 

    public void destroy() { 
     // your shutdown logic goes here 
    } 

    @Override 
    public String getName() { 
     return configurationPid; 
    } 

    @Override 
    public void updated(String pid, Dictionary dict) throws ConfigurationException { 
     // Instantiate each service with its own properties 
     MyServiceImpl service = new MyServiceImpl(dict); 
     Dictionary servProps = new Properties(); 
     servProps.put("custom.service.property", "an id or someting") 
     bundleContext.registerService(MyServiceImpl.class.getName(), service, servProps); 
     // save your servicereferences to unregister, eg in a map 
     // you can customize your service by giving some property to later retrieve it 
    } 

    @Override 
    public void deleted(String pid) { 
     // get the ServiceReference from some map 
     servicereference.unregister(); 
    } 

} 

的ManagedServiceFactory有一个方法init()设置所有必需的资源,清理方法(例如通过注销所有服务)。

一个新的服务实例为etc/org.my.pid-*.cfg每个配置文件创建,例如创建服务的3个实例:

etc/org.my.pid-serviceinstance1.cfg 
etc/org.my.pid-serviceinstance2.cfg 
etc/org.my.pid-whatever.cfg 

要获得服务的特定情况下,一些自定义属性注册(在我的示例中为custom.service.property)。然后在一个消费者包中请求MyService的实例custom.service.property = serviceinstance2然后就完成了。

你甚至可以用这种方式创建新的CamelContext。有一个关于PacktPub网站的完整教程。

编辑: 当你写在etc/org.my.pid-*updated()方法被称为一个新的文件,并部署新的服务。当一个文件被删除,deleted()方法被调用,你必须销毁和取消注册该服务。当然,您可以在不停止主包的情况下使用JBoss/Karaf运行:-)添加/删除/修改文件。

+0

感谢您的详细解答。但是还有一个问题:如何设置骆驼上下文?在我的蓝图xml中有足够的吗? Blueprint应该多次实例化camelcontext(以及所有其他bean) - 每个属性文件一次,对吧? – dermoritz

+0

@dermoritz在PacktPub上的例子中,他们设置了一个CamelContext并使用java [RouteBuilder]动态实例化路由中的路由(https://camel.apache.org/maven/current/camel-core/apidocs/org/apache/骆驼/建设者/ RouteBuilder.html)。每条路线都有自己的属性值。 所以,一个CamelContext就足够了。 Blueprint实例化CamelContext,你的ManagedServiceFactory基于配置文件实例化路由。 –

+0

@dermoritz看看他们提供的例子:https://github.com/jgoodyear/ApacheKarafCookbook/tree/master/chapter2/chapter2-recipe6 –