Announcement Announcement Module
Collapse
No announcement yet.
PropertyResourceConfigurer depends on another Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • PropertyResourceConfigurer depends on another

    I want to conditionally apply one properties file based on the values specified in another properties file. application.properties is meant to modified by deployers and specifies the dbType like so:
    Code:
    dbType=oracle
    Then I have properties files that define specific properties per database type, like oracle.properties:
    Code:
    hibernate.dialect=net.sf.hibernate.dialect.OracleDialect
    or mssqlserver.properties:
    Code:
    hibernate.dialect=net.sf.hibernate.dialect.SQLServerDialect
    Those properties are not included in application.properties because they are not meant to be modified by deployers and we don't want Hibernate-specific settings to be exposed.

    I want to conditionally include one of the db-specific files based on the dbType value at run-time. If dbType is oracle, include oracle.properties; if dbType is mssqlserver, mssqlserver.properties, etc. I set up my bean definitions like this:
    Code:
    <bean id="appProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location"><value>application.properties</value></property>
    </bean>
    
    <bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
        <property name="location"><value>$&#123;dbType&#125;.properties</value></property>
    </bean>
    That doesn't work the way I expected it to; the resource loader in PropertyOverrideConfigurer attempts to load a file named "${dbType}.properties", not "oracle.properties".

    The reason for this is in the method invokeBeanFactoryPostProcessors() in AbstractApplicationContext. It queries the internal bean factory for all beans of type BeanFactoryPostProcessor. The first post-processor (appProperties) runs and and correctly sets the value of the property "location" on the bean definition for "hibernateProperties" to be "oracle.properties". Then it attempts to run the second post-processor ("hibernateProperties"), but which results in a Fil. That is because the post-processor bean was instantiated before the property value was modified by the first post-processor ("appProperties").

    As a result, I cannot have a PropertyResourceConfigurer that has values set by another PropertyResourceConfigurer (either PropertyPlaceholderConfigurer or PropertyOverrideConfigurer). I investigated modifying invokeBeanFactoryPostProcessors() in AbstractApplicationContext, but any changes to the bean definition would require a full bean factory refresh to appear, which doesn't seem like a good thing. Suggestions? Thanks.

  • #2
    In my particular case, I now see that I can use PropertiesFactoryBean to load the second set of properties and set those on the sessionFactory directly. It appears that I could also use PropertyPathFactoryBean to refer to the properties loaded there, but that is really clunky and I don't know if that would apply to all cases.

    Comment


    • #3
      Rudely replying to myself again for the benefit of anyone who encounters this need. I have a clunky but effective solution. In one application context, define the following:
      Code:
      <bean id="appPropertiesPlaceholder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
          <property name="location">
              <value>application.properties</value>
          </property>
      </bean> 
      
      <bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
          <property name="location">
              <value>$&#123;dbType&#125;.properties</value>
          </property>
      </bean>
      Add that as a parent context of the original context. Then in the child context, put:
      Code:
      <bean id="hibernatePropertiesOverride" class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
          <property name="properties">
              <bean ref="hibernateProperties" />
          </property>
      </bean>
      I don't like this because it forces you to break off a parent context that you wouldn't otherwise have had to create. It would be nice if you could add properties to the application context itself and then the default PropertyEditor for the String class would understand how to look them up and substitute the appropriate values.

      Comment


      • #4
        for this specific case you could also use:
        Code:
        #dbType, possible values
        #oracle&#58;     Oracle
        #mssqlserve&#58; SQLServer
        dbType=Oracle
        
        #dialect
        hibernate.dialect=net.sf.hibernate.dialect.$&#123;dbType&#125;Dialect

        Comment

        Working...
        X