-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Statement Leak with Schema Multi Tenant
PostPosted: Fri Sep 09, 2016 4:44 pm 
Newbie

Joined: Thu Sep 08, 2016 7:02 pm
Posts: 5
We're running a multi site app and trying to use MultiTenant switching between Schemas. We're able to switch between schemas, but it's popping up a statement leak warning about 30 seconds after a jdbc connection is made. The system is running on Payara(Glassfish 4) with Hibernate 5 and for the backend we're using Intersystems Cache as a datastore through a JDBC connection. The warning is probably being generated by a glassfish setting to find memory leaks. Our suspicion is that we're creating the connection or executing the statement improperly. The info on multi tenant functionality, in particular with schemas, seems to be more geared towards earlier versions of hibernate. Any suggestions are welcome.

Code:
public class MultiTenantSchemaConnectionProvider implements MultiTenantConnectionProvider {

    private ConnectionProvider connectionProvider;

    public MultiTenantSchemaConnectionProvider(){
        connectionProvider = new DatasourceConnectionProviderImpl();
        Configuration configuration = new Configuration().configure();
        ((DatasourceConnectionProviderImpl) connectionProvider)
                .setJndiService(LazyHibernateServletFilter.getServiceRegistry().getService(JndiService.class));
        ((DatasourceConnectionProviderImpl) connectionProvider).configure(configuration.getProperties());
    }
   
    public Connection getAnyConnection() throws SQLException {
        return connectionProvider.getConnection();
    }

    public Connection getConnection(String tenantIdentifier) throws SQLException {
        Connection con = getAnyConnection();
        try {
            String tenantId = null;
            if (tenantIdentifier.startsWith("192")) { // just for testing
                tenantId = "testSchema1";
            } else {
                tenantId = "testSchema2";
            }
            con.createStatement().execute("USE DATABASE " + tenantId); // <----- Connection Leak Here
        } catch (SQLException ex) {
            ex.printStackTrace();
            throw new HibernateException("Could not alter connection for specific schema");
        }
        return con;
    }

    @Override
    public void releaseAnyConnection(Connection connection) throws SQLException {
        connection.close();
    }

    @Override
    public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
        connection.close();
    }
...
}


This is the error that's being generated.
Code:
2016-09-09T13:33:41.902-0700|Warning: A potential statement leak detected for connection pool CacheDb. The stack trace of the thread is provided below :
com.sun.gjc.spi.base.StatementWrapper.<init>(StatementWrapper.java:98)
com.sun.gjc.spi.jdbc40.StatementWrapper40.<init>(StatementWrapper40.java:64)
com.sun.gjc.spi.jdbc40.ConnectionWrapper40.createStatement(ConnectionWrapper40.java:75)
edu.ucdavis.vmth.vmacs.persistence.config.MultiTenantSchemaConnectionProvider2.getConnection(MultiTenantSchemaConnectionProvider2.java:69)
org.hibernate.internal.AbstractSessionImpl$ContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:429)
org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:84)
org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:109)
org.hibernate.engine.jdbc.internal.StatementPreparerImpl.connection(StatementPreparerImpl.java:47)
org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:146)
org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148)


Top
 Profile  
 
 Post subject: Re: Statement Leak with Schema Multi Tenant
PostPosted: Sat Sep 10, 2016 11:06 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
As long as you close all connection properly, I don't see how the connection could be leaked my using MultiTenncy. Try using a monitoring tool, like FlexyPool, to get a better insight into connection pool usage. Most database systems offer the possibility of finding out if there are connections being leaked too.


Top
 Profile  
 
 Post subject: Re: Statement Leak with Schema Multi Tenant
PostPosted: Mon Sep 12, 2016 6:50 pm 
Newbie

Joined: Thu Sep 08, 2016 7:02 pm
Posts: 5
That's the strange thing. It's not a connection leak; it's a statement leak. Our Glassfish has a statement leak check enabled, and that's what being issued. There is a statement close method: statement.close(). Using that in the getConnection method I'm able to get rid of the error. However it's strange that I'm not finding much saying you need to do that, and certainly that hasn't happened in our app before, though we haven't been getting connections directly.


Top
 Profile  
 
 Post subject: Re: Statement Leak with Schema Multi Tenant
PostPosted: Tue Sep 13, 2016 4:38 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
The Statement should be closed after the query, or at the end of the currently running transaction (for batches). Do you spot an actual use case where this does not hold true? Try investigating it and let us know if you spot the actual culprit.


Top
 Profile  
 
 Post subject: Re: Statement Leak with Schema Multi Tenant
PostPosted: Tue Sep 13, 2016 2:03 pm 
Newbie

Joined: Thu Sep 08, 2016 7:02 pm
Posts: 5
We don't normally handle statements directly. We normally just deal with sessions and transactions. Transactions are closed within the DAO and Session closed within a ServletFilter that does a session per request. Here's some examples from our code base, in particular our baseDAO:

Code:
    @Override
    public void persist(T transientInstance) {
        logger.debug("BaseDAO: persisting instance");
        try {
            Session session = getRequestSessionAndBeginTransaction();
            session.persist(transientInstance);
            commitTransaction(session);
            logger.debug("BaseDAO: persist successful");
        } catch (RuntimeException re) {
            logger.error("BaseDAO: persist failed", re);
            throw re;
        }
    }

or
Code:
    @Override
    public List<T> findByIds(List<Serializable> ids) {
        logger.debug("BaseDAO: getting instance with ids: " + ids);
        try {
            Session session = getSession();
            Query query = session.createQuery("from " + getModelClass().getName() + " where id IN :ids")
                    .setParameter("ids", ids);
            List<T> results = (List<T>) query.list();
            logger.debug("BaseDAO: get successful, instances found");
            return results;
        } catch (RuntimeException re) {
            logger.error("BaseDAO: get by ids failed", re);
            throw re;
        }
    }


Top
 Profile  
 
 Post subject: Re: Statement Leak with Schema Multi Tenant
PostPosted: Tue Sep 13, 2016 2:11 pm 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
It might be some issue in the your Hibernate version, so you'll have to debug it a little bit to see which statement is not properly closed.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.