I use Spring bean profile to separate each datasource environments:
<bean id="fooJDBCTemplate" class="com.rakuya.r_erp.task.dao.FooJDBCTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<beans profile="dev">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://somewhere:3306/erp?characterEncoding=UTF-8" />
<property name="username" value="" />
<property name="password" value="" />
</bean>
</beans>
<beans profile="qa">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://somewhere:3306/erp?characterEncoding=UTF-8"/>
<property name="username" value=""/>
<property name="password" value=""/>
</bean>
</beans>
<beans profile="prod">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://somewhere:3306/erp?characterEncoding=UTF-8"/>
<property name="username" value=""/>
<property name="password" value=""/>
</bean>
</beans>
And i use following command to build jar file and specify profile
mvn clean package -Dspring.profiles.active=prod
But i got the error about no definition of dataSource when executing the jar file.
It seems like Maven does not use the Spring profile to build jar.
How can I configure the Maven or Spring peofile to use the dataSource ?
Thx
You need to pass the profile -D switch when you run your app.
Since your bears are all the same type (DriverManagerDataSource) and the only thing that differs between environments are some of the properties, I think it would be best to get rid of the spring profiles and use properties to set these values. PropertyPlaceholderConfigurer should be able to handle this scenario where you set a vm param specifying what environment you want. Something like -Denv=dev.
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:${env}.properties</value>
</list>
</property>
</bean>
Then you would only need one datasource bean like the following:
<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.username}" />
<property name="password" value="${db.password}" />
</bean>
And a property file for each environment named dev.properties, qa.properties, and prod.properties with values in each for db.driver, db.url, etc.
When spring starts up it will select the appropriate properties file based on the value passed in with -Denv and load the corresponding property values into your datasource bean.
Related
Hi I want read properties for dev,prod environments , Is this any way do this?
I'm doing like below ,but no use
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-
method="close" id="dataSource">
<property name="driverClassName" value="${jdbc.driver.class}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxIdle" value="20"/>
<property name="maxActive" value="20"/>
</bean>
<bean
class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer"
id="bridgePropertyPlaceholder">
<property name="location" value="classpath:db-${envTarget}.properties"/>
</bean>
I'm doing like this and giving my goal as
clean install -DenvTarget=dev
but not working, please help me here .
Use Spring profiles and environment abstraction for this.
Then you can simply use different property files like db-[profilename].properties and they are automatically loaded according to the active profiles.
I'm wondering if its possible to load properties from both file and database, and use the properties in file when loading properties in database. So what I want to achieve is to save app properties in the database, and save the database info in the properties file. Below is my configuration, but it didn't work, the value in jdbc.properties cannot be loaded before reading database properties. Can anyone help me on this? Thanks!
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:jdbc.properties</value> <!--loading properties from file first-->
</list>
</property>
<property name="properties" ref="dataBaseProperties"/> <!--loading properties from database using the properties from file-->
</bean>
<bean id="dataBaseProperties" class="common.spring.DatabaseProperties" >
<constructor-arg type="javax.sql.DataSource" ref="confDataSource"/>
<constructor-arg value="select key_s,value_s from app_conf where status>0"/>
</bean>
<bean id="confDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"/> <!--from properties file - jdbc.properties-->
<property name="url" value="${jdbc.url}"/> <!--from properties file - jdbc.properties-->
<property name="username" value="${jdbc.username}"/> <!--from properties file - jdbc.properties-->
<property name="password" value="${jdbc.password}"/> <!--from properties file - jdbc.properties-->
</bean>
> <beans:bean id="appProperties"
> class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
> <beans:property name="location"
> value="classpath:META-INF/application.properties" /> </beans:bean>
You should mention the location from where it fetches the *.properties file
I use Oracle in production environment and I would like to use H2 for testing. I can type;
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:schema.sql"/>
<jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>
so my tables and scripts are created automatically. But I cannot set URL value of this db. (For H2-Oracle compatibility I should add ;MODE=Oracle to url part)
is there a way to achieve this goal?
Or just an opposite solution;
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:file:h2\db"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
in this time, I can edit URL part, but how can I load default test scripts (create and data sqls) to this datasource?
This technique solved the problem;
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<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>
and then adding this tag and definition;
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
<jdbc:script location="classpath:testdb/schema.sql" />
<jdbc:script location="classpath:testdb/data.sql" />
</jdbc:initialize-database>
Maybe this will help: H2 supports an INIT script (a SQL script which is executed when opening the connection). The database URL would look like this in the XML file:
<property name="url" value="jdbc:h2:file:h2\db;INIT=
RUNSCRIPT FROM 'classpath:schema.sql'\;
RUNSCRIPT FROM 'classpath:test-data.sql'"/>
(the ; needs to be escaped with a backslash).
This was my first attempt at Spring with JNDI but getting the below mentioned exception when trying to create the ApplicationContext like:
ApplicationContext context = new ClassPathXmlApplicationContext("master-job.xml");
The Spring configuration file is as follows:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="/jdbc/Eqpstatus"/>
<property name="resourceRef" value="true" />
</bean>
<bean id="masterDao" class="com.dao.MasterDao">
<property name="dataSource" ref="dataSource"/>
</bean>
On Server i have the required resource entry for the JNDI name.
<Resource auth="Container" driverClassName="oracle.jdbc.OracleDriver"
maxActive="10" maxIdle="2" maxWait="10000" name="jdbc/Eqpstatus"
password="xxxx" type="javax.sql.DataSource"
url="jdbc:oracle:thin:#(DESCRIPTION=(LOAD_BALANCE=on)(ADDRESS=(PROTOCOL=TCP)(HOST=xxxx) (PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=xxxx) (PORT=1521))(CONNECT_DATA=(SERVICE_NAME=xyz)))"
username="xxx"/>
The error i see is:
javax.naming.NameNotFoundException: Name jdbc is not bound in this Context
Would highly appreciate any inputs on this as am new to Spring-JNDI integration.
First, I think you should use the dedicated tag instead of declaring a "JndiObjectFactoryBean" bean :
<!-- JNDI DataSource for J2EE environments -->
<jee:jndi-lookup id="dataSource" jndi-name="java:jdbc/rppsDS-PUB-PROTO" default-ref="localDataSource" />
<!-- local dataSource for JUnit integration tests -->
<bean id="localDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="100"/>
<property name="maxWait" value="1000"/>
<property name="poolPreparedStatements" value="true"/>
<property name="defaultAutoCommit" value="true"/>
</bean>
Then, you need a jndi.properties file (which could be directly in application server dir such as JBoss) with a content similar to :
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost:1099
If you are using Tomcat and everything is fine with your Tomcat configuration; this should be enough:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/dataSource" />
Where jdbc/dataSource is the name defined in your Tomcat config.
EDIT:
My bad, forgot about the jndi.properties; there are two possibilities:
either provide a jndi.properties on your classpath or
set the values in a in the <jee:jndi-environment/> element of <jee:jndi-lookup /> (see reference)
The java.naming.factory.initial property needs to be set for sure, to something like org.apache.naming.java.javaURLContextFactory, possibly some other values as well, like:
java.naming.factory.url.pkgs=org.apache.naming
java.naming.factory.url.pkgs.prefixes=org.apache.naming
java.naming.provider.url=org.apache.naming
Also see reference.
How can I setup connection pooling in Spring MVC? I am working on an intranet website powered by Spring MVC 2.5 and jQuery. This is my first attempt at web development.
I am not sure but, I am only using this in my spring configuration file and I saw this in the Spring MVC step By Step tutorial
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<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>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
This looks good during development and connection speed is fast but I am not sure if this will still holds true if many users are concurrently connected.
How can I achieve this? I have read that this is not an optimal connection datasource.
You might want to look at c3p0, which has some powerful configuration and optimization available.
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="..." />
<property name="jdbcUrl" value="..." />
<property name="user" value="..." />
<property name="password" value="..." />
</bean>
Your current setup is correct, all you need to do in order to use basic connection pooling is use a DataSource implementation provided by a connection pooling library, in your case Apache DBCP. See this post for a few links to other alternatives, C3P0 being one of them.
Note that when you actually use the DataSource bean you're injecting wrap it in a SimpleJdbcTemplate or use DataSourceUtils to obtain a Connection - see Spring JDBC Documentation
For connection Pooling
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
//Add this two more parameters
<property name="**initialSize**" value="20" />
<property name="**maxActive**" value="30" />
</bean>
connection pool will create 20 database connection as initialSize is 20 and goes up to 30 Database connection if required as maxActive is 30.