Accessing PropertySources in the Spring 3.1 application xml

1.8k views Asked by At

I'm using the Spring ApplicationContextInitializer to add PropertySources to the Enviroment. I have verified that that part is working as in it's loading the properties into the PropertySources. The part that I'm struggling with is figuring out how to access the Property values that were loaded in the ApplicationContextInitializer within the Spring XML configuration as well as the Java code itself.

Here is a snippit of my ApplicationContextInitializer:

public class ExternalPropertiesApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        Properties properties = load_properties_from_external_source();
        PropertiesPropertySource propertySource = new PropertiesPropertySource("external", properties);
        applicationContext.getEnvironment().getPropertySources().addFirst(propertySource);
    }
}

So this loads up my Properties which has key,value pairs like:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
jdbc.username=user
jdbc.password=passwd

My Spring configuration file looks like this:

<context:component-scan base-package="com.example"/>
<context:property-placeholder ignore-resource-not-found="true" system-properties-mode="OVERRIDE"/>

<bean id="myds" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

This is failing because it doesn't recognize ${jdbc.driverClassName}. I also tried #{external.jdbc.driverClassName} which fails too. The first fails because I'm not explicitly loading jdbc.properties in my Spring configuration file (which is the intent). The latter fails because it can't find the external bean. What step am I missing? How do I expose the property values that were loaded externally?

I also have a Java class like so:

package com.example;

@Component
public class MyClass {
    @Value("${jdbc.url}")
    private String jdbcUrl;
}

Similar to the Spring configuration, how would I access the jdbc.url property values that were loaded upon initialization?

Oh and here is a snippit of the web.xml:

<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>com.example.ExternalPropertiesApplicationContextInitializer</param-value>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
1

There are 1 answers

0
codemonkey007 On

There were a couple of issues with the Spring configuration file that was the culprit.

Specifically, in the heading, I had:

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

despite being on Spring 3.1. That caused Spring to revert to the old PropertyPlaceholderConfigurer rather than the new PropertySourcesPlaceholderConfigurer.

Once I changed the 3.0.xsd reference to 3.1.xsd, it started to resolve the issue. The new header looks like so:

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd">

The second issue was this line:

<context:property-placeholder ignore-resource-not-found="true" system-properties-mode="OVERRIDE"/>

Because of the system-properties-mode attribute, Spring again reverted back to the old PropertyPlaceholderConfigurer and not the new PropertySourcesPlaceholderConfigurer.

When using the old PropertyPlaceholderConfigurer, it doesn't pick up the values from the new Environment which was why the property values weren't being picked up in the Spring Context configuration.