Spring: Loading properties from a database and local files

I am trying to load properties from a database. I have succeeded in this. But now the problem is that for the dataSource bean I want to use placeholders. See applicationProperties.xml, then you can get a view:

<!-- Data Source Bean --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${driverClassName}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </bean> <!-- My Own class for managing properites came from Database --> <bean class="PropFromDB.PropFromDB.PropertiesUtil" > <property name="propertiesArray"> <list> <ref bean="propertiesFromDB" /> </list> </property> </bean> <!-- PropertiesFactoryBean bean --> <bean id="propertiesFromDB" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="properties" ref="commonsConfigurationFactoryBean" /> </bean> <!-- CommonsConfigurationFactoryBean bean --> <bean id="commonsConfigurationFactoryBean" class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean"> <constructor-arg ref="databaseConfiguration"></constructor-arg> </bean> <!-- DatabaseConfiguration bean --> <bean name="databaseConfiguration" class="org.apache.commons.configuration.DatabaseConfiguration"> <constructor-arg index="0" ref="dataSource" /> <constructor-arg index="1" value="properties" /> <constructor-arg index="2" value="key" /> <constructor-arg index="3" value="value" /> </bean> 

The above code is designed to load properties from the database. now, as you can see for the dataSource bean, some placeholders are used. So I included this line at the top:

 <context:property-placeholder location="classpath:databaseForConfiguration.properties"/> 

databaseForConfiguration.properties contains all the necessary properties in the classpath :

 driverClassName=org.postgresql.Driver url=jdbc:postgresql://localhost:5432/mydb username=user password=pass 

But when I try to execute, I get the following exception:

  Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are: PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'driverClassName' threw exception; nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [${driverClassName}] at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:108) at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:62) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1489) ... 60 more 

and similar for {url} , {username} , {password} .

As you can easily understand, to initialize a propertyUtil bean, you must first initialize the dataSource bean. And for the dataSource bean there must be local property placeholders. Which in this case does not receive.

I want both of these things , loading placeholders from local files and also from the database .

Someone please help me solve this problem.

early.

+7
spring
source share
2 answers

For

 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${driverClassName}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </bean> 

I created a factory for the data source. and now it looks like this:

 <bean id="dataSource" class="core.factory.DataSourceFactory" factory-method="createDataSource"> <constructor-arg type="java.lang.String" value="DBConfig.properties" /> </bean> 

The DataSourceFactory class is as follows:

 public class DataSourceFactory { private static final String DRIVER_CLASS_NAME = "db.driver"; private static final String URL = "db.url"; private static final String URL_LOGDB = "logdb.url"; private static final String USER_NAME = "db.username"; private static final String PASSWORD = "db.password"; public static DataSource createDataSource(String propertyFilename) throws IOException { Properties properties = getProperties(propertyFilename); return getDataSource(URL, properties); } public static DataSource createDataSourceForLogDb(String propertyFilename) throws Exception { Properties properties = getProperties(propertyFilename); return getDataSource(URL_LOGDB, properties); } private static Properties getProperties(final String fileName) throws IOException { Properties properties = new Properties(); InputStream in = DataSourceFactory.class.getClassLoader().getResourceAsStream(fileName); properties.load(in); in.close(); return properties; } private static DataSource getDataSource(final String url, final Properties properties) { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName(properties.getProperty(DRIVER_CLASS_NAME)); dataSource.setUrl(properties.getProperty(url)); dataSource.setUsername(properties.getProperty(USER_NAME)); dataSource.setPassword(properties.getProperty(PASSWORD)); return dataSource; } } 

Now I can get the properties from the local file as well as the database.

As for another problem, I added comments that were supposed to load i18n resources from the database, I got a solution at this link: Spring MVC: Database MessageSource goes back to the properties file .

I asked a question myself, and now I have a solution. Hope this will be helpful to someone.

+8
source share

First of all, you missed the <context:property-placeholder> . Its location for the file object, not Properties .

That's right, your databaseForConfiguration.properties contains a Properties object from the database, but it is not a .properties file.

So try the following:

 <bean id="myProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" p:staticMethod="org.apache.commons.configuration.ConfigurationConverter.getProperties" p:arguments-ref="databaseConfiguration"/> <context:property-placeholder properties-ref="myProperties"/> 

On the other hand, it is unclear how you intend to load properties from the database if you try to use placeholders for a DataSource . In this case, you should already have <context:property-placeholder> ...

UPDATE

There is a reason to mix multiple answers from different topics. Asn, shown above, MethodInvokingFactoryBean creates the material for creating the Properties object.

If your <context:property-placeholder> cannot allow placeholders ( Could not load JDBC driver class [${driverClassName}] ), then it does not see your databaseForConfiguration.properties in the class path.

Be sure to use the correct location value, for example. location="classpath:WEB-INF/databaseForConfiguration.properties" if your file has a WAR.

+6
source share

All Articles