部署新功能时,在启动捆绑包之前未加载配置文件

时间:2016-12-15 15:51:19

标签: jbossfuse fabric8

我正在评估jboss fuse(使用版本6.2.1.redhat-084),并且我遇到了以下问题:

  • 我的项目中有很多功能
  • 每个功能都有一个配置文件
  • 功能存储库文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<features name="myservice-features" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0">
    <feature name="myservice-common" version="${project.version}">
        <configfile finalname="etc/com.myorg.myservice_common.cfg" override="true">mvn:com.myorg/myservice-common/${project.version}/cfg/${build.environment}</configfile>
        <bundle start-level="100" dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.javax-cache-api/1.0.0_1</bundle>
        <bundle start-level="100" dependency="true">mvn:org.apache.camel/camel-velocity/${camel.version}</bundle>
        <bundle start-level="110">mvn:com.myorg/myservice-common/${project.version}</bundle>
    </feature>
    <feature name="myservice-impl" version="${project.version}">
        <feature>myservice-common</feature>
        <configfile finalname="etc/com.myorg.myservice.cfg" override="true">mvn:com.myorg/myservice-impl/${project.version}/cfg/${build.environment}</configfile>
        <bundle start-level="200">mvn:com.hazelcast/hazelcast/${hazelcast.version}</bundle>
        <bundle start-level="200">mvn:com.hazelcast/hazelcast-client/${hazelcast.version}</bundle>
        <bundle start-level="220">mvn:com.myorg/myservice-impl/${project.version}</bundle>
    </feature>
</features>
  • 该服务使用带有相应PID的蓝图属性占位符来初始化驼峰上下文中的属性
  • 问题是,在配置文件中部署功能时,只有在尝试解析捆绑包后才会通过org.apache.felix.fileinstall获取配置文件,并且我遇到以下异常:

    2016-12-15 10:07:38,384 | ERROR | oyer-49-thread-1 | BlueprintContainerImpl           | 23 - org.apache.aries.blueprint.core - 1.4.4 | Unable to start blueprint container for bundle otc-trade-service-impl/1.0.0.SNAPSHOT
org.osgi.service.blueprint.container.ComponentDefinitionException: Unable to initialize bean .camelBlueprint.factory.myservice-impl-context
        at org.apache.aries.blueprint.container.BeanRecipe.runBeanProcInit(BeanRecipe.java:714)[23:org.apache.aries.blueprint.core:1.4.4]
...
Caused by: java.lang.IllegalArgumentException: Property placeholder key: xxxxx not found
        at org.apache.camel.blueprint.BlueprintPropertiesParser.parseProperty(BlueprintPropertiesParser.java:164)
        at org.apache.camel.component.properties.DefaultPropertiesParser$ParsingContext.doGetPropertyValue(DefaultPropertiesParser.java:306)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
        at org.apache.camel.component.properties.DefaultPropertiesParser$ParsingContext.getPropertyValue(DefaultPropertiesParser.java:246)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
        at org.apache.camel.component.properties.DefaultPropertiesParser$ParsingContext.readProperty(DefaultPropertiesParser.java:154)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
        at org.apache.camel.component.properties.DefaultPropertiesParser$ParsingContext.doParse(DefaultPropertiesParser.java:113)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
        at org.apache.camel.component.properties.DefaultPropertiesParser$ParsingContext.parse(DefaultPropertiesParser.java:97)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
        at org.apache.camel.component.properties.DefaultPropertiesParser.parseUri(DefaultPropertiesParser.java:62)
        at org.apache.camel.component.properties.PropertiesComponent.parseUri(PropertiesComponent.java:178)
        at org.apache.camel.component.properties.PropertiesComponent.parseUri(PropertiesComponent.java:129)
        at org.apache.camel.impl.DefaultCamelContext.resolvePropertyPlaceholders(DefaultCamelContext.java:1956)
        at org.apache.camel.model.ProcessorDefinitionHelper.resolvePropertyPlaceholders(ProcessorDefinitionHelper.java:734)
        at org.apache.camel.model.RouteDefinitionHelper.initRouteInputs(RouteDefinitionHelper.java:379)
        ... 47 more
  • 这类似于问题https://issues.jboss.org/browse/ENTESB-593;然而,看起来像'修复&#39;该问题只涉及将配置文件复制到$ {karaf.base} / etc文件夹中,但在启动捆绑包之前没有实际触发和同步karaf配置管理器

我对此问题有点困惑。显然我可以设置&#39; start =&#34; false&#34;&#39;对于我的捆绑包并在配置文件部署后手动启动所有驼峰上下文捆绑包,但我想知道是否有更优化的解决方案。

