I want to read in a properties file with my data source connection information and be able to get those values from my Spring-Datasource.xml file. Here is what I have:
Code
Properties prop = properties.load(new FileReader(fileName));
PropertySource myPropertySource = new MyPropertySource(prop);
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext(new String[]{"/applicationContext.xml"},false);
applicationContext.getEnvironment().getPropertySources().addFirst(myPropertySource);
System.out.println(applicationContext.getEnvironment().getProperty("database.username"));
applicationContext.refresh();
This will display the correct value for database.username.
Spring-Datasource.xml
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driver}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
I end up with the following error, it does not seem to find any of the properties.
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in class path resource [Spring-Datasource-dev.xml]: Could not resolve placeholder 'database.driver'
Am I accessing them wrong, or missing something? Thanks.
You have typos... instead of this:-
<property name="username" value="%{database.username}"/>
<property name="password" value="%{database.password}"/>
... do this:-
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
If that doesn't solve the problem, then you may have forgotten to define PropertyPlaceholderConfigurer:-
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:messages.properties"/>
</bean>
If you are trying to load dynamic properties file, you can try this: PropertyPlaceholderConfigurer: can i have a dynamic location value
Related
This is a question that was asked in an interview .
The question was that a bean has certain properties which we configure in .xml file and then we inject it but let's say that one does not know that the properties or the properties will be different for different Beans . So how will we make that bean so that we are able to configure it in runtime ?
I think externalizing the bean values, something like:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:com/foo/jdbc.properties</value>
</property>
</bean>
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
then following the example having your jdbc.properties file:
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root
the properties can be configured at runtime
I work with Spring 3.2.2 . I want to use db.properties file for DB parameters
db.properties
db.driver=org.postgresql.Driver
db.url=jdbc:postgresql://localhost:5432/test
db.user=test
db.password=test
spring configuration
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.user}"/>
<property name="password" value="${db.password}"/>
</bean>
but I have error
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'driverClassName' threw exception; nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [${db.driver}]
Can anybody help me?
Try to define you property file in spring as:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:db.properties</value>
</property>
</bean>
and than access it in a same way as you did.
AWS talks about System.getProperty("JDBC_CONNECTION_STRING") in http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_Java.managing.html after we set up our environmental variables. All great except I can't call System.getProperty inside my Spring XML configuration code nor I can call for resource bundle shortcuts since resources bundle itself has to extract somehow these environmental variables to serve them. Could you kindly help me please to convert this example config to use environmental variables ? :-)
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://secrethost:007/whois?autoReconnect=true" />
<property name="username" value="bond" />
<property name="password" value="abuginsidemistycorner" />
<property name="initialSize" value="100" />
<property name="minEvictableIdleTimeMillis">
<value>300000</value>
</property>
<property name="timeBetweenEvictionRunsMillis">
<value>60000</value>
</property>
<property name="maxIdle" value="20" />
</bean>
I was not able to understand what do people do here:
Can I use an Environment variable based location for Spring FileSystemResource? which would work for recent spring version?
First add a <context:property-placeholder .. /> element to your configuration.
<context:property-placeholder />
Then simply use placeholders in your config.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="${JDBC_CONNECTION_STRING}" />
<property name="username" value="bond" />
<property name="password" value="abuginsidemistycorner" />
<property name="initialSize" value="100" />
<property name="minEvictableIdleTimeMillis" value="30000" />
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<property name="maxIdle" value="20" />
</bean>
Make sure that the placeholder names match your variables you have setup.
If you are using the class org.springframework.beans.factory.config.PropertyPlaceholderConfigurer to load the property files, you can set the property systemPropertiesMode to the value SYSTEM_PROPERTIES_MODE_OVERRIDE.
In the spring.xml you'll have this bean:
<bean id="propertyPlaceholder"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="locations">
<list>
<value>classpath://file.properties</value>
</list>
</property>
</bean>
Spring will load the system properties in this way:
Check system properties first, before trying the specified properties.
This allows system properties to override any other property source.
In this way you should be able to read the system properties as normal properties.
For someone who use JavaConfig:
In #Configuration file we need to have:
#Bean
public static PropertyPlaceholderConfigurer properties() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ClassPathResource[] resources = new ClassPathResource[ ] {
new ClassPathResource("db.properties")
};
ppc.setLocations( resources );
ppc.setIgnoreUnresolvablePlaceholders( true );
ppc.setSearchSystemEnvironment(true);
return ppc;
}
#Value("${db.url}")
private String dbUrl;
#Value("${db.driver}")
private String dbDriver;
#Value("${db.username}")
private String dbUsername;
#Value("${db.password}")
private String dbPassword;
#Bean
public DataSource db() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(dbUrl);
dataSource.setDriverClassName(dbDriver);
dataSource.setUsername(dbUsername);
dataSource.setPassword(dbPassword);
return dataSource;
}
important is line: ppc.setSearchSystemEnvironment(true);
after that in db.properties, I have:
db.url = ${PG_URL}
db.driver = ${PG_DRIVER}
db.username = ${PG_USERNAME}
db.password = ${PG_PASSWORD}
I am having an issue with loading a .properties file.
The file is called "businessmessages_en_US.properties" and it is stored in "src/main/resources/config/i18n". I have added "src/main/resources" to the build path and in my spring xml I have created a bean:
<bean name="messageResource" id="messageResource"
class="[package].CustomResourceBundleMessageSourceImpl">
<property name="basename">
<value>classpath*:config/i18n/*.properties</value>
</property>
</bean>
Note that the "basename" property must be a string according to the class
Yet every time I run my program, the logger shoots a message:
01 Jul 2013 09:12:34,267 WARN [package].CustomResourceBundleMessageSourceImpl - ResourceBundle [classpath*:config/i18n/*.properties] not found for MessageSource: Can't find bundle for base name classpath*:config/i18n/*.properties, locale en_US
I need the program to read this file so that the logger can have the correct values. Any help would be greatly appreciated. Thank you!
<context:property-placeholder location="classpath*:*.properties"/>
and then use it like this:
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
in my applicationcontext.xml i have this :
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/dashboardsupervisor" />
<property name="username" value="root" />
<property name="password" value="1234" />
</bean>
here i am connecting with my database :
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
MySQLRdbHelper rdbHelper = (MySQLRdbHelper)
ctx.getBean("ManagerSupervisor");
What is want is to NOT read the password "1234" from my applicationcontext.xml
and read it from some properties file in my local drive .
as this will be running on different machines and every one have different passwords.
Can i achieve this .
thanks
Yes, you can, and the key to this is Springs PropertyPlaceholderConfigurer.
For example, you create a file on your file system called database.properties, containing your password (note, that you can also add more settings to this file, like username, JDBC url, etc).
jdbc.password=1234
Next, you need to declare a PropertyPlaceholderConfigurer bean and point it to the database.properties file:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>path/to/database.properties</value>
</property>
</bean>
Note that the path is interpreted as a classpath resource, unless it is prefixed with file:.
Finally, replace the configuration of your dataSource bean: replace
<property name="password" value="1234" />
with
<property name="password" value="${jdbc.password}" />
You could use profiles:
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.getEnvironment().setActiveProfiles("dev1");
ctx.load("*Context.xml");
ctx.refresh();
<bean id="database1" profile="dev1"/>
<bean id="database2" profile="dev2">
The best way is to create the data source in application server and configure as below in application.xml
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>YourDSName</value></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
.....
</bean>