Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where do I have to place the JDBC driver for Tomcat's connection pool?

So I've figured out my error, now I'm just looking for some insight as to what is going on exactly. I am using Apache Tomcat Version 7.0.32. I am using this tutorial to set up pooling for JDBC. In my META-INF folder I made a context.xml file and put this in there.

<?xml version="1.0" encoding="UTF-8"?>  <Context>     <Resource type="javax.sql.DataSource" name="jdbc/gmustudent"         factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"          driverClassName="com.mysql.jdbc.Driver"         url="jdbc:mysql://localhost:3306/official"         username="root" password="root"         maxActive="100" maxIdle="20" minIdle="15" initialSize="15" maxWait="10000" /> </Context> 

I got this error when I wrote this

WARNING: Unexpected exception resolving reference java.sql.SQLException: com.mysql.jdbc.Driver     at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:254)     at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:182)     at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:699)     at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:631)     at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:485)     at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:143)     at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:116)     at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:103)     at org.apache.tomcat.jdbc.pool.DataSourceFactory.createDataSource(DataSourceFactory.java:539)     at org.apache.tomcat.jdbc.pool.DataSourceFactory.getObjectInstance(DataSourceFactory.java:237)     at org.apache.naming.factory.ResourceFactory.getObjectInstance(ResourceFactory.java:143)     at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:304)     at org.apache.naming.NamingContext.lookup(NamingContext.java:843)     at org.apache.naming.NamingContext.lookup(NamingContext.java:154)     at org.apache.naming.NamingContext.lookup(NamingContext.java:831)     at org.apache.naming.NamingContext.lookup(NamingContext.java:168)     at org.apache.catalina.core.NamingContextListener.addResource(NamingContextListener.java:1061)     at org.apache.catalina.core.NamingContextListener.createNamingContext(NamingContextListener.java:671)     at org.apache.catalina.core.NamingContextListener.lifecycleEvent(NamingContextListener.java:270)     at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)     at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)     at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5173)     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)     at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)     at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)     at java.util.concurrent.FutureTask.run(FutureTask.java:138)     at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)     at java.lang.Thread.run(Thread.java:680) Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver     at java.net.URLClassLoader$1.run(URLClassLoader.java:202)     at java.security.AccessController.doPrivileged(Native Method)     at java.net.URLClassLoader.findClass(URLClassLoader.java:190)     at java.lang.ClassLoader.loadClass(ClassLoader.java:306)     at java.lang.ClassLoader.loadClass(ClassLoader.java:247)     at java.lang.Class.forName0(Native Method)     at java.lang.Class.forName(Class.java:247)     at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:246)     ... 29 more Oct 31, 2012 11:23:25 AM org.apache.catalina.core.NamingContextListener addResource WARNING: Failed to register in JMX: javax.naming.NamingException: com.mysql.jdbc.Driver Oct 31, 2012 11:23:25 AM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["http-bio-8086"] Oct 31, 2012 11:23:25 AM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["ajp-bio-8009"] Oct 31, 2012 11:23:25 AM org.apache.catalina.startup.Catalina start INFO: Server startup in 794 ms 

This error only comes up when I have this statement in my context.xml file. When I remove it no error.

factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"  

The reason I want to make sure that I have it is because in the apache tomcat tutorial it says

factory is required, and the value should be org.apache.tomcat.jdbc.pool.DataSourceFactory 

So then I did a little bit of research on SO and found a post saying that you need to add this jar to your lib folder if you have an older version of tomcat. So I added the jar and now it works but I would like to have some information as to what on earth is going on because I am using the newest tomcat version. So why when I specify a factory do I get an error. And what is this jar that I'm adding in and why is there very little documentation about it? Any information about what is going on here would be greatly appreciated.

like image 699
gmustudent Avatar asked Oct 31 '12 15:10

gmustudent


People also ask

Where do you configure a database connection pool in a Tomcat server?

For configuring the connection pool for SQLServer you need to configure the SQLServer drivers as explained in the Microsoft SQL Server section and put the jar file into the TOMCAT_HOME/lib folder. Note that database name, username and password must be defined directly in the URL.

How does JDBC connection pooling work?

Via the JDBC resource, the application gets a database connection. Behind the scenes, the application server retrieves a physical connection from the connection pool that corresponds to the database. The pool defines connection attributes such as the database name (URL), user name, and password.

What is it that we use for JDBC connection pooling in our application?

Connection pooling means that connections are reused rather than created each time a connection is requested. To facilitate connection reuse, a memory cache of database connections, called a connection pool, is maintained by a connection pooling module as a layer on top of any standard JDBC driver product.

Where is the JDBC driver located in Tomcat?

The JDBC driver has to be visible to the same classloader as the data source factory itself. The data source factory library is placed in Tomcat's own /lib folder and thus loaded by Tomcat's "common" classloader. Your problem sounds much like that you dropped the JDBC driver in webapp's /WEB-INF/lib.

What is the connection pool in Tomcat?

The Tomcat Connection pool is configured as a resource described in The Tomcat JDBC documentation With the only difference being that you have to specify the factory attribute and set the value to org.apache.tomcat.jdbc.pool.DataSourceFactory The connection pool only has another dependency, and that is on tomcat-juli.jar.

What version of Tomcat is used for JDBC pooling?

So I've figured out my error, now I'm just looking for some insight as to what is going on exactly. I am using Apache Tomcat Version 7.0.32. I am using this tutorial to set up pooling for JDBC. In my META-INF folder I made a context.xml file and put this in there.

How do I connect Tomcat to a MySQL database?

Connecting Tomcat to a MySQL database. 1 Step 1: Download the MySQL JDBC driver. The driver that JDBC needs to connect to MySQL is called Connector/J. It is developed by the MySQL engineering ... 2 Step 2: Configure your MySQL database as a JNDI resource. 3 Step 2a: JDBC resource configuration. 4 Step 2b: Configuring resource references.


1 Answers

The JDBC driver has to be visible to the same classloader as the data source factory itself. The data source factory library is placed in Tomcat's own /lib folder and thus loaded by Tomcat's "common" classloader.

Your problem sounds much like that you dropped the JDBC driver in webapp's /WEB-INF/lib. The webapp's /WEB-INF/lib is invisible to the "common" classloader. So technically, you have to place the JDBC driver in Tomcat's own /lib folder (or, at least, in a configurable path as specified by common.loader setting in /conf/catalina.properties) in order to make it visible to the data source factory.

Or, as you attempted, copying the data source factory into /WEB-INF/lib will also fix it. The webapp's /WEB-INF/lib has namely higher precedence in classloading than Tomcat's /lib folder. So if the data source factory is found in /WEB-INF/lib, it will be loaded from there. As the JDBC driver is also there, it will be seen. This is however not the right solution to your concrete problem, this is more a workaround, so you shouldn't do this.

There isn't exactly documentation which is specifically targeted to this issue. The Tomcat Class Loader HOW-TO will however help in understanding the class loading hierarchy in Tomcat.

screen shot showing Tomcat folder with nested "lib" folder with nested JDBC driver .jar file

See also:

  • The infamous java.sql.SQLException: No suitable driver found
  • How should I connect to JDBC database / datasource in a servlet based application?
  • Is it safe to use a static java.sql.Connection instance in a multithreaded system?
like image 135
BalusC Avatar answered Nov 04 '22 00:11

BalusC