2
votes

I have two classes in one directory - test and main. Both must connect to the database via JDBC driver, which is connected via pom.xml.

The classes have the same connection settings, but the test class works fine, and the main class throws ClassNotFoundException: com.mysql.jdbc.Driver. I tried different versions of the connector, now it is the freshest (8.0.12).

I also tried to add the jar-file with the driver manually - the situation repeated. No more ideas.

test class:

package app.model;

import app.entities.StandartGame;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class DBTest {

private static final String USERNAME = "root";
private static final String PASSWORD = "root";
private static final String DATABASEURL = "jdbc:mysql://localhost:3306/test?serverTimezone=Europe/Moscow&useSSL=false";

public static void main(String[] args) {

    try {
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection connection = DriverManager.getConnection(DATABASEURL, USERNAME, PASSWORD);
        Statement statement = connection.createStatement();

        String thisName, thisGenre;
        double thisPrice;

        ResultSet resultSet = statement.executeQuery("select * from GameShop");
        List<StandartGame> games = new ArrayList<StandartGame>();

        while (resultSet.next()) {
            thisPrice = resultSet.getDouble("price");
            thisName = resultSet.getString("name");
            thisGenre = resultSet.getString("genre");

            StandartGame game = new StandartGame(thisName, thisPrice, thisGenre);
            games.add(game);
        }

        for (StandartGame game: games) {
            System.out.println(game.getName());
        }


    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (SQLException e) {
        e.printStackTrace();
    }
  }
}

main class:

package app.model;

import app.entities.StandartGame;
import java.sql.*;
import java.util.List;

public class SingletonModel {

private static SingletonModel model;

private static final String USERNAME = "root";
private static final String PASSWORD = "root";
private static final String DATABASEURL = "jdbc:mysql://localhost:3306/test?serverTimezone=Europe/Moscow&useSSL=false";

public static String driverPath = "com.mysql.cj.jdbc.Driver";
public static Connection connection;
public static Statement statement;

public static synchronized void addGames(StandartGame ... gamez) {
    try {

        Class.forName(driverPath);
        connection = DriverManager.getConnection(DATABASEURL, USERNAME, PASSWORD);
        statement = connection.createStatement();

        String thisName, thisGenre;
        double thisPrice;

        for (StandartGame stg : gamez) {
            thisName = stg.getName();
            thisGenre = stg.getGenre();
            thisPrice = stg.getPrice();
            statement.executeUpdate("insert into GameShop (name, genre, price) VALUE " +
                    "('"+thisName+"', '"+thisGenre+"', '"+thisPrice+"')");
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1309)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1138)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:291)
at app.model.SingletonModel.addGames(SingletonModel.java:50)
at app.servlets.AddServlet.doPost(AddServlet.java:35)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:844)
1
How are you launching your main class (web app)? From within an IDE? If so, which IDE are you using? If not, have you copied the JDBC .jar file to the classpath for the instance of Tomcat that you are using?Gord Thompson
Launch from IDEA. And now i'm used Maven dependency only, but earlier tried drop jar driver in near directory to main class. It was not working, like now.anabioze

1 Answers

1
votes

This is almost certainly related to how you have configured the code rather than the code itself. The exception is coming from Class.forName and using diff shows the strings you've quoted are the same (no sneaky homoglyphs or other typos in there).

The typical approach is to try the simplest thing that still fails. Minimal, Complete, and Verifiable example being the local Stack Overflow term for this.

Replacing your entire example code with this should show still the problem without all the other nonsense. You could use exactly the same code with an inlined literal string with copy-and-paste between the two, or reference the class directly.

Class<?> driverClass = com.mysql.cj.jdbc.Driver.class;

(You may have to correct the classpath for your Java source code compiler first.) Usually that can be replaced by directly constructing the driver.

java.sql.Driver driver = new com.mysql.cj.jdbc.Driver();

We've translated a runtime error into a compile time error. Win! Well, it'll probably end up as a link time error in this case.

Whichever, after that diversion, the exception shows that there is a problem with classpath at runtime. That may be something in the pom.xml - the MySQL driver must be visible in the classpath for running the web app.

You can deploy library classes along with your web app code. Alternatively there are other standard places to put libraries in web containers (see your documentation) that can be shared more widely and remove the overhead of reloading drivers when redeploying in a running container during development. JDBC drivers are just libraries of classes in jars (some have native components, but I believe these days that's largely limited to dodgy bridges to native interfaces).