2

Using Hibernate with Struts2, entire flow is as:

hibernate.cfg.xml as:

<hibernate-configuration>

    <session-factory>
    <property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
    <property name="connection.url">jdbc:oracle:thin:@xx.xx.xxx.xx:1521:TEST</property>
    <property name="connection.username">xxxx</property>
    <property name="connection.password">xxxxyyy</property>
    <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>

   <mapping class="test.models.administration.Menus" />

   <mapping resource="Dual.hbm.xml" />
 </session-factory>

 </hibernate-configuration>

And for DAO's extending AbstractSimpleGenericDao:

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.googlecode.s2hibernate.struts2.plugin.annotations.SessionTarget;
import com.googlecode.s2hibernate.struts2.plugin.annotations.TransactionTarget;

@SuppressWarnings("unchecked")
public abstract class AbstractSimpleGenericDao<C, I extends Serializable> {

Class<C>                 entityClass;

@SessionTarget
protected Session        hSession;

@TransactionTarget
protected Transaction    hTransaction;

{
entityClass = (Class<C>) ((ParameterizedType)           
getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

public List<C> getAll()
{
 try
{
  return hSession.createCriteria(entityClass).list();
}
catch (HibernateException e)
{
  throw e;
}
}

  public C get(I id)
   {
    try
    {
     return (C) hSession.get(entityClass, id);
     }
   catch (HibernateException e)
    {
    throw e;
     }
       }

    public void save(C object)
    {
     try
     {
        hSession.save(object);
     }
        catch (HibernateException e)
        {
          hTransaction.rollback();
          throw e;
        }
        }

         public void update(C object)
           {
             try
              {
                hSession.update(object);
               }
        catch (HibernateException e)
          {
           hTransaction.rollback();
           throw e;
           }
            }

      public void delete(I id)
        {
         try
        {
          C actual = get(id);
          hSession.delete(actual);
         }
         catch (HibernateException e)
         {
         hTransaction.rollback();
          throw e;
          }
          }
          }

Then extending above DAO in my DAO class like:

       public class UserRoleDAO extends AbstractSimpleGenericDao<UserRole, UserRoleId> {

          public List L() {
    try {
        String queryString = "from UserRole";
        Query queryObject = hSession.createQuery(queryString);
        return queryObject.list();
    } catch (RuntimeException re) {
        throw re;
    }
      }

Then in my struts Action class, instantiating DAO and retrieving list:

          public class abc extends ActionSupport{
          private UserRoleDAO userRoleDao = new UserRoleDAO();
          private List ls=new ArrayList();
          public String execute()
        {
             List ls=userRoleDao.L()
     return "success";
        }
            }

If I am Calling this abc Action class, by repetitive clicks on specified menu link then it causes Connection Leak, counts as opened connection that i am able to see using jProfiler, and is never going to close. Meanwhile also, It's leaking connections.

StackTrace of all opened leaked connection's using jProfiler:

org.hibernate.transaction.JDBCTransaction.begin()

com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInter
ceptor.injectHibernateTransactionByAnnotation(java.lang.Object, org.hibernate.Session, boolean)

com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInter
ceptor.injectHibernateTransactionByAnnotation(java.lang.Object, org.hibernate.Session, boolean)

com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInter
ceptor.intercept(com.opensymphony.xwork2.ActionInvocation)

java.lang.Thread.run()
URL: /project/action-name

Why Hibernate is leaking these connections?

Is it like, Hibernate is keeping the connection in session and reusing the same connection and therefore, if at the same time if I am making concurrent request's, if session connection is occupied it would leak connections. This is just i am assuming. I don't have any idea.

Roman C
  • 49,761
  • 33
  • 66
  • 176
Ashish Kataria
  • 520
  • 3
  • 11
  • 31
  • How do you manage session? – Roman C Jan 24 '13 at 11:14
  • @RomanC I am not doing anything for managing session except creating DAO's as i stated above... I am using Tomcat server – Ashish Kataria Jan 24 '13 at 11:23
  • What versions and what plugins do you use. – Roman C Jan 24 '13 at 11:32
  • What is your struts configuration? – Roman C Jan 24 '13 at 11:51
  • @RomanC using Struts2, myeclipse, Tomcat 6.x – Ashish Kataria Jan 24 '13 at 12:01
  • See [this](http://stackoverflow.com/questions/6294764/struts2-full-hibernate-plugin-session-is-closed) – Roman C Jan 24 '13 at 12:09
  • @RomanC I am using struts2-fullhibernatecore-plugin-2.2.1-GA.jar – Ashish Kataria Jan 24 '13 at 12:41
  • http://code.google.com/p/full-hibernate-plugin-for-struts2/downloads/detail?name=struts2-fullhibernatecore-plugin-2.2.2-GA.jar&can=2&q= – Ashish Kataria Jan 24 '13 at 13:06
  • You may want to try to use a connection pool like commons dbcp or c3p0. Then set the dataSource property on your sessionFactory config. This may help. – Manuel Quinones Jan 24 '13 at 16:09
  • @ManuelQuinones Hibernate keeps pooling its connections by default to 20. – Roman C Jan 24 '13 at 20:40
  • @RomanC Is it the bug in this hibernate plugin I am using... is there any alternative way wiithout plugin? – Ashish Kataria Jan 26 '13 at 19:08
  • @AshishKataria How many connections do you have? – Roman C Jan 26 '13 at 20:31
  • @RomanC This Google Hibernate Plugin is managing sessions as well as opening/closing of connections.. At tomcat side, I have 250 connection limit.. I would like to know, Any other way of using Hibernate without this plugin? I doubt, this plugin might be creating connection leaks. Or Any way, I can fix this plugin, anyone using this plugin? – Ashish Kataria Jan 28 '13 at 08:57
  • @AshishKataria It depends on how would you like to manage the hibernate session to not rewrite a lot the code. I don't understand what a connection limit do you have, don't mess up tomcat http connections and hibernate database connections. As I see from your hibernate.cfg the hibernate owns connections to the database and by default keeps pooling em, you can use hibernate.c3p0 properties to configure the connection pool. Update to version 2.2.2, and why didn't you post struts.xml? – Roman C Jan 28 '13 at 12:44

1 Answers1

1

In your hibernate configuration implicitly used DriverManagerConfigurationProvider. This provider used by default unless you configured it with property connection.provider_class.

This provider also implements a very rudimentary connection pool.

What it means "rudimentary connection pool". If you run your application you can see in the logs

[DriverManagerConnectionProvider] Using Hibernate built-in connection pool (not for production use!)
[DriverManagerConnectionProvider] Hibernate connection pool size: 20

You can also set this value via hibernate configuration property connection.pool_size. But it doesn't limit you to the maximum opened connections count. You can open as many as you need connections while pool is empty. The provider will keep them open as it returns connections to pool on closeConnection unless the current pool size not exceeds the value in the property connection.pool_size. Once current pool size is not empty you cannot open any new connection because the connection provider returns connection from the pool.

As you can see now it's difficult to say that hibernate using this connection provider by default may leak the connections, I've just say it's impossible. However, it's not limited with the number of opened connections.

To make sure the connections are limited use a different connection provider. For example you could use C3P0ConnectionProvider and set the property hibernate.c3p0.max_size to limit opened connections.

Roman C
  • 49,761
  • 33
  • 66
  • 176
  • I just checked as I have not defined connection.pool_size property so it was taking 20 connection pool by default i.e. connections grows till 20 which i thought of leaking and would stick to it afterwards, Now I have defined connection.pool_size property=1. Still Connections grows but immediately comes back to 1. That is perfectly Ok, but any drawbacks of defining pool_size=1. or rather, what would be the advantage of using pool size>1 when connections would not be going to come back less than defined limit? Thanks for providing a solution RomanC – Ashish Kataria Jan 29 '13 at 15:47
  • And you mentioned to use C3P0ConnectionProvider, hibernate.c3p0.max_size to limit opened connections. Limiting number of opened connections, does it mean beyond that new request would not be served? Now with connection.pool_size property=1, Number of connections go beyond 1, but at the same time connections fall back to 1. So here, connections will increase but soon will release too. Any advantage of using C3P0ConnectionProvider over this? – Ashish Kataria Jan 29 '13 at 15:57
  • new request will be served unless you limited connections by the database. really don't know how do they fall back, if you close the connection it's not closed instead returned to the pool. c3p0 better manages connections, i.e. their lifecycle. – Roman C Jan 29 '13 at 18:53
  • opening connection is time expensive, with c3p0 this time will be less expensive as with default connection manager. IMHO. – Roman C Jan 29 '13 at 19:10