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}
Related
I am using spring 3 but my configuration is xml based in which I am trying to convert my project into annotation based using #configuration annotation.
I am little confused how to add data source entry as #Bean for two below cases
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/myds" />
</bean>
<bean id="data_source" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="url1" />
<property name="username" value="user1" />
<property name="password" value="****" />
</bean>
In the Java Spring bean configuration of dataSrouce, I tried to define init and destroy attributes which call my mysql scripts as initialization and cleanup for unit tests, as the code shown below:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="destroy" init-method="init">
<property name="destroy">
<value>classpath: mysql_dropuser.sql</value>
</property>
<property name="init">
<value>classpath: mysql_createuser.sql,classpath: mysql_bootstrap.sql</value>
</property>
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF-8" />
</bean>
But I got the error:
Invalid property 'destroy' of bean class.
My question is that how I could define the init and destroy methods in the xml file?
This is how I did it once before, hope this helps:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/testdb" />
<property name="username" value="testuser" />
<property name="password" value="testuser" />
<property name="initialSize" value="5" />
<property name="maxActive" value="20" />
<property name="maxIdle" value="20" />
<property name="maxWait" value="5000" />
</bean>
<jdbc:initialize-database data-source="dataSource" ignore-failures="ALL">
<jdbc:script execution="INIT" location="classpath:database/schemas/create_testdb.sql" />
<jdbc:script execution="INIT" location="classpath:database/schemas/add_testdata.sql" />
<jdbc:script execution="DESTROY" location="classpath:database/schemas/drop_testdb.sql" />
</jdbc:initialize-database>
It seems like you have already defined init/destroy methods (they are specified via corresponding attributes). And you should also have public void no-argument methods with that names in your class. Properties are a bit different; as usual they are considered as combination of private field and public get/set methods. So in your case at least setter method public void setDestroy(String str) is expected. Please, check your bean's class to meet these conventions. You may also look for 'spring resource' (http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/io/Resource.html) injection, since you're trying to provide file paths into you bean.
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
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>
I have the following partial spring context xml file:
<bean name="template" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean name="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassLoader" value="" /> <!-- THIS PROPERTY -->
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3061/my_database" />
<property name="username" value="username" />
<property name="password" value="password" />
<property name="initialSize" value="8" />
</bean>
How do I inject the driverClassLoader property? (I'm using some custom plug-in architecture but not the spring dm server so have to provide a classloader to find the mysql driver)
this apache dbcp classloader bug was just fixed in march 2011.
It may fix your root issue so you don't need to inject the classloader...
https://issues.apache.org/jira/browse/DBCP-333
without this bug fix I don't think the driverClassloader setter was working....
I think you want to use the PropertyPlaceholderConfigurer. Look at section 3.7.2.1 in the Spring 2.0 reference guide.