This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
The UsersDAOImpl class is supposed to add a new user when I run the file as a JUnit test, but I keep getting a NullPointerException when I call sessionFactory.getCurrentSession() and I don't know why.
The session factory is put in the beans.xml.
The credentials to the database were removed for obvious reasons.
[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" 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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
<!-- enable autowiring -->
<context:component-scan base-package="src"></context:component-scan>
<!-- enable #Transactional -->
<tx:annotation-driven />
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="username" value="{Master}"></property>
<property name="password" value="{password}"></property>
<property name="url" value="{url}"></property>
</bean>
<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"></property>
<property name="packagesToScan" value="src"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory">
</property>
</bean>
<bean id="usersDAO" class="dao.UsersDAOImpl">
<property name="sessionFactory" ref="mySessionFactory"> </property>
</bean>
</beans>
[UsersDAOImpl.java]
package dao;
import static org.junit.Assert.*;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import customExceptions.*;
import util.Debug;
import util.HibernateUtil;
import domain.Users;
#Transactional
public class UsersDAOImpl implements UsersDAO {
#Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionfactory) {
this.sessionFactory = sessionfactory;
}
#Test
public void testPush() {
try {
push(new Users("username6", "email#gmail.com", "password", "firstName", "lastName", false));
} catch (UserNameTakenException e) {
e.printStackTrace();
fail();
} catch (InvalidNameException e) {
e.printStackTrace();
fail();
}
}
/**
* Adds a new user to the database
*
* #param newUser
* The user to be added
* #throws UserNameTakenException
* In the case a username is taken
* #throws InvalidNameException
* If a field is left blank, but front end should prevent that
*/
#Override
#Transactional(propagation = Propagation.REQUIRED)
public void push(Users newUser) throws UserNameTakenException, InvalidNameException {
// For debugging purposes:
Debug.printMessage(this.getClass(), "push()", "invoked");
// Check if there are any empty Strings
if (newUser.getUsername().isEmpty() || newUser.getPassword().isEmpty() || newUser.getFirstName().isEmpty()
|| newUser.getLastName().isEmpty()) {
throw new InvalidNameException("There is an empty String");
}
// Get the session
//THIS IS WHERE I GET THE EXCEPTION
Session sess = sessionFactory.getCurrentSession();
// Check to see if the username is taken
Users users = getUserByName(newUser.getUsername());
// If the list is not empty, a user with the name was found
if (users != null) {
sess.close();
throw new UserNameTakenException("The username was found in the database");
} else {
// Otherwise, add the new user
// Debug
Debug.printMessage(this.getClass(), "push()", "username available.");
Debug.printErrorMessage(this.getClass(), "push()", "saving " + newUser.getUsername());
sess.save(newUser);
sess.close();
}
}
/**
* Updates the User's password in the database
*
* #param user
* The user to change
* #param newVal
* The new password
*/
#Override
public void updatePassword(Users user, String newVal) {
Debug.printMessage(this.getClass(), "updatePassword()", "invoked");
Session sess = HibernateUtil.getSession();
Transaction trans = sess.beginTransaction();
user.setPassword(newVal);
sess.update(user);
trans.commit();
sess.close();
}
/**
* Updates the User's first name in the database
*
* #param user
* The user to change
* #param newVal
* The new first name
*/
#Override
public void updateFirstName(Users user, String newVal) {
// For debugging purposes:
Debug.printMessage(this.getClass(), "updateFirstName()", "invoked");
Session sess = HibernateUtil.getSession();
Transaction trans = sess.beginTransaction();
user.setFirstName(newVal);
sess.update(user);
trans.commit();
sess.close();
}
/**
* Updates the User's last name in the database
*
* #param user
* The user to change
* #param newVal
* The new last name
*/
#Override
public void updateLastName(Users user, String newVal) {
// For debugging purposes:
Debug.printMessage(this.getClass(), "updateLastName()", "invoked");
Session sess = HibernateUtil.getSession();
Transaction trans = sess.beginTransaction();
user.setLastName(newVal);
sess.update(user);
trans.commit();
sess.close();
}
/**
* Returns the user with the given username
*
* #param username
* The username to find
*/
#Override
public Users getUserByName(String username) {
// For debugging purposes:
Debug.printMessage(this.getClass(), "getUserByName()", "invoked");
Session sess = HibernateUtil.getSession();
Users user = (Users) sess.get(Users.class, username);
sess.close();
return user;
}
/**
* Returns a list of all users from A_USERS
*/
#Override
public List<Users> getAllUsers() {
// For debugging purposes:
Debug.printMessage(this.getClass(), "getAllUsers()", "invoked");
Session sess = HibernateUtil.getSession();
Query query = sess.getNamedQuery("getAllUsers");
List<Users> users = query.list();
sess.close();
return users;
}
}
Also, I apologize if this is formatted incorrectly. This is my first time posting a question.
The Stack Trace
java.lang.NullPointerException
at dao.UsersDAOImpl.push(UsersDAOImpl.java:65)
at dao.UsersDAOImpl.testPush(UsersDAOImpl.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
null
The sessionFactory field is null.
As for why, I can only guess. You're both auto-wiring the sessionFactory field but also injecting it as a property via its configuration in the applicationContext.xml. Do one or the other, not both, and see what happens.
A session is opened whenever getCurrentSession() is called for the first time and closed when the transaction ends. This creates a brand new session if one does not exist or uses an existing one if one already exists. It automatically configured with both auto-flush and auto-close attributes as true means Session will be automatically flushed and closed.
We can use getCurrentSession() method when our transaction runs long time. To use this method we need to configure one property in hibernate.cfg.xml file. The property is
<propertyname="hibernate.current_session_context_class">thread</property>
Values for the current_session_context_class will be,
thread(local transaction)
managed jta(global transaction)
thread - session bound to a thread, for single thread execution if you call a getCurrentSession() then it will return you a same session object.
managed - this provided for managing session from some external entity, something like intercepter. maintaining session in a ThreadLocal same as a "thread" type, but having a different methods like bind(), unbind(), hasbind() to be used by external entity to maintain session in a context.
jta - session will be bound to a transaction, as we says a transaction then we need application server for using this context class.
public org.hibernate.classic.Session getCurrentSession() throws HibernateException {
if ( currentSessionContext == null ) {
throw new HibernateException( "No CurrentSessionContext configured!" );
}
return currentSessionContext.currentSession(); }
Or Try This
Session session = sessionFactory.getCurrentSession();
if (session.isOpen()) {
session.close();
}
TransactionSynchronizationManager.unbindResource(sessionFactory);
TransactionSynchronizationManager.clearSynchronization();
Related
I have a class in java with two more methods similar to the one here.
public Object noOfEmployees() {
List<Employee> emp = null;
String u = user.getUserName();
if ("user1".equals(u)) {
Query query = getHibernateTemplate().getSessionFactory().openSession()
.createSQLQuery("select * from employee where job='System Analyst'")
.addEntity(EMPLOYEE.class);
emp = query.list();
getHibernateTemplate().getSessionFactory().openSession().close();
} else if ("user2".equals(u)) {
Query query = getHibernateTemplate().getSessionFactory().openSession()
.createSQLQuery("select * from employee where job='DBA'")
.addEntity(EMPLOYEE.class);
emp = query.list();
getHibernateTemplate().getSessionFactory().openSession().close();
}
return emp.size();
}
When I ran the application, this is how I got the output:
Logged in as 'user2'
Hibernate: select * from employee where job='DBA'
Hibernate: select * from employee where job='DBA' and rank='2'
Hibernate: select * from employee where present='yes'
Logged in as 'user1'
Hibernate: select * from employee where job='System Analyst'
Hibernate: select * from employee where job='System Analyst' and rank='3'
Hibernate: select * from employee where present='yes'
Again, logged in as 'user2', first two methods get executed.
Hibernate: select * from employee where job='DBA'
Hibernate: select * from employee where job='DBA' and rank='2'
When I logged in as any user, this time even the first method did not get executed.
I have noticed that the code gets stuck when query.list() is encountered. I know that using hibernateTemplate is not recommended but the entire application is written using it. I have only started to learn about spring and hibernate. I will start making changes once I get comfortable with those.
Any suggestions related to the performance of query.list() and ways to improve the code are more than welcome.
Thank you!
Your code is flawed on many levels... For starters you shouldn't be using HibernateTemplate unless you are in a very old application, else use a plain SessionFactory. See http://docs.spring.io/spring/docs/current/spring-framework-reference/html/orm.html#orm-hibernate-straight for more information.
Second when using Spring use Spring to manage your resources, i.e. Session in this case, or if you want to do it yourself at least manage it properly!.
So in short use a SessionFactory and use getCurrentSession instead of openSession. And use a proper query.
#Autowired
private SessionFactory sf;
#Transactional
public Long noOfEmployees() {
final String query = "select count(*) from employee where job=:job";
Query q = sf.getCurrentSession().createSQLQuery(query);
if ("user1".equals(u)) {
q.setParameter("job", "System Analyst");
} else if ("user2".equals(u) ) {
q.setParameter("job", "DBA");
}
return (Long) query.uniqueResult();
}
The #Transactional will make spring manage the resources, assuming you have <tx:annotation-driven /> in your context and properly added the HibernateTransactionManager.
The problem, obviously, with this code
Query query = getHibernateTemplate().getSessionFactory().openSession().
...
getHibernateTemplate().getSessionFactory().openSession().close();
With this getHibernateTemplate().getSessionFactory().openSession().close() you get a new session and close it!
You should use HQL
Query query = session.createQuery("from Employee where job='System Analyst'");
List<Employee> emp = query.list();
And the way you use Hibernate Template is entirely incorrect.
Refer how to use it
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/classic-spring.html
An example
public class ProductDaoImpl {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public Collection loadProductsByCategory(final String category) throws DataAccessException {
return this.hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session) {
Criteria criteria = session.createCriteria(Product.class);
criteria.add(Expression.eq("category", category));
criteria.setMaxResults(6);
return criteria.list();
}
};
}
}
I have tried to change my flawed-on-many-levels code to some extent. All thanks to #M.Deinum and #v.ladynev for their swift responses.
Given below are only snippets where changes to move from HibernateTemplate to SessionFactory are mentioned:
//IndexService
#Transactional
public class IndexService {
User user;
SessionFactory sf;
public IndexService(User user, SessionFactory sf) {
this.user = user;
this.sf = sf;
}
//This method is used to get the number of employees based on users.
public Object noOfEmployees() {
String u = user.getUserName();
final String query = "select count(*) from employee where job=:job";
Query q = sf.getCurrentSession().createSQLQuery(query);
if ("user1".equals(u)) {
q.setParameter("job", "System Analyst");
} else if ("user2".equals(u) ) {
q.setParameter("job", "DBA");
}
return q.uniqueResult();
}
--------------------------------------------------------------------------------------
//Index
#Controller
#Transactional
public class Index {
#Autowired
User user;
#Autowired
SessionFactory sf;
#RequestMapping("/index")
public ModelAndView getIndex() {
System.out.println("user.getUserName() In Index = " + user.getUserName());
ModelAndView modelAndView = new ModelAndView("index");
IndexService indexService = new IndexService(user, sf);
modelAndView.addObject("noOfEmployees", indexService.noOfEmployees());
return modelAndView;
}
}
--------------------------------------------------------------------------------------
//spring-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="basicDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url"
value="jdbc:mysql://localhost/database_name"></property>
<property name="username" value="user"></property>
<property name="password" value="password"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="basicDataSource"></property>
<property name="mappingResources" value="myBeans.hbm.xml" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
Issues that I came across while changing from HibernateTemplate to SessionFactory:
1.NullPointerException for SessionFactory
In index class,
#Autowired
SessionFactory sf;
and passed it as an argument.
IndexService indexService = new IndexService(user, sf);
2.No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
I put #Transactional above Index also. It is the controller in my application.
Thank you once again #M.Deinum and #v.ladynev!
This same question has been asked so many times on SO, but please read
my question fully before making it duplicates.
I don't want to use Annotation based Transaction Management, so my problem is different then questions asked here.
MY XML Declaration
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:/comp::/env/jdbc/DS</value>
</property>
</bean>
<!-- Create SessionFactory , one instance per application only -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!-- Just for Testing Purpose -->
<property name="mappingResources">
<list>
<value>com/mycompany/hbmapping/platform/support/Currency.hbm.xml</value>
</list>
</property>
<!-- <property name="mappingDirectoryLocations"> <value>/WEB-INF/classes/com/mycompany/hbmapping</value>
</property> -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<!-- Cache related properties -->
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory
</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">/ehcache.xml</prop>
<prop key="hibernate.cache.use_structured_entries">true</prop>
</props>
</property>
</bean>
<bean id="hibernateTxManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
Following DAO Declaration as a bean
<bean id="currency" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>
com.mycompany.dao.platform.support.CurrencyDao
</value>
</property>
<property name="target">
<ref bean="currencyTarget" />
</property>
</bean>
<bean id="currencyTarget"
class="com.mycompany.dao.platform.support.CurrencyDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
My TX Advice
<tx:advice id="txAdvice" transaction-manager="hibernateTxManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"></tx:method>
<tx:method name="update*" propagation="REQUIRED"></tx:method>
<tx:method name="delete*" propagation="REQUIRED"></tx:method>
</tx:attributes>
</tx:advice>
AOP Configuration
<aop:config>
<aop:pointcut
expression="within(com.mycompany.dao.platform.support.CurrencyDao)"
id="currencyPointCut" />
</aop:config>
<!-- applying advice on joint point -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut-ref="currencyPointCut" />
</aop:config>
MY DAO
public class CurrencyDaoImpl extends BaseBusinessDao implements CurrencyDao {
/**
*
*/
public CurrencyDaoImpl() {
}
public Serializable save(CurrencyModel currency) {
Session session = getCurrentSession();
Serializable id = session.save(currency);
return id;
}
public void update(CurrencyModel currency) {
Session session = getCurrentSession();
session.update(currency);
}
public void delete(Serializable id) {
Session session = getCurrentSession();
session.delete(id);
}
}
My Model
public class CurrencyModel extends BaseModel {
/**
*
*/
private static final long serialVersionUID = 6543232156842168468L;
private String currencyId;
/**
* name of the currency.
*/
private String currency;
private String trId;
/**
*
*/
public CurrencyModel() {
}
public String getCurrencyId() {
return currencyId;
}
public void setCurrencyId(String currencyId) {
this.currencyId = currencyId;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public String getTrId() {
return trId;
}
public void setTrId(String trId) {
this.trId = trId;
}
#Override
public int hashCode() {
return currency.hashCode();
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!this.getClass().equals(obj.getClass())) {
return false;
}
String anotherCurrency = ((CurrencyModel) obj).getCurrency();
if (getCurrency().equals(anotherCurrency)) {
return true;
}
return false;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Currency for this instance is " + getCurrency());
return sb.toString();
}
}
My Hibernate Mappings file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.mycompany.model.platform.support">
<class name="CurrencyModel" table="tblcurrency">
<id name="currencyId" column="currencyId">
<generator class="uuid"></generator>
</id>
<version name="version" column="version" type="long"></version>
<property name="rowStatus" column="rowStatus" not-null="true"></property>
<property name="currency" column="currency" not-null="true"></property>
<!-- this property needs to be replaces with transaction management root
object UserTransactionModel
-->
<property name="trId" not-null="true"></property>
</class>
</hibernate-mapping>
When i am running this application using programmatically by following code,
SimpleNamingContextBuilder scb = new SimpleNamingContextBuilder();
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://url:3306/db");
ds.setUsername("dtsnuser");
ds.setPassword("0okmnji9");
ds.setValidationQuery("select 1");
ds.setInitialSize(10);
ds.setMaxActive(20);
ds.setMaxIdle(10);
ds.setMaxWait(-1);
scb.bind("java:/comp::/env/jdbc/DS", ds);
scb.activate();
// setup bean factory
dlBeanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader xbl = new XmlBeanDefinitionReader(dlBeanFactory);
xbl.loadBeanDefinitions(new FileSystemResource(
"src/main/webapp/WEB-INF/app-config/applicationContext.xml"));
currencyDao = (CurrencyDaoImpl) dlBeanFactory.getBean("currencyTarget");
currencyModel = new CurrencyModel();
currencyModel.setCurrency("INR");
id = UUID.randomUUID().toString();
currencyModel.setCurrencyId(id);
String trId = UUID.randomUUID().toString();
currencyModel.setTrId(trId);
it throws following exception
org.hibernate.HibernateException: Could not obtain
transaction-synchronized Session for current thread at
org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)
at
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:990)
at
com.mycompany.dao.base.BaseBusinessDao.getCurrentSession(BaseBusinessDao.java:41)
at
com.mycompany.dao.platform.support.CurrencyDaoImpl.delete(CurrencyDaoImpl.java:45)
at
com.mycompany.dao.platform.support.TestCurrencyDaoImpl.testDelete(TestCurrencyDaoImpl.java:130)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606) at
junit.framework.TestCase.runTest(TestCase.java:154) at
junit.framework.TestCase.runBare(TestCase.java:127) at
junit.framework.TestResult$1.protect(TestResult.java:106) at
junit.framework.TestResult.runProtected(TestResult.java:124) at
junit.framework.TestResult.run(TestResult.java:109) at
junit.framework.TestCase.run(TestCase.java:118) at
junit.framework.TestSuite.runTest(TestSuite.java:208) at
junit.framework.TestSuite.run(TestSuite.java:203) at
org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:131)
at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
My DataSource is located at remote server.
What i am doing wrong ?
Is advice is not applied properly ? Can i figure out that advice is applied properly ?
Please , don't advice me to use annotation based approach, i can't go with it for the moment.
Thanks
Mihir
In web apps this is the way to handle the transaction with aop,
import javax.persistence.EntityManager;
public final class JPAUtil {
private static final ThreadLocal<EntityManager> currentEntityManager= new ThreadLocal<EntityManager>();
private EntityManagerFactory entityManagerFactory;
/**
* Get the EntityManager for specified persistence unit for this thread.
*/
public EntityManager em(String persistenceName) {
EntityManager entityManager = null;
if(entityManagerFactory != null) {
EntityManager entityManager = entityManagerFactory.createEntityManager();
bindForCurrentThread(entityManager);
}
return entityManager;
}
/**
* Get the default EntityManager for this thread.
*/
public static final EntityManager em() {
EntityManager em = currentEntityManager.get();
if (jpaPlugin == null || em == null) {
return em(END_USER);
}
return em;
}
/**
* Bind an EntityManager to the current thread.
*/
public static final void bindForCurrentThread(EntityManager em) {
currentEntityManager.set(em);
}
public static final void closeEM() {
Logger.debug("Closing entity manager...");
EntityManager em = currentEntityManager.get();
if (em != null && em.isOpen()) {
em.close();
}
Logger.debug("Entity manager closed successfully.");
bindForCurrentThread(null);
}
public static final void beginTransaction() {
em().getTransaction().begin();
}
public static final void commitTransaction() {
em().getTransaction().commit();
}
}
#Aspect
public class DBAspects {
private static final String READONLY_CONNECTION = "org.hibernate.readOnly";
/**
* Injecting entity manager before calling the em() method of JPABaseDAO.
* #param joinPoint
* #param bd
*/
#Before("call(* com.xo.web.models.dao.JPABaseDAO+.em(..)) && this(bd)")
public void injectEntityManager(JoinPoint joinPoint, JPABaseDAO bd) {
bd.setEntityManager(JPAUtil.em());
//Logger.info("Injected enitymanager to : " + joinPoint.getSignature().getName());
}
/**
* Pointcuts to get the XODBTransaction methods
*/
#Pointcut("execution(#com.xo.web.persistence.XODBTransaction * *(..)) || call(public play.mvc.Result com.xo.web.controllers.*.*(..))")
public void getTransactionMethods(){
}
/**
* Pointcuts to get the XODBTransaction methods
*/
#Pointcut("execution(#com.xo.web.persistence.XODBReadOnly * *(..))")
public void getReadOnlyTransactionMethods(){
}
/**
* Processing the transactions based on the XODBTransaction annotation.
* #param joinPoint
* #return
* #throws Throwable
*/
#Around("getTransactionMethods()")
public Object handleTransaction(ProceedingJoinPoint joinPoint) {
Object resultObject = null;
EntityManager entityManager = JPAUtil.em();
try{
if(entityManager != null) {
javax.persistence.EntityTransaction transaction = entityManager.getTransaction();
try{
final String callerName = joinPoint.getSignature().getName();
if(transaction != null && !transaction.isActive()) {
transaction.begin();
Logger.info("Transaction started for : " + callerName);
}
resultObject = joinPoint.proceed();
if(transaction != null && transaction.isActive()) {
transaction.commit();
Logger.info("Transaction ended for : " + callerName);
}
}catch(Throwable th) {
if(transaction != null && transaction.isActive()) {
transaction.rollback();
}
Logger.info("Error while performing CUD operation...", th);
}
}
} catch(Throwable th) {
Logger.info("Error occurred while processing the request.", th);
} finally {
JPAUtil.closeEM();
}
Signature sig = joinPoint.getSignature();
if (sig instanceof MethodSignature) {
Method method = ((MethodSignature) sig).getMethod();
if(method.getReturnType() == Result.class) {
Context.current().session().clear();
}
}
return resultObject;
}
}
Hopes this gives an idea.
Hy guys,
I want to run a spring batch job and then make some test on the data that result, but I need to use the hibernate lazy loading. So I need an opened transaction to keep the session alive.
But I get this exception : IllegalTransactionStateException : Pre-bound JDBC Connection found!
I could write methods to get directly the associated objects I want to test, but I don't want to write method only for test and to loose hibernate's advantages.
Is there a way to do this ? I've try to set the validateStateTransaction to false in the jobRepositoy but it doesn"t work (in fact it only work with a in memory meta data repository like MapJobRepository).
I'm searching for a couple of days but nothing that works.
Could you help me please ? Thanks
My code here :
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="databaseType">
<value>POSTGRES</value>
</property>
<property name="dataSource" ref="databasePool" />
<property name="transactionManager" ref="transactionManager" />
<property name="isolationLevelForCreate" value="ISOLATION_DEFAULT" />
<property name="tablePrefix" value="#{ schema }.BATCH_" />
<property name="validateTransactionState" value="false" />
</bean>
and
#Test
#Transactional
public void test() {
/*
* ===================RUN JOB======================
*/
JobParameters jobParameters = new JobParametersBuilder();
int returnCode = runJob("job_name", jobParameters);
assertEquals("returnCode must be 0.", 0, returnCode );
/*
* ===============END JOB=============================
*/
/*
* ===============TEST ON DATA==========================
*/
ObjectToTest obj = objectDao.findById("1");
assertNotNull( obj.getSomeCollection().get(1));
/*
* =================END TEST==================
*/
}
Here is the exception :
org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC Connection found! JpaTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single JpaTransactionManager for all transactions on a single DataSource, no matter whether JPA or JDBC access.
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:359)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:438)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:261)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy113.getLastJobExecution(Unknown Source)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:98)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:362)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:590)
at fr.insee.harmonica.commun.batch.CommandLineJobRunnerTest.runJob(CommandLineJobRunnerTest.java:143)
at fr.insee.harmonica.commun.batch.CommandLineJobRunnerTest.execute(CommandLineJobRunnerTest.java:420)
I've try to put the test part in another method that would be anotated with #Transactional, but then I get a LazyInitializationException...
EDIT :
I use the org.springframework.orm.jpa.JpaTransactionManager implementation for transaction Manager.
Here is my spring configuration :
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
I have searched the way to manually open transaction but I didn't find it yet
Ok I found a solution (without any help finally).
To do this you have to open manually a transaction AFTER your job ends.
You can do something like that :
#Autowired
protected PlatformTransactionManager transactionManager;
#Test
public void test() {
/*
* ===================RUN JOB======================
*/
JobParameters jobParameters = new JobParametersBuilder();
int returnCode = runJob("job_name", jobParameters);
assertEquals("returnCode must be 0.", 0, returnCode );
/*
* ===============END JOB=============================
*/
/*
* ===============TEST ON DATA==========================
*/
(new TransactionTemplate(transactionManager)).execute(new TransactionCallback() {
#Override
public Object doInTransaction(TransactionStatus status) {
ObjectToTest obj = objectDao.findById("1");
assertNotNull( obj.getSomeCollection().get(1));
}
});
/*
* =================END TEST==================
*/
}
I'm newbie to spring framework.I have integrated spring + hibernate to create RESTFUI API web service.
public interface IGenericDao {
long persists(T clazz) throws ResourceFailureException;
List select(T clazz)throws ResourceFailureException;
}
#Repository(value="genericDao")
public class GenericDao implements IGenericDao {
#Autowired
SessionFactory sessionFactory;
#Override
public long persists(T clazz) throws ResourceFailureException {
long generatedID;
generatedID = (Long) getCurrentSession().save(clazz);
getCurrentSession().getTransaction().commit();
return generatedID;
}
#Override
public List select(T clazz) throws ResourceFailureException {
String queryStr = " FROM "+clazz.getClass().getName()+" as table WHERE (table.isDelete is null OR"
+ " table.isDelete = false) ";
return this.select(queryStr);
}
protected final Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}
//Implement GenericDAO class
#Repository(value="roleCapabilityDao")
public class RoleCapabilityDAO extends GenericDao{
public final void persistRole(final Role role) throws ResourceFailureException {
persists(role);
}
public final List getRoles(final String whereString)
throws ResourceFailureException {
String queryStr = "FROM Role " + whereString;
return select(queryStr);
}
public final Role getRoleById(final int roleId) throws ResourceFailureException {
String whereString = "WHERE id=" + roleId;
List roles = getRoles(whereString);
if (roles != null && !roles.isEmpty()) {
return roles.get(0);
}
return null;
}
}
//Servlet-context class.
#Transactional
public class HibernateUtility {
private static Logger logger =Logger.getLogger(HibernateUtility.class.getName());
public HibernateUtility() {
}
#Autowired(required=true)
RoleCapabilityDAO roleCapabilityDao;
#Autowired(required=true)
UserDAO userDao;
public void createDefaultUser(final ServletContext context) {
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, context);
Users user = new Users();
Role role = new Role();
.....
try {
role = roleCapabilityDao.getRoleByName("SystemAdmin");
}catch (ResourceFailureException re) {
logger.error("Resource not found" +re.getMessage());
}
}
applicationContext.xml
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:annotation-config />
<context:component-scan base-package="com.base" use-default-filters="false"/>
<bean id="propertyConfigurer"
.....
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}">
<property name="testOnBorrow" value="true"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<servlet>
<servlet-name>HibernateUtility</servlet-name>
<servlet-class>com.base.hibernate.HibernateUtilityServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
//RESTFUL API calls
#Path("/roles")
#Service
#Transactional
public class RoleCapabilityResource {
public RoleCapabilityResource(){
super();
}
#Autowired
UserDAO userDao;
#Autowired
RoleCapabilityDAO roleCapabilityDao;
private static Logger roleLogger=Logger.getLogger(RoleCapabilityResource.class.getName());
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/getAllRoles")
#Loggable(value = LogLevel.DEBUG)
#CapabilityCode(value = "C_User_R")
public Response getAllRoles(#Context final HttpServletRequest request) {
HttpSession session = request.getSession();
try {
String loggedUser = session.getAttribute("userName").toString();
Users user = userDao.getCurrentUser(loggedUser.trim());
if(user == null){
return Response.status(Response.Status.BAD_REQUEST).type("text/plain").entity("Current User not found").build();
}
List<Role> roleList = roleCapabilityDao.getValidRolesForUserRole(user.getRole().getName(), false);
JSONObject allRolesJson = getRoleJSON(roleList);
return Response.status(Response.Status.OK).type(MediaType.APPLICATION_JSON).entity(allRolesJson).build();
} catch (ResourceFailureException re) {
roleLogger.error("Error in resource"+re.getMessage());
return Response.status(Response.Status.BAD_REQUEST).type("text/plain").entity(re.toString()).build();
}
}
}
//HibernateUtilizyServlet
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* Hibernate Utility Servlet is invoked only once during JBoss Startup.
*/
#Service
#Transactional
public class HibernateUtilityServlet extends HttpServlet {
/**
* Default serial Version ID.
*/
private static final long serialVersionUID = 1L;
#Override
public void init(ServletConfig config) {
try {
super.init(config);
ServletContext context = getServletContext();
HibernateUtility hibernateUtil = new HibernateUtility();
hibernateUtil.createDefaultUser(context);
} catch (ServletException e) {
e.printStackTrace();
}
}
}
If i run the application it throws below error message
StandardWrapper.Throwable: org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63) [:3.1.0.RELEASE]
at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:685) [:3.6.0.Final]
at com.base.dao.GenericDao.getCurrentSession(GenericDao.java:186) [:]
at com.base.dao.GenericDao.select(GenericDao.java:80) [:]
at com.base.dao.RoleCapabilityDAO.getRoles(RoleCapabilityDAO.java:29) [:]
at com.base.dao.RoleCapabilityDAO.getRoleByName(RoleCapabilityDAO.java:40) [:]
at com.base.hibernate.HibernateUtility.createDefaultUser(HibernateUtility.java:180) [:]
at com.base.hibernate.HibernateUtilityServlet.init(HibernateUtilityServlet.java:41) [:]
I have tried some links as mentioned below,
1.Spring MVC + Hibernate: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here.
2.I am receiving HibernateException "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here"
but I have not resolved yet.The only difference is here I didn't use #controller annotation.
How to resolve this Error?
How to set sessions handle by spring?
HibernateUtilityServlet is no Spring Bean! It is just some simple Http Servlet created by your Servlet container (not by Spring).
Therefore
your Spring annotations at HibernateUtilityServlet are ignored (they are only taken in account if your Object is an Spring Bean (created by Spring))
you can not inject something in HibernateUtilityServlet
Futuremore: when you create an instance with new (like you did HibernateUtility hibernateUtil = new HibernateUtility();), then this Object will be no Spring Bean. Therefore
(you already know it):
your Spring annotations at this class are ignored
you can not inject something in this object
I don't really know what you want do do with this HibernateUtilityServlet, but it looks like you try to setup the database when the application starts. -- A Much more easyer way would be using the spring default functionality for this:
#Component
public class OnStartupAction implements ApplicationListener<ContextStartedEvent> {
#Override
public void onApplicationEvent(final ContextStartedEvent event) {
// do whatever you need here
}
}
More details in this answer of mine.
How can I do this in the same transactional session?
alter session set nls_date_format = 'yyyy/mm/dd hh24:mi:ss'
There are some procedures and insertes that I need to execute this before them.
I've tried to make another method, in the same one, but it still doesn't work.
I have MyBatis integrated with Spring. I don't know if it makes any difference.
Can anyone help me?
Thanks.
SOLUTION:
I'v managed this to work by changing the way Spring and MyBatis integrates through SqlSession.
Here are two possible solutions.
Extend SqlSessionFactory
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
import org.apache.log4j.Logger;
public class CustomSqlSessionFactory extends DefaultSqlSessionFactory
{
private static Logger msLogger = Logger.getLogger(CustomSqlSessionFactory.class);
public CustomSqlSessionFactory(Configuration configuration)
{
super(configuration);
}
#Override
public SqlSession openSession()
{
SqlSession session = super.openSession();
alterSession(session);
return session;
}
protected void alterSession(SqlSession session)
{
try
{
Statement statement = session.getConnection().createStatement();
statement.addBatch("alter session set nls_date_format = 'yyyy/mm/dd hh24:mi:ss'");
statement.addBatch("ALTER SESSION SET NLS_COMP = LINGUISTIC");
statement.addBatch("ALTER SESSION SET NLS_SORT = XTURKISH_AI");
statement.executeBatch();
msLogger.debug("Altered newly created session parameters.");
statement.close();
}
catch (SQLException e)
{
msLogger.error("Alter session failed!", e);
}
}
#Override
public SqlSession openSession(boolean autoCommit)
{
SqlSession session = super.openSession(autoCommit);
alterSession(session);
return session;
}
#Override
public SqlSession openSession(Connection connection)
{
SqlSession session = super.openSession(connection);
alterSession(session);
return session;
}
#Override
public SqlSession openSession(ExecutorType execType)
{
SqlSession session = super.openSession(execType);
alterSession(session);
return session;
}
#Override
public SqlSession openSession(ExecutorType execType, boolean autoCommit)
{
SqlSession session = super.openSession(execType, autoCommit);
alterSession(session);
return session;
}
#Override
public SqlSession openSession(ExecutorType execType, Connection connection)
{
SqlSession session = super.openSession(execType, connection);
alterSession(session);
return session;
}
#Override
public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level)
{
SqlSession session = super.openSession(execType, level);
alterSession(session);
return session;
}
#Override
public SqlSession openSession(TransactionIsolationLevel level)
{
SqlSession session = super.openSession(level);
alterSession(session);
return session;
}
}
If you are using spring also create a CustomSqlSessionFactoryBuilder
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class CustomSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder
{
#Override
public SqlSessionFactory build(Configuration config)
{
return new CustomSqlSessionFactory(config);
}
}
and attach CustomSqlSessionFactoryBuilder by modifying the SqlSessionFactoryBean configuration
<bean id="mySqlSessionFactoryBuilder" class="your.package.CustomSqlSessionFactoryBuilder" />
<bean id="mySessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="sqlSessionFactoryBuilder" ref="mySqlSessionFactoryBuilder" />
</bean>
Session will be altered on each borrow operation. However, if you are using pooled connection, this approach will degrade the execution performance. Hence on every checkout of the connection from the pool, openSession will be called.
If you are using a pooled data source then handling session alter operations on data source level will be much faster. Second solution modifies C3P0 pooled data source for altering session.
Modify Pooled Data Source (C3P0 and Spring)
Create a connection customizer class [1]
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.log4j.Logger;
import com.mchange.v2.c3p0.AbstractConnectionCustomizer;
public class ConnectionCustomizer extends AbstractConnectionCustomizer
{
private static Logger msLogger = Logger.getLogger(ConnectionCustomizer.class);
public void onAcquire(Connection c, String pdsIdt)
{
try
{
Statement statement = c.createStatement();
statement.addBatch("alter session set nls_date_format = 'yyyy/mm/dd hh24:mi:ss'");
statement.addBatch("ALTER SESSION SET NLS_COMP = LINGUISTIC");
statement.addBatch("ALTER SESSION SET NLS_SORT = XTURKISH_AI");
statement.executeBatch();
msLogger.debug("Altered newly created session parameters.");
statement.close();
}
catch (SQLException e)
{
msLogger.error("Alter session failed!", e);
}
}
}
Modify data source configuration bean and add created class as connectionCustomizerClassName
<!--
driverClass : Driver class that will be used to connect to database.
jdbcUrl : jdbc url defining the database connection string.
user : username of the database user.
password : password of the database user.
acquireIncrement : how many connections will be created at a time when there will be a shortage of connections.
idleConnectionTestPeriod : after how much delay a connection will be closed if it is no longer in use.
maxPoolSize : Max number of connections that can be created.
maxStatements : Max number of SQL statements to be executed on a connection.
minPoolSize : Minimum number of connections to be created.
connectionCustomizerClassName : Custom connection customizer to enable session alterations and jobs on acquiring/closing - checking in/out physical connections
-->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
<property name="jdbcUrl" value="${app.jdbc.url}" />
<property name="user" value="${app.jdbc.username}" />
<property name="password" value="${app.jdbc.password}" />
<property name="acquireIncrement" value="3" />
<property name="maxPoolSize" value="50" />
<property name="maxStatements" value="50" />
<property name="minPoolSize" value="5" />
<property name="idleConnectionTestPeriod" value="60" />
<property name="preferredTestQuery" value="SELECT 1 FROM DUAL" />
<property name="testConnectionOnCheckout" value="true" />
<property name="connectionCustomizerClassName" value="your.package.name.ConnectionCustomizer" />
</bean>
[1]: http://www.mchange.com/projects/c3p0/