Reputation: 1307
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.
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;
}
}
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][] ================================================
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();
}
}
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