57

Why does it say null URL and gives a empty ' ' class in the exception when I have provided the database URL?

I am trying to connect to a derby database via a servlet while using Tomcat. When the servlet gets run, I get the following exceptions:

org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'

at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1452)
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1371)
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)

at servlets.servlet_1.doGet(servlet_1.java:23) // ---> Marked the statement in servlet

at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:964)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.NullPointerException
at sun.jdbc.odbc.JdbcOdbcDriver.getProtocol(JdbcOdbcDriver.java:507)
at sun.jdbc.odbc.JdbcOdbcDriver.knownURL(JdbcOdbcDriver.java:476)
at sun.jdbc.odbc.JdbcOdbcDriver.acceptsURL(JdbcOdbcDriver.java:307)
at java.sql.DriverManager.getDriver(DriverManager.java:253)
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1437)
... 24 more

Servlet :

package servlets;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.http.*;
import javax.servlet.*;
import javax.sql.DataSource;

public class servlet_1 extends HttpServlet {

    @Override 
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
           // String queryString = request.getQueryString();
            System.out.println("!!!!!!!!!!!!!!!!!!!");
            Context initContext = new InitialContext();
            Context envContext = (Context)initContext.lookup("java:comp/env");
            DataSource ds = (DataSource)envContext.lookup("jdbc/PollDatasource");
            Connection connection = ds.getConnection(); // -->LINE 23
            String sqlQuery = "select * from PollResult";
            PreparedStatement statement = connection.prepareStatement(sqlQuery);
            ResultSet set = statement.executeQuery();
            System.out.println("after the final statement");
        } catch (Exception exc) {
            exc.printStackTrace();
        }
    }
}

What exception is this? Why do I get this exception?

I have added the following tag in context.xml of Tomcat :

<Resource name="jdbc/PollDatasource" auth="Container" type="javax.sql.DataSource"
driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
url="jdbc:derby://localhost:1527/poll_database;create=true"
username="suhail" password="suhail"
maxActive="20" maxIdle="10" maxWait="-1" />

and this in web.xml :

<resource-ref>
  <description>my connection</description>
  <res-ref-name>jdbc/PollDatasource</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
</resource-ref>

Where am I making a mistake?

Image that shows the database URL..

enter image description here

NOTE : After the answer by @Bryan Pendleton I changed the driver to org.apache.derby.jdbc.ClientDriver but I get the same exception.

Community
  • 1
  • 1
Suhail Gupta
  • 22,386
  • 64
  • 200
  • 328
  • 2
    I think the connect URL is missing. – Akhi Jul 17 '12 at 06:01
  • @SuhailGupta We get flags on questions indicating it's a duplicate. Sometimes we process them incorrectly. It happens. We fix it where we can and we fixed it here. There's no reason to comment on this issue anymore. – casperOne Jul 17 '12 at 15:57
  • Where is your JDBC driver .jar file located? – Christopher Schultz Jul 22 '12 at 13:49
  • @Christopher Schultz what do you actually mean by `JDBC` driver ? I have the driver to connect to the derby database inside the _lib_ folder of _tomcat_. – Suhail Gupta Jul 22 '12 at 17:11
  • I meant what I said: "where is your JDBC driver .jar file?" You say it is in Tomcat's `lib` directory. That's good. Do you have it anywhere else? Do you have an out-of-process Derby database? Derby is usually used in-process. – Christopher Schultz Jul 22 '12 at 21:09
  • @Christopher Schultz No,only inside the tomcat's lib folder. No,in process. – Suhail Gupta Jul 23 '12 at 05:07
  • I got the exact same error message after I copied a db configuration from one project to another as is (no changes). The connection was fine, the JDBC driver was fine, the connection user/password was fine. The problem was the second project was calling a package/stored procedure that didn't exist. Very misleading error message. – Gerry Nov 15 '21 at 18:04

12 Answers12

38

I can't see anything obviously wrong, but perhaps a different approach might help you debug it?

You could try specify your datasource in the per-application-context instead of the global tomcat one.

You can do this by creating a src/main/webapp/META-INF/context.xml (I'm assuming you're using the standard maven directory structure - if not, then the META-INF folder should be a sibling of your WEB-INF directory). The contents of the META-INF/context.xml file would look something like:

<?xml version="1.0" encoding="UTF-8"?>

<Context [optional other attributes as required]>

<Resource name="jdbc/PollDatasource" auth="Container"
          type="javax.sql.DataSource" driverClassName="org.apache.derby.jdbc.ClientDriver"
          url="jdbc:derby://localhost:1527/poll_database;create=true"
          username="suhail" password="suhail" maxActive="20" maxIdle="10" maxWait="-1"/>
