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

Spring JNDI配置文件使用环境变量替换${...}占位符失效问题及<context:property-placeholder />配置疑问

Hey there, let's break down why your ${...} placeholders in jndi.xml aren't resolving with environment variables, and cover how to handle JNDI variables as placeholders too.

First: Why Your PropertySourcesPlaceholderConfigurer Might Not Be Working

Even if you have a PropertySourcesPlaceholderConfigurer bean defined, there are a few common pitfalls that could block it from resolving environment variables:

  • Missing environment variable property source: Your custom configurer might not explicitly include system environment variables as a property source. While Spring's Environment includes env vars by default, overriding property sources in your bean could exclude them.
  • Bean initialization order: PropertySourcesPlaceholderConfigurer needs to initialize early in the context lifecycle. If your bean isn't marked as static (in Java config) or loads after jndi.xml, it won't process the placeholders in time.
  • Conflicting configurers: If both a manual PropertySourcesPlaceholderConfigurer and <context:property-placeholder /> exist, they might interfere—only one will act as the primary placeholder resolver.

What Does <context:property-placeholder /> Do?

This XML tag is a Spring shortcut that automatically registers a PropertySourcesPlaceholderConfigurer bean for you. It simplifies configuration by:

  • Defaulting to loading properties from application.properties (and similar files) on the classpath.
  • Automatically including system properties and environment variables as property sources.
  • Letting you tweak behavior with attributes like ignore-unresolvable (avoids errors for unrecognized placeholders) and system-properties-mode (controls whether env vars/system props override file-based properties).

Fixing the Placeholder Resolution Issue

Option 1: Use <context:property-placeholder /> (Simplest Approach)

Replace your manual PropertySourcesPlaceholderConfigurer bean with this XML config in your Spring context:

<context:property-placeholder ignore-unresolvable="true" system-properties-mode="OVERRIDE" />
  • ignore-unresolvable="true": Prevents Spring from throwing errors if it encounters placeholders it can't resolve (useful for mixing placeholder sources).
  • system-properties-mode="OVERRIDE": Ensures environment variables/system properties take precedence over file-based properties.

Option 2: Fix Your Manual PropertySourcesPlaceholderConfigurer

If you need to keep the manual bean, update it to explicitly include environment variables (and JNDI, if needed) as property sources. Here's a Java config example:

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() throws NamingException {
    PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
    MutablePropertySources propertySources = new MutablePropertySources();

    // Add system environment variables as a property source
    propertySources.addLast(new SystemEnvironmentPropertySource("systemEnv", System.getenv()));
    
    // Optional: Add JNDI properties (more on this below)
    Context jndiContext = new InitialContext();
    propertySources.addLast(new JndiPropertySource("jndiProps", jndiContext));

    configurer.setPropertySources(propertySources);
    configurer.setIgnoreUnresolvablePlaceholders(true);
    return configurer;
}

Important: Mark the bean as static—this ensures it initializes early enough to process placeholders in other beans like your widgetsRestBaseUrl bean.

Exposing JNDI Variables as Placeholders

To use JNDI variables in ${...} placeholders, add a JNDI property source to your placeholder configurer. The Java config above already includes this, but if you prefer XML, combine <context:property-placeholder /> with a custom property source bean:

<bean id="jndiPropertySource" class="org.springframework.core.env.JndiPropertySource">
    <constructor-arg name="name" value="jndiProps" />
    <constructor-arg name="jndiContext">
        <bean class="javax.naming.InitialContext" />
    </constructor-arg>
</bean>

<context:property-placeholder ignore-unresolvable="true">
    <context:property-sources>
        <context:ref bean="jndiPropertySource" />
        <context:property-source name="systemEnv" properties-ref="systemEnvironment" />
    </context:property-sources>
</context:property-placeholder>

<bean id="systemEnvironment" class="java.util.HashMap">
    <constructor-arg value="#{systemEnvironment}" />
</bean>

Now you can reference JNDI variables using ${yourJndiVariableName} just like environment variables.

Quick Validation Steps

  1. Check if Spring sees your environment variable: Inject Environment into a bean and print the value to confirm:
    @Autowired
    private Environment env;
    
    @PostConstruct
    public void verifyEnvVar() {
        System.out.println("widgetsRestBaseUrl: " + env.getProperty("widgetsRestBaseUrl"));
    }
    
  2. Confirm jndi.xml is loaded: Ensure your jndi.xml is included in your Spring context (via @ImportResource in Java config, <import /> in XML, or configured in web.xml for Tomcat).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 16:59:05