Does bean creation in spring datasource xml open connection to the database? - java

In Spring while creating beans in the following way in datasource xml does it also establishes a connection with the database?
If it opens a db connection,then how it get closed?
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin#localhost:1521/myoracledb" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
Does rs.close();,ps.close(); and conn.close(); in finally block guarantees connection close where rs is ResultSet object,ps is PreparedStatement object and conn is Connection object.
I am using normal JDBC(with Spring-Datasource.xml) and springMVC and facing some issue with connection remaining open with the database.
Is there any other way to ensure that database connection remain closed in the process?

First thing
The datasource configuration in the spring-context.xml provides Simple implementation of the standard JDBC DataSource interface, configuring a plain old JDBC Driver via bean properties, and returning a new Connection for every getConnection call.
Each time you do a datasourceObject.getConnection() it will establish a new connection for you.
Secondly
Use of (rs.close(), ps.close() and) conn.close() in a finally block guarantees connection close.
Yes it does, that is why it is recommended to close the connection in the finally because even in case of some Exception the finally block will get execute and release the resources

Related

How to verify whether a connection pool has beem set up in spring MVC web app?

In one of my question asked earlier I got to know that DriverManagerDataSource is NOT intended for production use. So I changed my configuration. I know I am using DBCP which is also outdated and a lot of other connection pools are available like HIkariCP and BOneCP but
I wish to understand the way how to verify that a pool has been setup
or not?
On searching a lot I got some answer at the following link
How would you test a Connection Pool
but I didn't get a way to verify programmatically. Also I cannot debug my jar files used for connection pooling because no source code is available. I dont know why but I can't change my jars for offical reasons.
The following are my configuration (OLD and NEW)
OLD
<bean id="webLogicXADataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="#[csa.db.driver]" />
<property name="url" value="#[csa.db.url]" />
<property name="username" value="#[csa.db.username]" />
<property name="password" value="#[csa.db.password]" />
</bean>
NEW
Using DBCP connection pool
<bean id="webLogicXADataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="#[csa.db.driver]" />
<property name="url" value="#[csa.db.url]" />
<property name="username" value="#[csa.db.username]" />
<property name="password" value="#[csa.db.password]" />
</bean>
OTHER ELEMENTS:(Thus far I have kept them same like they were earlier)
Place holder
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:${DB_PROPERTIES}</value>
</list>
</property>
<property name="placeholderPrefix" value="#[" />
<property name="placeholderSuffix" value="]" />
</bean>
Transaction Manager
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="webLogicXADataSource" />
<qualifier value="inventoryTxManager"/>
</bean>
DAOIMPL SAMPLE BEAN
<bean id="inventoryDao"
class="com.lxnx.fab.ce.icce.inventoryRoutingInvoice.dao.InventoryDaoImpl">
<property name="dataSource" ref="webLogicXADataSource" />
<property name="transactionManager" ref="transactionManager" />
Right now all the DAO classes in my project are singleton(no prototype property set for any of the beans)
The following is the sample java code of the DAOImpl.java class where I need to do all the transactions:
DAOImpl.java
public class InventoryDaoImpl implements InventoryDao {
private final static ISmLog iSmLog = Instrumentation
.getSmLog(LNConstants.SYSTEM_LOG_NAME);
private JdbcTemplate jdbcTemplate;
private DataSource dataSource;
private PlatformTransactionManager transactionManager;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.dataSource = dataSource;
}
public void setTransactionManager(
PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
#Transactional private void insertRelatedInfoData(
InventoryModel inventoryModel) {
final List<String> relatedLniList = inventoryModel.getArrRelatedLni();
final String documentLni = inventoryModel.getDocumentLNI();
String sql = "INSERT INTO SCSMD_REPO.INV_RELATED_INFO(LNI, RELATED_LNI) VALUES(?,?)";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
String relatedLni = relatedLniList.get(i);
ps.setString(1, documentLni);
ps.setString(2, relatedLni);
}
#Override
public int getBatchSize() {
return relatedLniList.size();
}
});
}
}
I am not getting any errors. Just wanted to verify If a pool has been setup U wish to verify the same
Are all configurations fine or did I miss something?? Please help me out with you valuable answers. thanks
If you don't have logs enable then you can't verify it. however there is one more donkey logic.
every database server will have timeout functionality. if db not hit by application after some time connection will break. for example mysql server will break it's connection from application after 8 hour (if there is no hit from application). you check modify timeout to minimum time (say 30 min)in mysql config file and check after 30 minutes you get connection close exception in you appication, when you hit db
The easiest way, as explained, would be to examine the logs. It's quite likely that a connection pool will log something, at least if your logging level is low enough.
Another way would be to examine the class of the Connection that the datasource returns. If you're dealing with a connection pool, the class will be a wrapper or a proxy class for that pool. The wrapper/proxy class makes sure that when you call close() the connection isn't really closed, it's just returned to the pool for further use. For example if you were to use HikariCP as your pool, you could check if(connection instanceof IHikariConnectionProxy) to see if the pool is being used.
Adding that kind of code in your software would be a bad idea in practically all cases. If you don't know whether a connection pool is being used or not, it's not something you solve with code. It's something you solve by reading and studying more.
You've also named your bean webLogicXADataSource even though nothing seems to support it being an XA datasource. Are you perhaps working on things a bit too advanced for you?

How to achieve DB concurrency?

I have controller ,service and dao class singleton
Dao Class:
#Autowired
JdbcTemplate jdbcTemplate;
#Override
public String addUsers(UserDTO userDto) throws Exception {
// TODO Auto-generated method stub
System.out.println("JDBC TEMPLATE::"+jdbcTemplate);
String query="Insert into users values('"+userDto.getUserName()+"')";
System.out.println(query);
jdbcTemplate.update(query);
return "success";
}
applicationContext.xml
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<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/demo" />
<property name="username" value="" />
<property name="password" value="" />
</bean>
In dao class I am using JdbcTemplate which is defined as singleton and dataSource bean is also singleton.
Now I have following doubt:
1)If my JdbcTemplate is singleton and dataSource bean is singleton will they cause any problem for concurrent request?
2)Is that the ideal way to make JdbcTemplate bean and injecting in to DAo?
3)Is request scope should only be there if any class hold instance variables?
In order be able to work concurrently against your DB, I would suggest to you to use connection pooling.
When multiple requests will "arrive" concurrently, for each of them the connections pool will assign a dedicated connection to work against the DB.
Of course, that is under your responsibility to make sure you're not accessing to the same "area" in your DB.
In MySql DB I know that there's a locking mechanism for such scenarios, but I would recommend making a deeper research.
There are 2 well-known connection pools:
Apache DBCP http://commons.apache.org/proper/commons-dbcp/
c3po http://www.mchange.com/projects/c3p0/
More detailed explanation:
Connection Pooling
It's a technique to allow multiple clients to make use of a cached set of shared and reusable connection objects providing access to a database.
Opening/Closing database connections is an expensive process and hence connection pools improve the performance of execution of commands on a database for which we maintain connection objects in the pool.
It facilitates reuse of the same connection object to serve a number of client requests.
Every time a client request is received, the pool is searched for an available connection object and it's highly likely that it gets a free connection object.
Otherwise, either the incoming requests are queued or a new connection object is created and added to the pool (depending on how many connections are already there in the pool and how many the particular implementation and configuration can support).
As soon as a request finishes using a connection object, the object is given back to the pool from where it's assigned to one of the queued requests (based on what scheduling algorithm the particular connection pool implementation follows for serving queued requests).

Spring 3 set web application datasource based on connection string queried using another datasource

I have a Spring web application that uses 2 databases. One database has connections strings information and other has business data. So, I would like to set the second datasource based on connection string queried from first datasource. How can this be done? Any ideas please.
I have datasource definitions in the following syntax:
<bean id="userDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.sybase.jdbc3.jdbc.SybDriver" />
<property name="url" value="jdbc:sybase:Tds:127.0.0.1:2999?ServiceName=db" />
<property name="username" value="user" />
<property name="password" value="pass" />
</bean>
Since the second database connection depends on the content queried from the first database, you have to first create a DAO object from the first database and then issue a query to find out the required connection information for the second database, such as url, username, passwprd. After you get all information from the first DB, you can use getConnection method of DriverManager class to get the JDBC connection:
Connection connection = DriverManager.getConnection(url, username, password);
Then you can start using the second DB from there.

Setting connection timezone with Spring and DBCP and MySQL

