You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JBoss Fuse Blueprint中使用多个property-placeholder?

在JBoss Fuse 6.3 Blueprint中使用多配置文件的错误解决方法

我之前也碰到过这个问题,其实原因很明确:虽然Red Hat文档说允许多个cm:property-placeholder,但默认情况下每个占位符都用相同的${前缀和}后缀,而Aries Blueprint的校验逻辑不允许这种重复的前后缀组合,所以才会抛出Multiple placeholders with the same prefix and suffix are not allowed错误。

先回顾下你的场景:
你最初尝试用两个独立的占位符加载不同配置:

<cm:property-placeholder persistent-id="foo" />
<cm:property-placeholder persistent-id="bar" />

并且参考了Red Hat的文档说明:

在Blueprint中使用多个属性占位符
在Blueprint XML文件中定义多个属性占位符(即引用不同persistent ID的多个cm:property-placeholder元素)是合法的。但需要注意的是,若不同占位符中存在同名属性,会出现冲突,此时遵循以下优先级规则:

  1. 显式定义的属性设置(例如etc/PersistentID.cfg文件中的配置)优先级高于cm:default-properties元素中定义的默认属性设置。
  2. 若同一属性存在多个显式设置,Blueprint文件中最后一个属性占位符的设置优先级更高。
  3. cm:default-properties元素中定义的默认属性设置优先级最低。

但实际运行时出现了错误日志:

2018-05-15 17:43:59,065 | ERROR | /s42http1/deploy | BlueprintContainerImpl | 22 - org.apache.aries.blueprint.core - 1.8.0 | Unable to start blueprint container for bundle myBlueprint/0.0.1.SNAPSHOT org.osgi.service.blueprint.container.ComponentDefinitionException: Multiple placeholders with the same prefix and suffix are not allowed at org.apache.aries.blueprint.ext.PlaceholdersUtils.validatePlaceholder(PlaceholdersUtils.java:49)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.blueprint.compendium.cm.CmNamespaceHandler.parsePropertyPlaceholder(CmNamespaceHandler.java:318)[20:org.apache.aries.blueprint.cm:1.1.0] at org.apache.aries.blueprint.compendium.cm.CmNamespaceHandler.parse(CmNamespaceHandler.java:199)[20:org.apache.aries.blueprint.cm:1.1.0] at org.apache.aries.blueprint.parser.Parser.parseCustomElement(Parser.java:1369)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.blueprint.parser.Parser.loadComponents(Parser.java:427)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.blueprint.parser.Parser.populate(Parser.java:331)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:350)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:277)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:300)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:269)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:265)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.blueprint.container.BlueprintExtender.modifiedBundle(BlueprintExtender.java:255)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:500)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:433)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$AbstractTracked.track(BundleHookBundleTracker.java:725)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.bundleChanged(BundleHookBundleTracker.java:463)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$BundleEventHook.event(BundleHookBundleTracker.java:422)[22:org.apache.aries.blueprint.core:1.8.0] at org.apache.felix.framework.util.SecureAction.invokeBundleEventHook(SecureAction.java:1127)[org.apache.felix.framework-4.4.1.jar:] at org.apache.felix.framework.util.EventDispatcher.createWhitelistFromHooks(EventDispatcher.java:696)[org.apache.felix.framework-4.4.1.jar:] at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:484)[org.apache.felix.framework-4.4.1.jar:] at org.apache.felix.

下面给你两种可行的解决办法:

方法一:为每个占位符设置唯一的前后缀

给每个cm:property-placeholder指定不同的placeholder-prefix和placeholder-suffix,这样就能区分不同配置的属性引用:

<cm:property-placeholder persistent-id="foo" placeholder-prefix="${foo:" placeholder-suffix="}" />
<cm:property-placeholder persistent-id="bar" placeholder-prefix="${bar:" placeholder-suffix="}" />

之后在Blueprint里引用属性时,要对应使用各自的前缀:

<bean id="fooService" class="com.example.FooService">
    <property name="url" value="${foo:url}" />
</bean>
<bean id="barService" class="com.example.BarService">
    <property name="port" value="${bar:port}" />
</bean>

方法二:单个占位符加载多个配置文件(推荐)

这种方式更简洁,也能满足Red Hat文档里的优先级规则。你可以在单个cm:property-placeholder的persistent-id里用逗号分隔多个配置ID,这样会按顺序加载,后面的配置会覆盖前面的同名属性:

<cm:property-placeholder persistent-id="foo,bar" />

这种情况下,你直接用统一的${propertyName}格式引用属性就行,如果foo.cfg和bar.cfg有同名属性,bar.cfg的值会生效(因为它在列表中更靠后),完全符合文档里的优先级规则。

内容的提问来源于stack exchange,提问作者Yannick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:09:45