The infamous java.sql.SQLException: No suitable driver found
Asked Answered
S

23

129

I'm trying to add a database-enabled JSP to an existing Tomcat 5.5 application (GeoServer 2.0.0, if that helps).

The app itself talks to Postgres just fine, so I know that the database is up, user can access it, all that good stuff. What I'm trying to do is a database query in a JSP that I've added. I've used the config example in the Tomcat datasource example pretty much out of the box. The requisite taglibs are in the right place -- no errors occur if I just have the taglib refs, so it's finding those JARs. The postgres jdbc driver, postgresql-8.4.701.jdbc3.jar is in $CATALINA_HOME/common/lib.

Here's the top of the JSP:

<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<sql:query var="rs" dataSource="jdbc/mmas">
  select current_validstart as ValidTime from runoff_forecast_valid_time
</sql:query>

The relevant section from $CATALINA_HOME/conf/server.xml, inside the <Host> which is in turn within <Engine>:

<Context path="/gs2" allowLinking="true">
  <Resource name="jdbc/mmas" type="javax.sql.Datasource"
      auth="Container" driverClassName="org.postgresql.Driver"
      maxActive="100" maxIdle="30" maxWait="10000"
      username="mmas" password="very_secure_yess_precious!"
      url="jdbc:postgresql//localhost:5432/mmas" />
</Context>

These lines are the last in the tag in webapps/gs2/WEB-INF/web.xml:

<resource-ref>
  <description>
     The database resource for the MMAS PostGIS database
  </description>
  <res-ref-name>
     jdbc/mmas
  </res-ref-name>
  <res-type>
     javax.sql.DataSource
  </res-type>
  <res-auth>
     Container
  </res-auth>
</resource-ref>

Finally, the exception:

   exception
    org.apache.jasper.JasperException: Unable to get connection, DataSource invalid: "java.sql.SQLException: No suitable driver"
    [...wads of ensuing goo elided]
Shippy answered 15/12, 2009 at 23:33 Comment(1)
P
139

The infamous java.sql.SQLException: No suitable driver found

This exception can have basically two causes:

1. JDBC driver is not loaded

In case of Tomcat, you need to ensure that the JDBC driver is placed in server's own /lib folder.

Other servers have a similar way of placing the JAR file:

  • GlassFish: put the JAR file in /glassfish/lib
  • WildFly: put the JAR file in /standalone/deployments

Or, when you're actually not using a server-managed connection pool data source which you e.g. obtain via JNDI @Resource or configure in JPA's persistence.xml, but when you are manually fiddling around with DriverManager#getConnection() the low level way in a custom class in WAR, then you need instead to place the JDBC driver in WAR's /WEB-INF/lib and perform ..

Class.forName("com.example.jdbc.Driver");

.. in your custom code before the first DriverManager#getConnection() call, whereby you make sure that you do not swallow/ignore any ClassNotFoundException which can be thrown by it and continue the code flow as if nothing exceptional happened. See also Where do I have to place the JDBC driver for Tomcat's connection pool? and Submitting form to Servlet which interacts with database results in blank page.

2. Or, JDBC URL is in wrong syntax

You need to ensure that the specified JDBC URL is conform the JDBC driver documentation and keep in mind that it's usually case sensitive. When the JDBC URL does not return true for Driver#acceptsURL() for any of the loaded drivers, then you will also get exactly this exception.

In case of PostgreSQL it is documented here.

With JDBC, a database is represented by a URL (Uniform Resource Locator). With PostgreSQL®, this takes one of the following forms:

  • jdbc:postgresql:database
  • jdbc:postgresql:/
  • jdbc:postgresql://host/database
  • jdbc:postgresql://host/
  • jdbc:postgresql://host:port/database
  • jdbc:postgresql://host:port/

In case of MySQL it is documented here.

This is the generic format of the connection URL:

protocol//[hosts][/database][?properties]

This is an example of a simple single-host connection URL:

jdbc:mysql://host1:33060/sakila

In case of Oracle it is documented here.

The Thin driver offers these kinds of URL formats for all of them:

SID (no longer recommended by Oracle to be used):

jdbc:oracle:thin:[<user>/<password>]@<host>[:<port>]:<SID>

Services:

jdbc:oracle:thin:[<user>/<password>]@//<host>[:<port>]/<service>

TNSNames:

jdbc:oracle:thin:[<user>/<password>]@<TNSName>


See also:

Phantasmal answered 16/12, 2009 at 0:28 Comment(6)
Thanks guys! Sorry 1st attempt wasn't in OP, just jdbc:postgresql:mmas (and I'd tried others!). Sadly, with araqnid's URL, same result. Last night I swapped tablib stuff for (ick) embedded Java, and that works fine: try { Class.forName("org.postgresql.Driver").newInstance(); con = DriverManager.getConnection("jdbc:postgresql:mmas","mmas","passwd"); stmt = con.createStatement(); rs = stmt.executeQuery("select yada yada"); if (rs != null && rs.next()) { // reap fame, fortune, glory, babes Jakarta example was w/taglibs, so I started that way.Shippy
Ah. Comments not so much w/the code formatting. Ahem. Is my newbie showing? (ZIIP!) Anyway, the Jakarta example was all about using the <sql:query> syntax instead of just embedding Java code, and I agree that's a much much cleaner way to do it. One should not need to explicitly call forName() and getConnection(), right? But the old ugly hack-the-driver-code-in-the-presentation-layer method worked just fine, first try. So I'm baffled, but now it's more of a maintenance/aesthetics issue than "This is broken, fix it or brush up on your burger-flipping skills."Shippy
IMHO using the sql taglib is only slightly better than doing JDBC in scriptlets... much prefer a controller/view pattern where the db stuff is done upfront and the JSP just displays stuff. Each to their own though, and using sql:query keeps things simple :) (ish)Theophany
I have never said that I agree with using JSTL SQL taglib, but that's not the subject where this topic is about.Phantasmal
Thanks, your JDBC connection string formats were extremely helpful!Eclogue
For me this meant the driver I was including wasn't found in maven, but wasn't throwing an error (that I could find). It wasn't until I looked in my .m2 folder that I saw the jar wasn't there.Sundaysundberg
I
22

I've forgot to add the PostgreSQL JDBC Driver into my project (Mvnrepository).

Gradle:

// http://mvnrepository.com/artifact/postgresql/postgresql
compile group: 'postgresql', name: 'postgresql', version: '9.0-801.jdbc4'

Maven:

<dependency>
    <groupId>postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>9.0-801.jdbc4</version>
</dependency>

You can also download the JAR and import to your project manually.

Intermolecular answered 17/7, 2018 at 14:25 Comment(0)
T
16
url="jdbc:postgresql//localhost:5432/mmas"

That URL looks wrong, do you need the following?

url="jdbc:postgresql://localhost:5432/mmas"
Theophany answered 15/12, 2009 at 23:56 Comment(0)
G
12

I faced the similar issue. My Project in context is Dynamic Web Project(Java 8 + Tomcat 8) and error is for PostgreSQL Driver exception: No suitable driver found

It got resolved by adding Class.forName("org.postgresql.Driver") before calling getConnection() method

Here is my Sample Code:

try {
            Connection conn = null;
            Class.forName("org.postgresql.Driver");
            conn = DriverManager.getConnection("jdbc:postgresql://" + host + ":" + port + "/?preferQueryMode="
                    + sql_auth,sql_user , sql_password);
        } catch (Exception e) {
            System.out.println("Failed to create JDBC db connection " + e.toString() + e.getMessage());
        }
Gilead answered 30/4, 2018 at 10:1 Comment(0)
D
3

I found the followig tip helpful, to eliminate this issue in Tomcat -

be sure to load the driver first doing a Class.forName(" org.postgresql.Driver"); in your code.

This is from the post - https://www.postgresql.org/message-id/[email protected]

The jdbc code worked fine as a standalone program but, in TOMCAT it gave the error -'No suitable driver found'

Devaney answered 19/1, 2018 at 15:52 Comment(2)
Please no link only answers - describe briefly what is behind that!Twana
A link to a solution is welcome, but please ensure your answer is useful without it: add context around the link so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. Answers that are little more than a link may be deleted.Exergue
H
3

Summary:

  • Soln2 (recommend)::

    • 1 . put mysql-connector-java-8.0.28.jar file in the <where you install your Tomcat>/lib.
  • Soln1::

    • 1 . put mysql-connector-java-8.0.28.jar file in the WEB-INF/lib.
    • 2 . use Class.forName("com.mysql.cj.jdbc.Driver"); in your Servlet Java code.

Soln1 (Ori Ans) //-20220304

In short:

  1. make sure you have the mysql-connector-java-8.0.28.jar file in the WEB-INF/lib
  2. make sure you use the Class.forName("com.mysql.cj.jdbc.Driver");

jar & class for jdbc connect


