Why is using C3PO and JNDI at the same time a problem?

I am running an application using Hibernate from the Tomcat 8 server. I want to use a different connection pool than Hibernate, because they make it obvious that it is not suitable for use in a production environment.

In addition, they note that:

For use inside an application server, you almost always have to configure Hibernate to receive connections from the javax.sql.Datasource application server registered in JNDI.

I think I need to do two things:

  • Configure Hibernate to work with a third-party connection pool - Hibernate recommends C3PO
  • Configure Hibernate to get connections from javax.sql.Datasource object registered in JNDI

I was learning how to do this, and I came across this question. The poster already uses C3PO and asks how to connect to its database through the JNDI Datasource object. However, they ran into problems as they already used C3PO when they followed the steps of the responder to use the JNDI data source. The poster said this in the comments section of the accepted answer:

Yes, right, I did it very stupidly using both c3p0 and JNDI. I deleted all c3p0 configurations and now it works fine.

Hibernate recommends using a third-party connection pool, namely C3PO, and using a JNDI data source to receive connections, and yet it seems to be causing a problem for this user; and they even go so far as to talk about using both of them at the same time, as if it were an obvious mistake.

Can I use both of them at the same time, or should I, as Hibernate recommends? All I'm trying to do is replace the default Hibernate connection pool with a pool that is intended for use in production environments, and configure Hibernate to receive connections from the javax.sql.Datasource object registered in JNDI as they recommend.

+8
hibernate jndi
source share
2 answers

I will try to clear the confusion.

I think this starts with a surprisingly simple DataSource interface: https://docs.oracle.com/javase/7/docs/api/javax/sql/DataSource.html

The DataSource interface is implemented by the driver provider. There are three types of implementation:

  • The main implementation - creates a standard Connection object
  • Implementation of the connection pool - creates a Connection object that will automatically participate in the connection pool. This implementation works with the middleware connection pool manager.
  • Distributed transaction - creates a Connection object that can be used for distributed transactions and almost always participates in the connection pool. This implementation works with a mid-level transaction manager and almost always with a pool manager connection.

Hibernation requires a data source for operation and recommends using a connection pool.

C3PO wraps the existing DataSource and applies a connection pool to it and creates a new DataSource, which is type 2. C3PO assumes that the DataSource that it receives is type 1, but it cannot be sure.

In other application servers, if you declare a data source that is registered in JNDI, it almost always uses the connection pool already in the container. In the case of Tomcat 8, it uses C3PO internally.

Thus, there are two ways to reach the connection pool in Hibernate: either create a type 1 data source, or insert it into the connection pool in the code, or declare your data source (with connection pool) in the container and put it into sleep mode from JNDI.

If you do both, as in your case, C3PO in your application gets the data source from JNDI, which itself is a C3PO DataSource managed by tomcat. When an application tries to get a connection, the C3PO application will call the C3PO container, which will create the actual connection, but the connection will be combined into both connection pools. When hibernate releases the connection, the C3PO application will support it for reuse, but the other connection pool will continue to wait until the connection is also released.

Depending on the configuration, the base connection pool may kill the connection after a certain timeout.

Thus, setting up two connection pools on top of each other is dangerous and completely unnecessary.

To answer the bonus question: in production environments, declare the data source in your production container and connect it to Hibernate via JNDI without any additional connection pool configured in Hibernate.

+2
source share

In the original SO message, the poster starts with C3PO already configured by Hibernate. When the poster switched to receiving a JNDI link to an already configured C3PO connection pool, he / she thought that the configuration was processed by Hibernate during its launch. The solution was to move the C3PO configuration into a container (Tomcat) and remove the configuration from the Hibernate settings.

Here is a simplified application launcher:

  • The container performs its launch operations.
    • Create a connection and start listening to connections
    • Create and configure JNDI resources such as DataStore sessions, mail sessions, etc.
  • Web Application Deployment
    • Web Application Scan
    • Web Application Setup
    • Provide any JNDI resources specified during configuration
    • Complete deployment

This is during the web application deployment phase that the Hibernate configuration reads and the JNDI resource request is made. Since C3PO is already configured, any configuration made in Hibernate is not visible.

+1
source share

All Articles