My Enviroment
Java 5
Spring 2.5.5
DBCP DataSource (org.apache.commons.dbcp.BasicDataSource)
MySQL
Similar posts
Setting session timezone with spring jdbc oracle
Links
http://www.mysqlfaqs.net/mysql-faqs/General-Questions/How-to-manage-Time-Zone-in-MySQL
My Problem
I need to set on my connection the timezone, aiming to prevent the conversions when dealing with TIMESTAMP columns.
My Idea/research
DBCP Connection Pool did not mention anything around timezone. LINK
What I investigate and thought that was oK is described on THIS post, exemplifying is:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="URL" value="${database.url}" />
<property name="user" value="${database.username}" />
<property name="password" value="${database.passwd}" />
<property name="connectionCachingEnabled" value="true"/>
<property name="sessionTimeZone" value="GMT-3"/>
</bean>
Asking for help area :)
But this is not working!!
What I want here is a simple way, preferentially using Spring to configure the timezone on jdbc connection.
Thanks in advance for any help/tips/advice/knowledge share
SOLUTION:
My Solution was based on tips collected on this post! Thanks for all!
(...)
#Override
public Connection getConnection() {
Connection conn = null;
Statement statement = null;
try {
conn = super.getConnection();
statement = conn.createStatement();
statement.execute("SET time_zone = \'" + timezone+"\'");
} catch (SQLException e) {
LOG.fatal("Error while SET time_zone", e);
} finally {
try {
statement.close();
} catch (SQLException e) {
LOG.warn("Error while closing statement", e);
}
}
if(LOG.isDebugEnabled())
LOG.debug("SET time_zone("+timezone+") for connection, succeed!");
return conn;
}
(...)
and on my Spring configuration file:
<bean id="dataSource" class="com.my.package.dbcp.TimezoneEnabledDataSource" destroy-method="close">
(...)
<property name="timezone" value="${database.timezone}" />
(...)
</bean>
I hope this post can help someone in the future. Any question ping me!
You should be able to put the same SQL statements in the initConnectionSqls property of the DBCP configuration element. Just add this to the DBCP configuration element
<property name="initConnectionSqls" value="SET time_zone = '${database.timezone}'"/>
Depending on your version of DBCP, you may have to use connectionInitSqls as the property name. This information is straight from DBCP configuration documentation.
If the data source doesn't have such a property, you can extend it and add that property:
public TimezoneEnabledDataSource extends BasicDataSource {
private String timezone;
//getter and setter for it
#Override
public Connection getConnection() {
Connection c = super.getConnection();
// execute a query: SET time_zone = '-8:00'
return c;
}
}
See here http://www.electrictoolbox.com/mysql-set-timezone-per-connection/ for the query details.
MySQL documentation writes:
Per-connection time zones. Each client that connects has its own time zone setting, given by the session time_zone variable. Initially, the session variable takes its value from the global time_zone variable, but the client can change its own time zone with this statement:
mysql> SET time_zone = timezone;
You can also check if c3p0 doesn't have something built-in.
One of the possible solutions:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="URL" value="${database.url}?serverTimezone=America/Los_Angeles" />
<property name="user" value="${database.username}" />
<property name="password" value="${database.passwd}" />
<property name="connectionCachingEnabled" value="true"/>
<property name="sessionTimeZone" value="GMT-3"/>
</bean>
There is no "sessionTimeZone" member in the BasicDataSource. Use C3P0 which is a "better" connection pool than DBCP, or even better, if you are in a Java EE web server, use it to initialize a JNDI datasource ;)

What's the proper way to handle JDBC connections with Spring and DBCP?

I'm using the Spring MVC to build a thin layer on top of a SQL Server database. When I began testing, it seems that it doesn't handle stress very well :). I'm using Apache Commons DBCP to handle connection pooling and the data source.
When I first attempted ~10-15 simultaneous connections, it used to hang and I'd have to restart the server (for dev I'm using Tomcat, but I'm gonna have to deploy on Weblogic eventually).
These are my Spring bean definitions:
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="url" value="[...]"/>
<property name="username" value="[...]" />
<property name="password" value="[...]" />
</bean>
<bean id="partnerDAO" class="com.hp.gpl.JdbcPartnerDAO">
<constructor-arg ref="dataSource"/>
</bean>
<!-- + other beans -->
And this is how I use them:
// in the DAO
public JdbcPartnerDAO(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
// in the controller
#Autowired
private PartnerDAO partnerDAO;
// in the controller method
Collection<Partner> partners = partnerDAO.getPartners(...);
After reading around a little bit, I found the maxWait, maxActive and maxIdle properties for the BasicDataSource (from GenericObjectPool). Here comes the problem. I'm not sure how I should set them, performance-wise. From what I know, Spring should be managing my connections so I shouldn't have to worry about releasing them.
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="url" value="[...]"/>
<property name="username" value="[...]" />
<property name="password" value="[...]" />
<property name="maxWait" value="30" />
<property name="maxIdle" value="-1" />
<property name="maxActive" value="-1" />
</bean>
First, I set maxWait, so that it wouldn't hang and instead throw an exception when no connection was available from the pool. The exception message was:
Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object
There are some long-running queries, but the exception was thrown regardless of the query complexity.
Then, I set maxActive and maxIdle so that it wouldn't throw the exceptions in the first place. The default values are 8 for maxActive and maxIdle (I don't understand why); if I set them to -1 there are no more exceptions thrown and everything seems to work fine.
Considering that this app should support a large number of concurrent requests is it ok to leave these settings to infinite? Will Spring actually manage my connections, considering the errors I was receiving? Should I switch to C3P0 considering it's kinda dead?
DBCP maxWait parameter should be defined in milliseconds. 30 ms is very low value, consider increasing it to 30000 ms and try again.
As you already found out, the default dbcp connection pool is 8 connections, so if you want to run 9 simultaneous queries one of them will be blocked. I suggest you connect to your database and run exec sp_who2 which will show you what is connected, and active, and whether any queries are being blocked. You can then confirm whether the issue is on the db or in your code.
As long as you are using Spring's JdbcTemplate family of objects your connections will be managed as you expect, and if you want to use a raw DataSource make sure you use DataSourceUtils to obtain a Connection.
One other suggestion - prior to Spring 3, don't ever using JdbcTemplate, stick to SimpleJdbcTemplate, you can still access the same methods using SimpleJdbcTemplate.getJdbcOperations(), but you should find yourself writing much nicer code using generics, and remove the need to ever create JdbcTemplate/NamedParameterJdbcTemplate instances.
Let's change the perspective.
but the exception was thrown
regardless of the query complexity
It could be because the table or the records in the table, which you are querying against has been locked (by some other active transaction) and hence it times out.
Try running the same query from SQLServer Client and if it takes a long time, then you can be sure that it is the table or record lock that is causing this.

Categories

Resources