additional notes (not important), base on my trying (could be wrong)::

  • 1.1 putting the jar directly inside the Java build path doesnt work

  • 1.2. putting the jar in Data management > Driver Def > MySQL JDBC Driver > then add it as library to Java Build path doesnt work.

  • 1.3 => it has to be inside the WEB-INF/lib (I dont know why)

  • 1.4 using version mysql-connector-java-8.0.28.jar works, only version 5.1 available in Eclipse MySQL JDBC Driver setting doesnt matter, ignore it.

    <see How to connect to MySql 8.0 database using Eclipse Database Management Perspective >

  •     Class.forName("com.mysql.cj.jdbc.Driver");
        Class.forName("com.mysql.jdbc.Driver");
    

    both works, but the Class.forName("com.mysql.jdbc.Driver"); is deprecated.

    Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
    

    <see https://www.yawintutor.com/no-suitable-driver-found-for-jdbcmysql-localhost3306-testdb/ >

  • If you want to connect to a MySQL database, you can use the type-4 driver named Connector/} that's available for free from the MySQL website. However, this driver is typically included in Tomcat's lib directory. As a result, you don't usually need to download this driver from the MySQL site.

    -- Murach’s Java Servlets and JSP

    I cant find the driver in Tomcat that the author is talking about, I need to use the mysql-connector-java-8.0.28.jar. <(striked-out) see updated answer soln2 below>

  • If you're working with an older version of Java, though, you need to use the forName method of the Class class to explicitly load the driver before you call the getConnection method

    Even with JDBC 4.0, you sometimes get a message that says, "No suitable driver found." In that case, you can use the forName method of the Class class to explicitly load the driver. However, if automatic driver loading works, it usually makes sense to remove this method call from your code.

    How to load a MySQL database driver prior to JDBC 4.0

    Class.forName{"com.mysql.jdbc.Driver");

    -- Murach’s Java Servlets and JSP

    I have to use Class.forName("com.mysql.cj.jdbc.Driver"); in my system, no automatic class loading. Not sure why. <(striked-out) see updated answer soln2 below>

  • When I am using a normal Java Project instead of a Dynamic Web Project in Eclipse,

    I only need to add the mysql-connector-java-8.0.28.jar to Java Build Path directly,

    then I can connect to the JDBC with no problem.

    However, if I am using Dynamic Web Project (which is in this case), those 2 strict rules applies (jar position & class loading).

    <see TOMCAT ON ECLIPSE java.sql.SQLException: No suitable driver found for jdbc:mysql >


Soln2 (Updated Ans) //-20220305_12

In short:

  • 1 . put mysql-connector-java-8.0.28.jar file in the <where you install your Tomcat>/lib.

    eg: G:\pla\Java\apache-tomcat-10.0.16\lib\mysql-connector-java-8.0.28.jar

    (and for an Eclipse Dynamic Web Project, the jar will then be automatically put inside in your project's Java build path > Server Runtime [Apache Tomcat v10.0].)

put jar in Tomcat/lib


Additional notes::

for soln1::

  1. put mysql-connector-java-8.0.28.jar file in the WEB-INF/lib.
  2. use Class.forName("com.mysql.cj.jdbc.Driver"); in your Servlet Java code.

this will create an WARNING:

WARNING: The web application [LearnJDBC] appears to have started a thread named [mysql-cj-abandoned-connection-cleanup] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:

<see The web application [] appears to have started a thread named [Abandoned connection cleanup thread] com.mysql.jdbc.AbandonedConnectionCleanupThread >

and that answer led me to soln2.

for soln2::

    1. put mysql-connector-java-8.0.28.jar file in the <where you install your Tomcat>/lib.

    this will create an INFO:

    INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
    
  • you can just ignore it.

    <see How to fix "JARs that were scanned but no TLDs were found in them " in Tomcat 9.0.0M10 >

  • (you should now understand what Murach’s Java Servlets and JSP was talking about: the jar in Tomcat/lib & the no need for Class.forName("com.mysql.cj.jdbc.Driver");)

  • to kinda fix it //-20220307_23

    Tomcat 8.5. Inside catalina.properties, located in the /conf directory set: tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\*.jar

    How to fix JSP compiler warning: one JAR was scanned for TLDs yet contained no TLDs?

    skip scan in Tomcat/lib jar

Heathheathberry answered 5/3, 2022 at 4:30 Comment(0)
A
2

Run java with CLASSPATH environmental variable pointing to driver's JAR file, e.g.

CLASSPATH='.:drivers/mssql-jdbc-6.2.1.jre8.jar' java ConnectURL

Where drivers/mssql-jdbc-6.2.1.jre8.jar is the path to driver file (e.g. JDBC for for SQL Server).

The ConnectURL is the sample app from that driver (samples/connections/ConnectURL.java), compiled via javac ConnectURL.java.

Ashore answered 30/7, 2019 at 16:6 Comment(0)
M
2

No matter how old this thread becomes, people would continue to face this issue.

My Case: I have the latest (at the time of posting) OpenJDK and maven setup. I had tried all methods given above, with/out maven and even solutions on sister posts on StackOverflow. I am not using any IDE or anything else, running from bare CLI to demonstrate only the core logic.

Here's what finally worked.

  • Download the driver from the official site. (for me it was MySQL https://www.mysql.com/products/connector/). Use your flavour here.
  • Unzip the given jar file in the same directory as your java project. You would get a directory structure like this. If you look carefully, this exactly relates to what we try to do using Class.forName(....). The file that we want is the com/mysql/jdbc/Driver.class

https://static.mcmap.net/file/mcmap/ZG-AbGLDKwfpKnMAWVMrKmltX1ywKmMva3/KG1jY.png

  • Compile the java program containing the code.
javac App.java
  • Now load the director as a module by running
java --module-path com/mysql/jdbc -cp ./ App

This would load the (extracted) package manually, and your java program would find the required Driver class.


  • Note that this was done for the mysql driver, other drivers might require minor changes.
  • If your vendor provides a .deb image, you can get the jar from /usr/share/java/your-vendor-file-here.jar
Mcdade answered 17/10, 2020 at 8:59 Comment(0)
W
1

It might be worth noting that this can also occur when Windows blocks downloads that it considers to be unsafe. This can be addressed by right-clicking the jar file (such as ojdbc7.jar), and checking the 'Unblock' box at the bottom.

Windows JAR File Properties Dialog:
Windows JAR File Properties Dialog

Woolf answered 10/5, 2017 at 20:55 Comment(0)
T
1

As well as adding the MySQL JDBC connector ensure the context.xml (if not unpacked in the Tomcat webapps folder) with your DB connection definitions are included within Tomcats conf directory.

Tuatara answered 29/6, 2017 at 16:7 Comment(0)
R
1

A very silly mistake which could be possible resulting is adding of space at the start of the JDBC URL connection.

What I mean is:-

suppose u have bymistake given the jdbc url like

String jdbcUrl=" jdbc:mysql://localhost:3306/web_customer_tracker?useSSL=false&serverTimeZone=UTC";

(Notice there is a space in the staring of the url, this will make the error)

the correct way should be:

String jdbcUrl="jdbc:mysql://localhost:3306/web_customer_tracker?useSSL=false&serverTimeZone=UTC";

(Notice no space in the staring, you may give space at the end of the url but it is safe not to)

Rothwell answered 20/4, 2019 at 7:44 Comment(0)
Z
0

I was using jruby, in my case I created under config/initializers

postgres_driver.rb

$CLASSPATH << '~/.rbenv/versions/jruby-1.7.17/lib/ruby/gems/shared/gems/jdbc-postgres-9.4.1200/lib/postgresql-9.4-1200.jdbc4.jar'

or wherever your driver is, and that's it !

Zipper answered 14/2, 2017 at 19:47 Comment(0)
W
0

I had this exact issue when developing a Spring Boot application in STS, but ultimately deploying the packaged war to WebSphere(v.9). Based on previous answers my situation was unique. ojdbc8.jar was in my WEB-INF/lib folder with Parent Last class loading set, but always it says it failed to find the suitable driver.

My ultimate issue was that I was using the incorrect DataSource class because I was just following along with online tutorials/examples. Found the hint thanks to David Dai comment on his own question here: Spring JDBC Could not load JDBC driver class [oracle.jdbc.driver.OracleDriver]

Also later found spring guru example with Oracle specific driver: https://springframework.guru/configuring-spring-boot-for-oracle/

Example that throws error using org.springframework.jdbc.datasource.DriverManagerDataSource based on generic examples.

@Config
@EnableTransactionManagement
public class appDataConfig {
 \* Other Bean Defs *\
    @Bean
    public DataSource dataSource() {
        // configure and return the necessary JDBC DataSource
        DriverManagerDataSource dataSource = new DriverManagerDataSource("jdbc:oracle:thin:@//HOST:PORT/SID", "user", "password");
        dataSource.setSchema("MY_SCHEMA");
        return dataSource;
    }
}

And the corrected exapmle using a oracle.jdbc.pool.OracleDataSource:

@Config
@EnableTransactionManagement
public class appDataConfig {
/* Other Bean Defs */
@Bean
    public DataSource dataSource() {
        // configure and return the necessary JDBC DataSource
        OracleDataSource datasource = null;
        try {
            datasource = new OracleDataSource();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        datasource.setURL("jdbc:oracle:thin:@//HOST:PORT/SID");
        datasource.setUser("user");
        datasource.setPassword("password");

        return datasource;
    }
}
Wexford answered 19/7, 2017 at 20:31 Comment(0)
C
0

I was having the same issue with mysql datasource using spring data that would work outside but gave me this error when deployed on tomcat.

The error went away when I added the driver jar mysql-connector-java-8.0.16.jar to the jres lib/ext folder

However I did not want to do this in production for fear of interfering with other applications. Explicity defining the driver class solved this issue for me

    spring.datasource.driver-class-name: com.mysql.cj.jdbc.Driver
Chieftain answered 14/5, 2019 at 19:22 Comment(0)
L
0

In my case I was working on a Java project with Maven and encountered this error. In your pom.xml file make sure you have this dependencies

<dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.11</version>
    </dependency>
  </dependencies>

and where you create connection have something like this

public Connection createConnection() {
        try {
            String url = "jdbc:mysql://localhost:3306/yourDatabaseName";
            String username = "root"; //your my sql username here
            String password = "1234"; //your mysql password here

            Class.forName("com.mysql.cj.jdbc.Driver");
            return DriverManager.getConnection(url, username, password);
        } catch (SQLException | ClassNotFoundException e) {
            e.printStackTrace();
        }

        return null;
    }
Luttrell answered 26/5, 2020 at 19:42 Comment(2)
You shouldn't need to call Class.forName. DriverManager should be able to find it.Tripp
You may be right. Java is not my main coding language.Luttrell
T
0

You will get this same error if there is not a Resource definition provided somewhere for your app -- most likely either in the central context.xml, or individual context file in conf/Catalina/localhost. And if using individual context files, beware that Tomcat freely deletes them anytime you remove/undeploy the corresponding .war file.

Topgallant answered 18/9, 2020 at 21:40 Comment(0)
B
0

For me the same error occurred while connecting to postgres while creating a dataframe from table .It was caused due to,the missing dependency. jdbc dependency was not set .I was using maven for the build ,so added the required dependency to the pom file from maven dependency

jdbc dependency

Beryllium answered 27/2, 2021 at 5:4 Comment(0)
H
0

For me adding below dependency to pom.xml file just solved like magic! I had no mysql connector dependency and even adding mssql jdbc jar file to build path did not work either.

    <dependency> 
        <groupId>com.microsoft.sqlserver</groupId>
        <artifactId>mssql-jdbc</artifactId>
        <version>9.4.0.jre11</version>
    </dependency>
Helfand answered 23/9, 2021 at 18:38 Comment(1)
Adding this alone just provides the dependencies at compile time. You'll still need a shaded JAR or manually add the driver to the classpath to make it available at runtimeParson
D
0

I ran into the same error. In my case, the JDBC URL was correct, but the issue was with classpath. However, adding MySQL connector's JAR file to the -classpath or -cp (or, in the case of an IDE, as a library) doesn't resolve the issue. So I will have to move the JAR file to the location of Java bytecode and run java -cp :mysql_connector.jar to make this work. If someone runs into the same issue as mine, I'm leaving this here.

Delocalize answered 26/3, 2022 at 4:48 Comment(0)
O
0

faced same issue. in my case ':' colon before '//' (jdbc:mysql://localhost:3306/dbname) was missing, and it just fixed the problem. make sure : and // are placed properly.

Officeholder answered 25/5, 2022 at 18:46 Comment(0)
M
0

I faced the same exception but on the H2 database and it appeared because of my initial request object manipulation in doFilter. I did it cuz I needed to read the Body of the request multiple times, but for some reason, it broke the connection to the H2 console. So this is what I did, that fixed this issue for me:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    if (((HttpServletRequest) request).getRequestURI().startsWith("/h2-console/")) {
        chain.doFilter(request, response);
        return;
    }
    RepeatableHttpServletRequestWrapper wrappedRequest = new RepeatableHttpServletRequestWrapper((HttpServletRequest) request);
    chain.doFilter(wrappedRequest, response);
}
Misha answered 25/9, 2023 at 2:1 Comment(0)
S
0

If you're using Maven and packaging your project into war, you should notice whether the jar is successfully downloaded in your Maven repo, after checking all above methods I finally found my 8.0.33 version of Mysql is downloaded failed like this: except for jar file, all other files like repositories, sha1 and pom are downloaded successfully.

So if you are Maven user, don't forget to check your repo!

Sherlynsherm answered 20/2 at 14:50 Comment(0)
M
-2

I encountered this issue by putting a XML file into the src/main/resources wrongly, I deleted it and then all back to normal.

Mongeau answered 26/3, 2019 at 2:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.