scphantm
scphantm

Reputation: 4543

elegantly handling stale database connections in Hibernate/Spring Transactions

i have a system that has been working fine in testing but now that i have moved them to the production servers and am ready to throw the switch, im having a problem.

if the application sits idle for around 15 minutes, the DB connection in the spring transaction service drops. the first person that comes to the app after that happens is greeted with this

org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Cannot open connection
    org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:596)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
    org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
    parity.persistence.DataAccess$$EnhancerByCGLIB$$921ef13.find(<generated>)
    parity.model.Configuration.getConfiguration(Configuration.java:84)
    parity.model.Configuration.getSetting(Configuration.java:46)
    parity.model.Configuration$$FastClassByCGLIB$$8355c3d0.invoke(<generated>)
    net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:617)
    parity.model.Configuration$$EnhancerByCGLIB$$5e96e8b9.getSetting(<generated>)
    parity.model.OnlineStatus.getSiteStatus(OnlineStatus.java:50)
    parity.action.site.SiteStatusInterceptor.intercept(SiteStatusInterceptor.java:16)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
    org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
    org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:498)
    org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:434)
root cause

if you hit F5 on your browser, it reconnects and runs just fine. it looks like spring is doing something along the lines of the first request, going eek, i died, and in the process of dieing, reconnecting to the database. but im not sure.

i have been searching for ways to solve this but it looks like unless i am using c3p0 or weblogic everyone is clueless. is there a way to fix this? here are my config files

hibernate.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
        <property name="connection.autocommit">false</property>
        <property name="show_sql">false</property>
        <property name="use_sql_comments">false</property>

    </session-factory>
</hibernate-configuration>

transaction-service.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:aop="http://www.springframework.org/schema/aop"
    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/tx
     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
     http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean id="boardingSessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocations">
            <list>
                <value>classpath:hibernate/boarding-hibernate.cfg.xml</value>
                <value>classpath:boarding-hibernate.cfg.xml</value>
            </list>
        </property>
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
    </bean>

    <bean id="boardingTransactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="boardingSessionFactory" />
        <qualifier value="boarding" />
    </bean>

    <tx:advice id="boardingTxAdvice" transaction-manager="boardingTransactionManager">
        <tx:attributes>
            <tx:method name="get*" read-only="true" />
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>
</beans>

note, my hibernate uses 2 files, one in the API that handles global settings, and one in the app itself that has application specific settings. for purposes here, the global one is all that matters, i think.

Upvotes: 2

Views: 2682

Answers (1)

JB Nizet
JB Nizet

Reputation: 691775

The Hibernate documentation says:

Hibernate's own connection pooling algorithm is, however, quite rudimentary. It is intended to help you get started and is not intended for use in a production system, or even for performance testing. You should use a third party pool for best performance and stability.

So, the answer is simple: use a real connection pool, and configure it to test connections before giving them to the application.

Upvotes: 1

Related Questions