1 个答案:

答案 0 :(得分:0)

到目前为止,我已经提出了以下hacky解决方法:

  • 为org.osgi添加依赖项:org.osgi.compendium:5.0.0和org.osgi:org.osgi.core:5.0.0
  • 创建以下BundleActivator类:

  import AmbryPostResponseUnmarshalling._
  import akka.http.scaladsl.unmarshalling._

  case class AmbryPostFileResponse(ambryId: String)
  val ambryBlobInfo = new AmbryPostFileResponse("ambryId")



  val testHttpResponse = HttpResponse(status = StatusCodes.OK, headers = List(Location("ambryId")))

  "Unmarshaler" should {
    "unmarshal" in {
      val result = Unmarshal(testHttpResponse).to[AmbryPostFileResponse]
      whenReady(result, timeout(10 seconds)) { r =>
        r shouldEqual ambryBlobInfo
      }
    }
  }

  object AmbryPostResponseUnmarshalling extends AmbryPostResponseUnmarshalling

  trait AmbryPostResponseUnmarshalling {
    implicit final val fru: FromResponseUnmarshaller[AmbryPostFileResponse] = {
      //  val h: Class[Location] = headers.Location.getClass[Location]
      def unmarshal(response: HttpResponse) =
        AmbryPostFileResponse(response.getHeader("Location").get.asInstanceOf[Location].uri.toString())

      Unmarshaller.strict(unmarshal)
    }

  }

}
  • 将此捆绑包激活器添加到捆绑包清单
  • 将以下属性添加到配置文件中:

    package com.myorg.common;
    
    import org.osgi.framework.Bundle;
    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;
    import org.osgi.framework.ServiceRegistration;
    import org.osgi.service.cm.Configuration;
    import org.osgi.service.cm.ConfigurationEvent;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.util.Dictionary;
    
    public class ConfigurationActivator implements BundleActivator {
    
        public static final String BUNDLE_CONFIGURATION_WATCH = "bundle.configuration.watch";
        public static final String BUNDLE_SYMBOLIC_NAME = "bundle.symbolic.name";
    
        private static final Logger LOG = LoggerFactory.getLogger(ConfigurationActivator.class);
        private ServiceRegistration<org.osgi.service.cm.ConfigurationListener> listenerReg;
    
        public void start(BundleContext context) throws Exception {
            LOG.debug("Bundle " + context.getBundle().getSymbolicName() + " starting");
            listenerReg = context.registerService(org.osgi.service.cm.ConfigurationListener.class,
                    new ConfigurationListener(context), null);
        }
    
        public void stop(BundleContext context) throws Exception {
            LOG.debug("Bundle " + context.getBundle().getSymbolicName() + " stopping");
            if (listenerReg != null) {
                listenerReg.unregister();
            }
        }
    
        public class ConfigurationListener implements org.osgi.service.cm.ConfigurationListener {
            private BundleContext bundleContext;
    
            public ConfigurationListener(BundleContext bundleContext) {
                this.bundleContext = bundleContext;
            }
    
            public void configurationEvent(ConfigurationEvent configurationEvent) {
                try {
                    if (configurationEvent.getType() == ConfigurationEvent.CM_UPDATED) {
                        LOG.debug("Configuration update event: " + configurationEvent.getPid());
                        Bundle bundle = bundleContext.getBundle();
                        LOG.trace("Bundle " + bundle.getSymbolicName() + " state: " + bundle.getState());
                        try {
                            Configuration configuration = bundleContext.getService(configurationEvent.getReference()).getConfiguration(configurationEvent.getPid());
                            if (configuration != null) {
                                Dictionary<String, Object> properties = configuration.getProperties();
                                if (properties != null) {
                                    if (Boolean.TRUE.toString().equals(properties.get(BUNDLE_CONFIGURATION_WATCH))
                                            && bundle.getSymbolicName().equals(properties.get(BUNDLE_SYMBOLIC_NAME))) {
                                        LOG.info("Updating bundle " + bundle.getSymbolicName() + " due to configuration change");
                                        bundle.update();
                                    }
                                }
                            }
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
                } catch (IllegalStateException se) {
                    LOG.warn("Bundle context has been invalidated");
                }
            }
        }
    }
    
  • 部署该功能。如果在捆绑包已尝试启动后配置已更改,则捆绑包将更新

由于两个原因,这对我来说仍然不合适:

  1. 其他配置属性
  2. 原始问题仍会在部署期间在日志中导致混淆错误消息
  3. 有人能提出更好的答案吗?