7

I am using spring 3.1 with spring profiles to load the beans. In my app context file, I load the properties like :

<context:property-placeholder order="1"  location="classpath*:META-INF/spring/*_${spring.profiles.active}.properties" ignore-unresolvable="true"/>

And then I use the property value to load the data source bean like

<property name="driverClassName" value="${database.driverClassName}"/>

It works fine. The problem starts when I add a couple of more property placeholders so that properties from some database tables can be loaded.

This uses a properties reference loaded by

<bean id="configFactoryBean"
class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
   <constructor-arg ref="globalSystemConfiguration"/>
</bean>

To add to the details, this configFactoryBean uses the datasource to load the properties from the database.

When I do this, I have the following exception:

java.lang.ClassNotFoundException: ${database.driverClassName}

My analysis is that its trying to load the datasource before resolving the property from the first context property placeholder. I may be wrong. Or maybe spring profile variable is not resolved properly.

Can anyone please help me to fix this.

Thanks Akki

blackpanther
  • 10,998
  • 11
  • 48
  • 78
Abby
  • 403
  • 2
  • 6
  • 18

4 Answers4

11

This bug about multiple property placeholders might relate to your problem: https://jira.spring.io/browse/SPR-9989

When using multiple PropertyPlaceholderConfigurer in conjunction with @Value annotation and default value for placeholders syntax (ie ${key:defaultValue}), only the first PropertyPlaceholderConfigurer is used. If this configurer does not contain the desired value, it falls back to @Value default even if the second PropertyPlaceholderConfigurer contains the value.

Affects Version/s: 3.1.3

Vadim
  • 8,701
  • 4
  • 43
  • 50
user3415190
  • 111
  • 1
  • 3
4

In my application I am using property-placeholder configurer in following way and it works very well. You can try that.

<bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
          <property name="locations">
            <list>
                <value>classpath*:META-INF/spring/*_${spring.profiles.active}.properties</value>
            </list>
          </property>
    </bean>

I think this should resolve your problem. :)

PlasmaHH
  • 15,673
  • 5
  • 44
  • 57
Japan Trivedi
  • 4,445
  • 2
  • 23
  • 44
4

Each <context:property-placeholder> creates a new instance of PropertyPlaceholderConfigurer - it gets messy easily. You should have one such thing per application and on application level, not on libraries' one - that makes maintenance much easier.

For more details and a suggestion how to cope with it look here: http://rostislav-matl.blogspot.cz/2013/06/resolving-properties-with-spring.html

Rostislav Matl
  • 4,294
  • 4
  • 29
  • 53
  • But `order` attribute introduced to resolve this issue (instead of creating a new instance reuse and maintain a chain of property sources). Currently https://jira.spring.io/browse/SPR-9989 is open. – gavenkoa Jul 14 '14 at 14:15
1

Since you have suggested hardcoding the path to the configuration file works, try using the profiles attribute on the tag to selectively include the configuration.

<beans profile="profileName">
    <context:property-placeholder  order="1"  location="classpath*:META-INF/spring/hardcoded.properties" ignore-unresolvable="true"/>
</beans>

<beans profile="profileName2">    
    <context:property-placeholder order="1"  location="classpath*:META-INF/spring/hardcoded.properties" ignore-unresolvable="true"/>
</beans>

See this article explaining profiles: http://java.dzone.com/articles/using-spring-profiles-xml

Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
  • It works if i remove the other two tags. It's not able to resolve the property i guess – Abby Jun 03 '13 at 09:15
  • Do the other two property-placeholders have an order specified? – Kevin Bowersox Jun 03 '13 at 09:20
  • @user1517723 How does `CommonsConfigurationFactoryBean` play a part? – Kevin Bowersox Jun 03 '13 at 09:23
  • it creates a properties object from the org.apache.commons.configuration.DatabaseConfiguration as i load the properties from the database. this internally uses the datasource specified – Abby Jun 03 '13 at 09:25
  • @user1517723 I can't even find that thing in the documentation anywhere, I did find a forum post saying it wasn't supported in Spring 3.x here: http://forum.springsource.org/archive/index.php/t-125884.html – Kevin Bowersox Jun 03 '13 at 09:27
  • @user1517723 Are you missing the .jar file containing `CommonsConfigurationFactoryBean`? – Kevin Bowersox Jun 03 '13 at 09:31
  • If CommonsConfigurationFactoryBean is not supported, how I load the properties from database by using xml bean definitions – Abby Jun 03 '13 at 09:34
  • I think I have a problem with spring profiles. When I remove the profile specific attribute from the first context properties placeholder and manually hardcode a profile, it works. Why is the second placeholder causing a conflict with spring profiles – Abby Jun 03 '13 at 09:41
  • Can you post the config for the second placeholder or is this coming from CommonsConfigurationFactoryBean? – Kevin Bowersox Jun 03 '13 at 09:42
  • its coming from CommonsConfigurationFactoryBean. – Abby Jun 03 '13 at 09:43
  • I don't think your first property placeholder is actually being loaded. So the app can't make the database connection to get the other properties. – Kevin Bowersox Jun 03 '13 at 09:46
  • What can be the problem. If I remove the second placeholder, everything works fine – Abby Jun 03 '13 at 09:47
  • I tried the example at forum.springsource.org/archive/index.php/t-125884.html but I still have the same problem. Any ideas? Am really stuck here – Abby Jun 03 '13 at 10:28