nagy.zsolt.hun
nagy.zsolt.hun

Reputation: 6694

java spring context:property-placeholder - set properties paths from placeholder

<context:property-placeholder
    location="a.properties,b.properties"
    ignore-unresolvable="true"/>

result: both properties file are loaded

<context:property-placeholder
    location="${properties_location}"
    ignore-unresolvable="true"/>

where properties_location is "a.properties,b.properties"

result: Exception in thread "main" org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.FileNotFoundException: class path resource [a.properties,b.properties] cannot be opened because it does not exist

edit: ${properties_location} is set the following way:

System.getProperties().setProperty("properties_location", "a.properties,b.properties");
ApplicationContext ctx = new GenericXmlApplicationContext("context.xml");
...

How can I initialize my application the 2nd way? to have all the properties file's path defined in a placeholder.

Upvotes: 1

Views: 1231

Answers (3)

M. Deinum
M. Deinum

Reputation: 124441

From the source of the parser for the property-placeholder element.

String location = element.getAttribute("location");
if (StringUtils.hasLength(location)) {
    String[] locations = StringUtils.commaDelimitedListToStringArray(location);
    builder.addPropertyValue("locations", locations);
}

First the location is retrieved, if that has a value it is converted to a String[]. Springs conversion service takes care of replacing any placeholders in the String[]. But at that moment the properties_location placeholder is just a single element in the array and that gets resolved to a.properties,b.properties without further processing.

So at the moment this isn't possible with placeholders I'm afraid.

One thing that might work is using SpEL if it is always going to be a system property you can use #{systemProperties['properties_location']} to resolve the value. That should be resolved before anything else.

Upvotes: 1

ConMan
ConMan

Reputation: 1652

You cant use a property placeholder as a value in a placeholder placeholder resolver. Its like saying, "hey, resolve the placeholder for the location of the all the properties, and then you can start resolving properties!".

Logically it just dosent make sense. I was experimenting with spring property placeholder resolution recently, and stumbled upon this same question. I attempted to use two property placeholder configurers, one to resolve the location of the properties for the second, and the second to resolve the rest of the properties. Of course this dosent work due to the way in which spring initialises its beans.

  1. Initialise bean post processors
  2. Construct them
  3. Construct all other beans

Since the property placeholder configurer is a bean post processor, if you have more than one of them, they get initialised and constructed at the same time, so know nothing of each others properties at construction

Edit

Given that the property location is a system property you could have:

System.getProperties().setProperty("properties_location_a", "classpath:/a.properties");
System.getProperties().setProperty("properties_location_b", "classpath:/b.properties");

And then in your spring content.xml:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="ignoreUnresolvablePlaceholders" value="true"/>
  <property name="locations">
    <list>
      <value>${properties_location_a}</value>
      <value>${properties_location_b}</value>
    </list>
  </property>
</bean>

Upvotes: 0

Jens
Jens

Reputation: 69440

You have to change this to:

<context:property-placeholder
location="classpath:a.properties,
          classpath:b.properties"
ignore-unresolvable="true"/>

Upvotes: 1

Related Questions