</Context>

Obviously the path and docBase would need to match your application's specific details.

Using this approach, you don't have to specify the datasource details in Tomcat's context.xml file. Although, if you have multiple applications talking to the same database, then your approach makes more sense.

At any rate, give this a whirl and see if it makes any difference. It might give us a clue as to what is going wrong with your approach.

Christopher Schultz
  • 20,221
  • 9
  • 60
  • 77
Taskmaster
  • 966
  • 8
  • 16
11

Several fixes:

  1. Use the right driver class name for your environment: if you are using an out-of-process Derby server, then you want ClientDriver (and need to use derbyclient.jar), the hostname and port, etc. If you want an in-process Derby server, then you want derby.jar, EmbeddedDriver, and a URL that is appropriate for an embedded database.

  2. Put your driver JAR file only in Tomcat's lib/ directory.

  3. Don't put anything in Tomcat's conf/context.xml: there's really no reason for it. Instead, use your webapp's META-INF/context.xml to define your <Resource>.

The error "Cannot create JDBC driver of class '' for connect URL 'null' usually occurs because the JDBC driver is not in the right place (or in too many places, like Tomcat's lib/ directory but also in the webapp's WEB-INF/lib/ directory). Please verify that you have the right driver JAR file in the right place.

Christopher Schultz
  • 20,221
  • 9
  • 60
  • 77
  • 1
    The driver has always been in the right place,that is inside the _lib_ folder of tomcat. – Suhail Gupta Jul 23 '12 at 05:10
  • 3
    @ChristopherSchultz The reason why resources are put to conf/context and not META-INF is platform independecy. You have just one war and more resource config and pooling managed by the given server. – banterCZ Jan 11 '13 at 12:16
  • @banterCZ You can maintain platform independence without modifying Tomcat's site-wide `conf/context.xml`. Modifying that file is sloppy at best and a security vulnerability at worst. – Christopher Schultz Mar 10 '14 at 13:37
  • @ChristopherSchultz I'm using this to configure an Oracle Universal Connection Pool. When my app shuts down Tomcat complains that it left some UCP threads hanging. I'm not sure, but I assume if I could get it to work with `conf/context.xml` Tomcat wouldn't complain about this? – Andy Apr 30 '15 at 20:26
  • @Andy Oracle's driver either has a bug in it, or you aren't properly shutting-down the JDBC driver before your application unloads. Have you put your driver .jar file in Tomcat's `lib` directory or into your application's `WEB-INF/lib`? – Christopher Schultz May 01 '15 at 16:11
  • @ChristopherSchultz in Tomcat's `lib`. The whole point of defining a resource like this is that it can be shared between applications/executions of a single application, right? Meaning that the application shouldn't be responsible for shutting it down? – Andy May 01 '15 at 19:37
  • 1
    @Andy Many JDBC drivers do stupid things like capturing the thread class loader and storing them forever. In a servlet environment, this can lead to a ClassLoader-pinning memory leak. To get around these problems in JDBC drivers, you sometimes have to take action during webapp shutdown. I know for instance that MySQL's Connector/J has had ClassLoader-pinning issues for a long time, and MySQL doesn't seem to buy the arguments for *not* going what they're doing. So, the JDBC driver continues to be broken, and certain hacks are required in order to stop a web application cleanly. – Christopher Schultz May 04 '15 at 20:26
  • @ChristopherSchultz huh, thanks for the tip, I'm sure it would have taken me awhile to discover that! – Andy May 04 '15 at 21:39
  • Tips 3 resolved my issue. I was putting the database connection info in the conf/context.xml – duvo Sep 19 '17 at 18:04
  • @ChristopherSchultz, tip 2 resolved a similar issue I with the Oracle DB Driver. I had the driver jar not only in in Tomcat's lib directory but also in WEB-INF/lib. I spent 4 hours trying out different things yesterday but the damn thing just kept complaining about a empty '' class and null URL. This solved the issue in an instant, thanks ! – Suketu Bhuta Nov 21 '17 at 16:06
  • This solved my issue: - MySQL connector jar only in ```tomcat/lib```, - META-INF/context.xml and web.xml to configure the dataSource – AshMenhennett Dec 10 '17 at 09:53
  • If you inject the DataSource using a `@Resourse` annotation, make sure you specify a name for it, like `@Resource(name="jdbc/myDataSource")`. This solved my problem. – Gabriel Belingueres Apr 23 '21 at 14:43
7

These two things don't match:

driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
url="jdbc:derby://localhost:1527/poll database;create=true"

