0

One may dynamically load Spring profiles by implementing ApplicationContextInitializer and adding Spring profiles to the environment.

The problem is that in one of projects I am helping in they are using properties stored in database. How to load property representing additional active Spring profiles from the database and than injecting it to the environment. In ApplicationContextInitializer I cannot use Spring beans because the application context is not yet fully initialized. Is low level access to the database my only option?

goroncy
  • 2,053
  • 1
  • 19
  • 16
  • 1
    That would be the only obtain, you can still use a `JdbcTemplate` to make it a little easier, but you would have to construct a `DataSource` yourself for that action or retrieve it from JNDI for instance. – M. Deinum Sep 11 '15 at 08:03
  • @M.Deinum That is what I thought so. JdbcTemplate is by no means bad but I just had a small hope that the problem may be resolved by somehow using existing infrastructure (e.g. DAO) to obtain the info about props in db. Also another approach which is way too hardcore would be to wait until context is initialized -> read props -> restart the context by closing old one and starting the new one (slow and ugly). – goroncy Sep 11 '15 at 08:24

1 Answers1

0

Spring PropertyPlaceholderConfigurer needs to be initialized with a location property that is the properties file you want. But, this class can be also initialized with a java.util.Properties object.

From deprecated project Spring-Modules, you can find here this class that implements InitializingBean and FactoryBean Spring clases, such way it behaves like a normal java.util.Properties object which can be passed on to PropertyPlaceholderConfigurer.setProperties() method.

This way you can take advantage of org.apache.commons.configuration.DatabaseConfiguration which acts like a Properties object but reading properties from a database. For example, think of this bean configuration:

<bean 
    name="MyDatabaseConfiguration"
    class="org.apache.commons.configuration.DatabaseConfiguration">

    <constructor-arg type="javax.sql.DataSource" ref="someDataSource"/>
    <constructor-arg index="1" value="SCHEMA.PROPERTIES_TABLE"/>
    <constructor-arg index="2" value="KEY"/>
    <constructor-arg index="3" value="VALUE"/>
</bean>

Here, arg 1 is the table that contains the properties, arg 2 the key column ans arg 2 the value column.

So, you can create your custom class, very similar to CommonsConfigurationFactoryBean and use in this way:

<bean 
    name="PropertyPlaceholderConfigurer"     
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="properties" ref="MyCustomClass"/>
</bean>

Where MyCustomClass is the class you will use to wrap MyDatabaseConfiguration.

Hope it helps.

malaguna
  • 4,183
  • 1
  • 17
  • 33
  • org.apache.commons.configuration.DatabaseConfiguration will not help us. The structure of properties is much more complex there than just key and value. And the question is about loading Spring profiles. Loading them has to be done way before finalizing bean definitions (in ApplicationContextInitializer for example). – goroncy Sep 14 '15 at 07:57