G. Ciardini
G. Ciardini

Reputation: 1307

Hibernate / HikariCP - Connection leak, still active after close it

I'm having a problem with hibernate and hikaricp, more precisely I encountered a leak using a stateless session with a semi-complex procedure. To give you context this is an app that exposes api to write/read to the database. Everything is packaged via tomcat9.

How manage the session

Every time I need to open a session I use openSession()


public static SessionFactory getSessionFactory()
{
    if (sessionFactory == null)
    {
        sessionFactory = buildSessionFactory();
    }

    return sessionFactory;
}

public static StatelessSession openSession()
{
    return getSessionFactory().openStatelessSession();
}

Every time I need to close or manage an exception I use resolveError(session) and closeSession(session).

public static void resolveError(StatelessSession session)
{
    if (session != null
            && session.getTransaction() != null
            && session.getTransaction().getStatus() != null
            && session.getTransaction().getStatus() == TransactionStatus.ACTIVE)
    {
        session.getTransaction().rollback();
    }

}

public static void closeSession(StatelessSession session)
{
    if (session != null)
    {
        if (session.getTransaction() != null
                && session.getTransaction().getStatus() != null
                && session.getTransaction().getStatus() == TransactionStatus.ACTIVE)
        {
            session.getTransaction().commit();
        }

        session.close();
        session = null;
    }
}

How I've found the leak

Thanks to hikari bean I was able to get the current count of active connections, so before and after my method I am able to monitor it.


public static HikariPoolMXBean getHikariPool()
{
    try
    {
        MBeanServer bean = ManagementFactory.getPlatformMBeanServer();
        ObjectName poolName = new ObjectName("com.zaxxer.hikari:type=Pool (HikariPool-1)");

        return JMX.newMXBeanProxy(bean, poolName, HikariPoolMXBean.class);
    }
    catch (MalformedObjectNameException e)
    {
        e.printStackTrace();
    }

    return null;
}

Before my method (the service just started up)

[02-07-2024 17:06:16,640][DEBUG][] ================================================
[02-07-2024 17:06:16,640][DEBUG][] Idle Connections:   10
[02-07-2024 17:06:16,640][DEBUG][] Active Connections: 0
[02-07-2024 17:06:16,640][DEBUG][] Thread Awaiting:    0
[02-07-2024 17:06:16,640][DEBUG][] Total Connections:  10
[02-07-2024 17:06:16,640][DEBUG][] ================================================

After my method (even after a few minutes the count does not change)

[02-07-2024 17:06:16,640][DEBUG][] ================================================
[02-07-2024 17:06:16,640][DEBUG][] Idle Connections:   10
[02-07-2024 17:06:16,640][DEBUG][] Active Connections: 1
[02-07-2024 17:06:16,640][DEBUG][] Thread Awaiting:    0
[02-07-2024 17:06:16,640][DEBUG][] Total Connections:  11
[02-07-2024 17:06:16,640][DEBUG][] ================================================

What the method does

I have tried to summarize every action taken regarding the session (hope this helps).

private static final Object lock = new Object();

public Response method(DTO dto)
{
    StatelessSession session = openSession();
    
    ...

    try
    {
        validateDTO(dto); // hibernate-validator

        ...

        closeSession(session);

        synchronized (lock)
        {
            session = openSession();
            session.getTransaction().begin();

            ...

            session.getTransaction().commit();

            ...         

            closeSession(session);

            return Response.status(Response.Status.OK)
                    .entity(...).build();
        }
    }
    catch (Exception e)
    {
        ...

        resolveError(session);
        closeSession(session);

        return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(...).build();
    }
}

The question

Did I make a mistake in any of the above steps? do I have to close the session differently?

Thanks in advance, Giacomo.

Upvotes: 2

Views: 73

Answers (0)

Related Questions