If you are using the EmbeddedDriver, your URL should not contain network syntax.

Conversely, if you are using network syntax, you need to use the ClientDriver.

http://db.apache.org/derby/docs/10.8/getstart/rgsquck35368.html

Alastair McCormack
  • 26,573
  • 8
  • 77
  • 100
Bryan Pendleton
  • 16,128
  • 3
  • 32
  • 56
  • _"If you are using the EmbeddedDriver, your URL should not contain network syntax."_ Can you please tell the manner i should write the URL when using the _EmbeddedDriver_ – Suhail Gupta Jul 18 '12 at 03:46
  • As per following tutorial: http://db.apache.org/derby/papers/DerbyTut/embedded_intro.html , URL should look like `jdbc:derby:poll_database;create=true` in case of **EmbeddedDriver** – Yuriy Nakonechnyy Jul 21 '12 at 17:44
7

I was getting this problem because I put context.xml into the wrong path:

./src/main/resources/META-INF/context.xml

The correct path was:

./src/main/webapp/META-INF/context.xml
vadipp
  • 877
  • 1
  • 12
  • 22
3

If you are using eclipse, you should modify the context.xml, from the server project created in your eclipse package explorer. When using tomcat in eclipse it is the only one valid, the others are ignored or overwriten

jesantana
  • 1,241
  • 2
  • 14
  • 27
2

Context envContext = (Context)initContext.lookup("java:comp/env");

not:Context envContext = (Context)initContext.lookup("java:/comp/env");

Blade Master
  • 157
  • 6
  • that was a mistake ! Get the same exception after editing it. See the Edit – Suhail Gupta Jul 17 '12 at 06:16
  • see your context.xml of tomcat: url="connection.url",need to edit url,if you do not know changed to what ,you can see this: http://db.apache.org/derby/docs/10.7/devguide/rdevdvlp22102.html#rdevdvlp22102 – Blade Master Jul 17 '12 at 06:41
  • i changed to `url="jdbc:derby:poll database"` but get the same exceptions – Suhail Gupta Jul 17 '12 at 06:51
  • if your database name is polldatabase ,edit url to this: url="jdbc:derby: //localhost:1527/polldatabse;create=true"; – Blade Master Jul 17 '12 at 07:00
1

Did you try to specify resource only in context.xml

<Resource name="jdbc/PollDatasource" auth="Container" type="javax.sql.DataSource"
driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
url="jdbc:derby://localhost:1527/poll_database;create=true"
username="suhail" password="suhail"
maxActive="20" maxIdle="10" maxWait="-1" />

and remove <resource-ref> section from web.xml?

In one project I've seen configuration without <resource-ref> section in web.xml and it worked.

It's an educated guess, but I think <resource-ref> declaration of JNDI resource named jdbc/PollDatasource in web.xml may override declaration of resource with same name in context.xml and the declaration in web.xml is missing both driverClassName and url hence the NPEs for that properties.

Yuriy Nakonechnyy
  • 3,742
  • 4
  • 29
  • 41
1

The problem could also come because of a lack of SQL driver in your Tomcat installation directory.

I had to had mysql-connector-java-5.1.23-bin.jar in apache-tomcat-9.0.12/lib/ folder.

https://dev.mysql.com/downloads/connector/j/

Alexsoyes
  • 444
  • 4
  • 12
0

In my case I solved the problem editing [tomcat]/Catalina/localhost/[mywebapp_name].xml instead of META-INF/context.xml.

Joaquim Perez
  • 97
  • 1
  • 3
0

I had this problem on a Tomcat 6. I had the Oracle jdbc driver .jar in two sites, one in the tomcat6/lib folder and in my C:/develop/lib folder which I was pointing on my catalina.properties file:

common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar,C:/develop/lib/*.jar

One of these .jar must be deleted, the tomcat6/lib one or the common.loader one.

M.Garcia
  • 26
  • 6
-1

If you're using an embedded driver, the connectString is just

jdbc:derby:databaseName 

(whith options like;create=true;user=xxx etc).

If you're using client driver, the connect string can be left as is, but if changing the driver gives no result... excuse the question, but are you 100% sure you have started the Derby Network Server as per the Derby Tutorial?

pafau k.
  • 1,667
  • 12
  • 20
-1

I had a similar problem using Tomcat against Oracle. I DID have the context.xml in the META-INF directory, on the disc. This file was not showing in the eclipse project though. A simple hit on the F5 refresh and the context.xml file appeared and eclipse published it. Everything worked past that. Hope this helps someone.

Try hitting F5 in eclipse

theINtoy
  • 3,388
  • 2
  • 37
  • 60