I am trying to create two database connections using JdbcTemplate in spring MVC. I have two databases on same test server. when I try to connect both at same time the second connection throws error
Named Pipes Provider: Could not open a connection to SQL Server [53]. ; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: Named Pipes Provider: Could not open a connection to SQL Server [53].
Surprisingly when I connect one with test DB server and another with production DB server, both connections work. I don't know what actually causing it.
Spring-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.pr.pct.beans" />
<context:component-scan base-package="com.pr.pct.service" />
<context:component-scan base-package="com.pr.pct.dao" />
<context:component-scan base-package="com.pr.pct.controller" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="dataSourceDR"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="url" value="jdbc:sqlserver://IP:1433;DatabaseName=DB1;"/>
<property name="username" value="sa"/>
<property name="password" value="123123"/>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="url" value="jdbc:sqlserver://IP:1433;Database=DB2;"/>
<property name="username" value="sa"/>
<property name="password" value="123123"/>
</bean>
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:annotation-driven />
</beans>
JdbcTemplate DAO
package com.pr.pct.dao;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
#Component
public class ConnectionDao {
private DataSource dataSource;
private DataSource dataSourceDR;
private JdbcTemplate jdbcTemplate = null;
private JdbcTemplate jdbcTemplateDR = null;
public DataSource getDataSourceDR() {
return dataSourceDR;
}
#Autowired
public void setDataSourceDR(DataSource dataSourceDR) {
jdbcTemplateDR = new JdbcTemplate(dataSourceDR);
}
public JdbcTemplate getJdbcTemplateDR() {
return jdbcTemplateDR;
}
public void setJdbcTemplateDR(JdbcTemplate jdbcTemplateDR) {
this.jdbcTemplateDR = jdbcTemplateDR;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public DataSource getDataSource() {
return dataSource;
}
#Autowired
public void setDataSource(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
}
Stored Procedure Execution
#Autowired
ConnectionDao connectionDao;
then in function
connectionDao.getJdbcTemplateDR().queryForRowSet("USP_PCT_StartCurrentBookings"); -- calling procedure
`
So I implemented jdbc in my java programm. The "old-fashion" way works fluently and i get access to the database.
Now I wanted to refactor my code to Spring JDBC, because it offers more opportunities. But somehow my injection from beans.xml does not work. The dataSource is always null, therefore I can't execute any SQL Querys... because it is always null.
Beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driverClassName}"></property>
<property name="url" value="${db.url}"></property>
</bean>
<bean id="userService" class="beco.webservice.service.impl.UserServiceImpl">
<property name="userDAO" ref="userDAO"></property>
</bean>
<bean id="userDAO" class="beco.webservice.dao.impl.UserDAOImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>database.properties</value>
</list>
</property>
</bean>
</beans>
database.properties
db.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
db.url=jdbc:sqlserver://XX-XXXXXX\\XXXXX;databaseName=BBSupportQA;integratedSecurity=true
UserDataAccessObject.java
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import beco.webservice.dao.UserDAO;
import beco.webservice.model.User;
public class UserDAOImpl implements UserDAO {
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
#Override
public void createUser(User user) {
String SQL = "INSERT INTO dbo.BCO_Person(USER_ID, Email, Nickname) VALUES (?,?,?)";
int update = jdbcTemplate.update(SQL, user.getUserId(), user.getEmail(), user.getNickname());
if(update>0)
System.out.print("User is created...");
}
[...]
}
So I always get a Nullpointer and i debugged it and saw that DataSource / JDBCTemplate is always null.
If i use the old fashion way:
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
conn = DriverManager.getConnection("jdbc:sqlserver:sqlserver://XX-XXXXXX\\XXXXX;databaseName=BBSupportQA;integratedSecurity=true");
System.out.println(LOG_TAG + "Database successfully connected.");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
It works without any problems. What am I doing wrong? Is the url schema in the Spring properties different from the normal jdbc? I have no explanation for this.
I have implemented transactional rollback in the following way. This code worked well when I tried to implement the same on HSql DB and SQL Server. But the same transactional rollback is not working when implemented on MySQL DB. What could be the possible solution for rolling back the transaction in case of MySQL?
Here is my code -
xml file-> implement.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ">
<!-- Initialization for data source -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://(mydb details)"/>
<property name="username" value="(my db username)"/>
<property name="password" value="(my db password)"/>
</bean>
<!-- Initialization for TransactionManager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Definition for studentJDBCTemplate bean -->
<bean id="implementOnlyTransactions" class="Transactions.implementOnlyTransactions">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
</bean>
</beans>
implementOnlyTransactions.java->
package Transactions;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
public class implementOnlyTransactions {
private DataSource dataSource;
private JdbcTemplate jdbcTemplateObject;
private PlatformTransactionManager transactionManager;
public void setDataSource(DataSource dataSource) throws SQLException {
this.dataSource = dataSource;
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
}
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
public void create(Integer id, String name) throws Exception {
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
String SQL1 = "insert into Student (ID,Name) values (?, ?)";
int r = jdbcTemplateObject.update(SQL1, id, name);
System.out.println("Inserted Name = " + name + ", ID = " + id);
if(r>0){
transactionManager.rollback(status);
}
transactionManager.commit(status);
} catch (DataAccessException e) {
System.out.println("Error in creating record, rolling back");
//transactionManager.rollback(status);
throw e;
}
}
}
MainClass.java -->
package Transactions;
import java.sql.SQLException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainClass {
public static void main(String[] args) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("xmlFiles/implement.xml");
implementOnlyTransactions implemt =
(implementOnlyTransactions)context.getBean("implementOnlyTransactions");
try {
implemt.create(36,"bye2");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This is the applicationContext.xml file which i placed in the src/main/resources folder.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- Employee DB data source. -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxPoolSize" value="${jdbc.maxPoolSize}" />
<property name="minPoolSize" value="${jdbc.minPoolSize}" />
<property name="maxStatements" value="${jdbc.maxStatements}" />
<property name="testConnectionOnCheckout" value="${jdbc.testConnection}" />
</bean>
<bean id="Utilities" class="com.pooling.test.Utilities">
</bean>
<context:component-scan base-package="com.pooling.controllers">
</context:component-scan>
This is the jdbc.properties file which i placed in the src/main/resources folder.
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/books
jdbc.username=root
jdbc.password=admin
jdbc.maxPoolSize=50
jdbc.minPoolSize=10
jdbc.maxStatements=10
jdbc.testConnection=true
jdbc.unreturnedConnectionTimeout=240
jdbc.debugUnreturnedConnectionStackTraces=true
This is the Utilities class that contains the logic that i wish to perform
package com.pooling.test;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import com.jolbox.bonecp.BoneCP;
public class Utilities {
private final String CLASS_NAME = "Utilities";
#Autowired
private DataSource datasource;
public String createListofCategories()
{
String METHOD_NAME = "createListofCategories()";
/*//===========================================================================
TransactionDefinition mDefinition = new DefaultTransactionDefinition();
TransactionStatus mStatus = mTransactionManager.getTransaction(mDefinition);
//=========================================================================== */
String listOfCategories = "";
String sequel = "select distinct category_id, key_desc from book_resource_view, keywords_record_table";
sequel = sequel + " where keyword_key=category_id and category_id > 1 ";
sequel = sequel + " order by key_desc";
Connection connection = null;
ResultSet results = null;
Statement state = null;
int categoryID = 0;
String categoryDesc = "";
int numRows = 0;
try
{
connection = datasource.getConnection();
state = connection.createStatement();
results = state.executeQuery(sequel);
results.last();
numRows = results.getRow();
//======================================
results.beforeFirst();
for(int i=0; results.next(); i++){
listOfCategories = listOfCategories + "<td><ul id=\"category_list\">";
for(int j=0; j<16; j++){
categoryID = results.getInt("category_id");
categoryDesc = results.getString("key_desc");
listOfCategories = listOfCategories + "<li>"+categoryDesc+"</li>";
if(!results.next()){
break;
}
}
results.previous();
listOfCategories = listOfCategories + "</ul></td>";
}
listOfCategories = "<tr>"+listOfCategories+"</tr>";
}
catch (SQLException localSQLException)
{
try
{
results.close();
state.close();
connection.close();
}
catch (SQLException localSQLException1)
{
}
}
finally
{
try {
results.close();
state.close();
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return listOfCategories;
}
This is the controller code that i wish to call from the browser.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.pooling.test.ConnectionManager;
import com.pooling.test.Utilities;
#Controller
public class TestController {
#RequestMapping(value="/testing",method=RequestMethod.GET)
public #ResponseBody String getCategories(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Utilities utilities = (Utilities) context.getBean("Utilities");
return utilities.createListofCategories();
}
}
PROBLEM: the problem is that the pool gets initialized properly but when i keep executing the same controller request again and again the connection pool keeps on creating connections until the server gives "too many connections" error
I think the problem lies in the fact that you create a new ApplicationContext everytime the getCategories() method is called.
As #Chrylis already mentioned, you don't need to call context.getBean().
Replace the two lines from ApplicationContext to context.getBean() to #Autowired Utilities utilities. Just like you did with datasource in your Utilities class.
I am new to Spring MVC and JDBCTemplate and badly need some help on this. I've declared the following in applicationContext.xml:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://" />
<property name="username" value="user" />
<property name="password" value="pwd" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
In my DAOImpl class, I've the following code:
#Repository
public class ABCDAOImpl implements ABCDAO
{
private String INSERT_SQL = null;
private JdbcTemplate jdbcTemplate;
#Autowired
public void setDataSource(DataSource dataSource)
{
this.jdbcTemplate = new JdbcTemplate( dataSource );
}
#Override
public boolean insertDataInDataBase(final Object obj)
{
boolean insertSuccessful = false;
INSERT_SQL = "INSERT INTO XXX " +
"(AA, BB, CC, DD, EE, " +
"FF, GG, HH, II) VALUES (?,?,?,?,?,?,?,?,?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator()
{public PreparedStatement createPreparedStatement(Connection connection)
throws SQLException
{
PreparedStatement ps = null;
ps = connection.prepareStatement(INSERT_SQL);
ps.setString(1, xx);
ps.setString(2, xx);
ps.setString(3, xx);
ps.setString(4, xx);
ps.setString(5, xx);
ps.setString(6, xx;
ps.setString(7, xx);
ps.setString(8, xx);
ps.setString(9, xx);
return ps;
}}, keyHolder);
return insertSuccessful;
}
}
Test class:
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class ABCDAOImplTest
{
private Object object = new Object();
private ABCDAOImpl abcDAOImpl;
#Before
public void setup()
{
object.setAllVaribles();
abcDAOImpl = new ABCDAOImpl();
}
#Test
public void testRepositoryInsert()
{
System.out.println(abcDAOImpl.insertDataInDataBase(object));
assertTrue(abcDAOImpl.insertDataInDataBase(object));
}
}
Then I use jdbcTemplate to carry out an insert statement using PreparedStatementCreator.
Now, I am trying to test (without mocking, I am hardcoding the values just to test..) whether this code works or not? When I run this test, it gives me NPE saying jdbcTemplate is null. Is there something wrong with my code or is there something with the way I am testing it? Any help would be greatly appreciated.
Happy New Year :)
PS - I have annotated the Test class with #RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:applicationContext.xml"}) only after comment from #Pradeep. And now I get another exception: "Failed to load ApplicationContext."
The most obvious answer is that your test hasn't called the setDataSource() method or done anything else that would cause the JdbcTemplate to be created. You haven't shown enough code for someone to point out where the problem is, though.
Update: In your test, you say abcDAOImpl = new ABCDAOImpl();, and that's all. How do you expect the JdbcTemplate/DataSource to be injected? It won't happen by magic. Either you have to finish wiring it all up manually, or else let Spring inject the DAO into your test. To do that, just add a field like this:
#Autowired
private ABCDAO abcDao;
Maybe your missing Import of applicationContext.xml file in test-applicationContext.xml file
<import resource="classpath:applicationContext.xml" />