Sunday, March 30, 2014

Configuring Data Sources in Spring Framework

This is the second post in the configuring Spring series. It kickstarts the database centric configurations required when building an application that persist data with Spring framework. This post talks about configuring data sources.

There are various ways to enable the ability to persist data in your application. From using any of the available Implementation of Java Database Connectivity (commonly referred to as JDBC) to going the ORM route via any of the popular ORM frameworks (Hibernate, MyBatis, Eclipse Link etc )

But with any of the above mentioned method, a data source is always a requirement; because...well you need to have a source to the data if you want to persist and/or retrieve data. And in Spring the data source ends up as a Bean that you would configure.

Spring provides several options of configuring the data source. You can have:
  1. Data sources that are provided via JNDI.
  2. Data sources that work with JDBC drive.
  3. Data sources that are from a connection pool.
But before we go ahead to look at configuration proper, it would be useful to quickly define some basic concepts you would encounter when dealing with persistency:



JDBC Driver
The Java Database Connectivity is an API interface that standardized how a Java application talks to a Database server. In other for a Java application to be able to connect to a Database server via JDBC, it would have to do so using a JDBC implementation for the particular database it wants to connect with. This JDBC implementation is often referred to as the Driver. For example if your application needs to work with a MySQL server using JDBC, it would be done via MySQL/JDBC driver which is provided by MySQL. Database vendors makes their respective JDBC driver available. It is worth nothing that the actual connection to the database is established and given out by the JDBC driver as a connection Object.

Connection Pooling.
The process of creating connection object by the JDBC driver is always an expensive procedure. Because of this, it is usually wise to pool together connection objects and have them reused. This removes the overhead of having to create a connection object each time the database needs to be accessed.

DataSource.
DataSource is a connection factory that is part of the JDBC specification. It allows a container or a framework to hide connection pooling and transaction management issues from the application layer. I like to see the DataSource as an implementation that encapsulates over the JDBC functionality of access to a Database. It can also be seen as a bridge that is provided (most times by the application server) that bridges your application and the database it is talking to.

With these definitions out of the way, let us see how you would wire up a bean as a data source. For the proceeding examples, we would use the Data Access Object pattern where we have a class that is dedicated to handling database operations. And to do this, our DAO class would make use of the data source.

For the example I would be using Stereotype annotation together with XML. If you not sure what these means, then read the post on Configuring Beans in Spring Framework.
@Component

class UserDao {

   @Autowired
   private Datasource datasource;

   public void saveUser() {}
   public List<User> readUsers() {}
   public void deleteUser(){}
}

the methods of UserDao uses the datasource to perform its functionality.

Configuring Data Sources via JNDI

In this set up the data source is kept in the JNDI and retrieved and wired up as a bean that can be injected into beans that needs it. This is done via namespaces; a feature that was mentioned in Configuring Beans in Spring Framework which allows you to hide explicit bean definitions by using XML namespaces.

<beans 
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee  
http://www.springframework.org/schema/jee/spring-jee.xsd">


<!-- namespace for finding classes annoted and turning them into beans --> 
<context:component-scan base-package="MySpringApp">
</context:component-scan>  

<!--JEE namespace to retrieve the datasource --> 
<jee:jndi-lookup 
  expected-type="javax.sql.DataSource" 
  id="dataSource" 
  jndi-name="jdbc/DatabaseName">
</jee:jndi-lookup>
<beans>

With the above configuration, a bean of type javax.sql.DataSource with id dataSource is wired up for use.

Configuring Data Source via JDBC

Configuring data sources via JDBC in Spring is basically configuring the data source that is defined through the JDBC driver. In spring you have two classes that you can use for this:
org.springframework.jdbc.datasource.DriverManagerDataSource and org.springframework.jdbc.datasource.SingleConnectionDataSource

DriverManagerDataSource always returns a new connection on each request, while SingleConnectionDataSource maintains one and one connection that is returned on every request. 

Configuring either of this is simple:
<beans xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemalocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context.xsd">

<!-- namespace for finding classes annoted and turning them into beans -->
<context:component-scan base-package="MySpringApp"></context:component-scan>

<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql://localhost/userapp"></property>
    <property name="username" value="sa"></property>
    <property name="password" value=""></property>
</bean>
</beans>
The properties configured are the minimum needed to get a data source working. You need to tell the data source which JDBC driver to use (in the example above we using a hsql JDBC driver). You need to specify the URL to the database, and also the authentication details: username and password. With these four properties set, a JDBC data source is ready to be used.

Configuring Data source from a Connection Pool.

Using just a JDBC data source is the least efficient configuration you can have for a data source as it inherits the overhead of having to create a new connection pool on every request (in the case of DriverManagerDataSource) while SingleConnectionDataSource on the other hand although does not have the overhead of having to recreate a connection on every request (since it keeps a pool of just one and one connection only) the very nature of just having one connection makes it unsuitable for multithreaded environment.

For production purposes, the common practice is to use a robust implementation to get data sources either via JNDI or by making use of libraries that enables database connection pooling. Spring itself does not come with this functionality but a popular project that does is the Jakarta Commons Database Con-

This you can easily integrate into your Spring application.

The DBCP has got various data sources that has ability for pooling. We would look at one of the basic ones. The BasicDataSource. This is similar to configuring the data source from JDBC with an additional functionality of being able to have connection pooled.

Configuring a bean as data source using DBCP's data source would look like:

<beans
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 
xsi:schemalocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context.xsd">

<!-- jee for finding classes annoted and turning them into beans -->
<context:component-scan base-package="MySpringApp"></context:component-scan>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName"value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost/userapp"/>
    <property name="username" value="sa"/>
    <property name="password" value=""/>
    <property name="initialSize" value="5"/>
    <property name="maxActive" value="10"/>
</bean>

</beans>


The first four properties is identical to what we had with JDBC data sources configuration. The two extra properties are used to configure the pooling behaviour. In this case, initial pooling size is set to 5 while maximum amount of active connection object, maxActive, is limited to 10. For more available properties that can be used to configure the DCBP data source, check the DCBP configuration page

So now that you have your data source configured using any of the above methods, it can thus be used in the DAO class to perform database related operations.


No comments: