Klaus
Klaus

Reputation: 767

Property from PropertySource is not used

I've got a question for programmatically added properties to a spring context.

GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ConfigurableEnvironment ctxEnvironment = ctx.getEnvironment();
ctxEnvironment.getPropertySources().addFirst(new ResourcePropertySource("rootProperties", new FileSystemResource("/tmp/root.properties")));
ctx.load(new ClassPathResource("/context/application-context.xml"));
ctx.refresh();

root.properties:

test=hello

Snippet from application context:

...
<property name="test" value="${test} world"/>
...

When I load the bean from the context, ${test} is not substituted with "hello".

Spring version: 5.1.5.RELEASE

What am I missing here?

PS: Btw, this works:

 System.out.println("Text: " + ctxEnvironment.resolvePlaceholders("${test}"));

Output:

 Text: hello

EDIT: Sorry, I forgot to add: I don't want to use the context:property-placeholder bean, because I know the location of the properties file only at runtime.

Upvotes: 1

Views: 282

Answers (3)

Klaus
Klaus

Reputation: 767

After some more diving into the spring API I found a pure programmatic solution to my problem without the need of a context:property element. For anyone interested, here is the full source:

Test.java

  public class Test {

      public static void main(String[] args) throws Exception {
          GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();

          PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
          MutablePropertySources propertySources = new MutablePropertySources();
          propertySources.addFirst(new ResourcePropertySource("rootProperties", new ClassPathResource("/root.properties")));
          configurer.setPropertySources(propertySources);
          ctx.addBeanFactoryPostProcessor(configurer);

          ctx.load(new ClassPathResource("/ctx.xml"));
          ctx.refresh();

          TestBean bean = ctx.getBean(TestBean.class);
          System.out.println(bean.getString());
      }
  }

TestBean.java

  public class TestBean {
      String string = "";

      public String getString() { return string; }
      public void setString(String string) { this.string = string; }
  }

ctx.xml

  <?xml version="1.0" encoding="UTF-8"?>
  <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.springframework.org/schema/beans classpath:/org/springframework/beans/factory/xml/spring-beans.xsd">
      <beans>
          <bean class="TestBean">
              <property name="string" value="${test} world"/>
          </bean>
      </beans>
  </beans>

root.properties

  test=hello

Upvotes: 0

Anish B.
Anish B.

Reputation: 16559

Your code is working fine.

I have tested with this.

applicationContext.xml :

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder
        location="application.properties" />
    <bean id="demo"
        class="com.example.Demo">
        <property name="value1" value="${test} world" />
    </bean>
</beans>

application.properties :

test = Hello

Demo.java :

public class Demo {

    String value1;

    public String getValue1() {
        return value1;
    }

    public void setValue1(String value1) {
        this.value1 = value1;
    }

    @Override
    public String toString() {
        return value1;
    }

}

Test.java :

public class Test {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        Demo demo = (Demo) classPathXmlApplicationContext.getBean("demo");
        System.out.println(demo);
        classPathXmlApplicationContext.close();
    }

}

When you run, the output :

Hello world

The problem is with the bean. Please check it.

Upvotes: 0

zpavel
zpavel

Reputation: 969

I reproduced your case and it's working for me. You need to add a property place holder in your applicationContext.xml file :

    <?xml version="1.0" encoding="UTF-8"?>
<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.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="file:/tmp/root.properties" />
    <bean id="myA" class="com.zpavel.MyA">
        <property name="test" value="${test}" />
    </bean>
</beans>

For example a simple bean :

public class MyA {

    private String test;

    public String getTest() {
        return test;
    }

    public void setTest(String test) {
        this.test = test;
    }
}

You can load it with :

ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/context/application-context.xml");
MyA myA = context.getBean(MyA.class);
System.out.println(myA.getTest());

It will print "hello" as expected.

Upvotes: 2

Related Questions