0

I've been trying to run my Maven Kotlin Ktor project with command line. The project contains the MySQL configuration too. Every time I tried to hit the following command, I got the following error.

Here is my command.

kotlin -cp mysql-connector-java-8.0.30.jar:dev_meet_dev_api.jar MainClassKt

The dev_meet_dev_api.jar file is my project jar and mysql-connector-java-8.0.30 is for MySQL connection with the database. My project is dependent on MySQL connector that's why I added the external dependency for MySQL connector.

As soon I hit the above command on terminal I've got the following error.

Caused by: java.lang.ClassNotFoundException: java.sql.Driver
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)

Edit 1: Added the maven file.

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>spartons.com.devMeetdevApi</groupId>
    <artifactId>KtorTesting</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <kotlin.version>1.7.10</kotlin.version>
        <ktor.version>2.1.1</ktor.version>
        <junit.version>4.12</junit.version>
        <serialization.version>1.4.0</serialization.version>
        <coroutines.version>1.6.4</coroutines.version>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <kotlin.compiler.incremental>true</kotlin.compiler.incremental>
        <kotlin.compiler.jvmTarget>11</kotlin.compiler.jvmTarget>
        <kotlin.code.style>official</kotlin.code.style>
        <kotlin.compiler.incremental>true</kotlin.compiler.incremental>
    </properties>

    <dependencies>

        <!--   Kotlin language dependencies   -->

        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
            <version>${kotlin.version}</version>
            <scope>runtime</scope>
        </dependency>

        <!--   Kotlin's coroutines dependency   -->

        <dependency>
            <groupId>org.jetbrains.kotlinx</groupId>
            <artifactId>kotlinx-coroutines-core</artifactId>
            <version>${coroutines.version}</version>
        </dependency>

        <!--  Ktor dependencies   -->

        <dependency>
            <groupId>io.ktor</groupId>
            <artifactId>ktor-server-core-jvm</artifactId>
            <version>${ktor.version}</version>
        </dependency>
        <dependency>
            <groupId>io.ktor</groupId>
            <artifactId>ktor-server-jetty-jvm</artifactId>
            <version>${ktor.version}</version>
        </dependency>
        <dependency>
            <groupId>io.ktor</groupId>
            <artifactId>ktor-server-content-negotiation-jvm</artifactId>
            <version>${ktor.version}</version>
        </dependency>
        <dependency>
            <groupId>io.ktor</groupId>
            <artifactId>ktor-serialization-kotlinx-json-jvm</artifactId>
            <version>${ktor.version}</version>
        </dependency>
        <dependency>
            <groupId>io.ktor</groupId>
            <artifactId>ktor-server-status-pages-jvm</artifactId>
            <version>${ktor.version}</version>
        </dependency>
        <dependency>
            <groupId>io.ktor</groupId>
            <artifactId>ktor-server-cors-jvm</artifactId>
            <version>${ktor.version}</version>
        </dependency>

        <!--  Kotlin serialization version   -->

        <dependency>
            <groupId>org.jetbrains.kotlinx</groupId>
            <artifactId>kotlinx-serialization-json</artifactId>
            <version>${serialization.version}</version>
        </dependency>

        <!--  MySQL connector dependency   -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>

    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <finalName>dev_meet_dev_api</finalName>
        <plugins>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>${kotlin.version}</version>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <compilerPlugins>
                        <plugin>kotlinx-serialization</plugin>
                    </compilerPlugins>
                    <args>
                        <arg>-opt-in=kotlin.RequiresOptIn</arg>
                    </args>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-serialization</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.10.1</version>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-compile</id>
                        <phase>none</phase>
                    </execution>
                    <execution>
                        <id>default-testCompile</id>
                        <phase>none</phase>
                    </execution>
                </executions>
                <configuration>
                    <release>11</release>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.3.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <artifactSet>
                        <excludes>
                            <exclude>mysql:mysql-connector-java:jar:</exclude>
                        </excludes>
                    </artifactSet>
                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <exclude>META-INF/*.SF</exclude>
                                <exclude>META-INF/*.DSA</exclude>
                                <exclude>META-INF/*.RSA</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Edit 2: Added the java-11 modules enter image description here

P.S I'm using Java 11. Projects works fine if I try to run with the IntelliJ.

Ahsan Saeed
  • 701
  • 10
  • 22
  • How do you build your jar `dev_meet_dev_api.jar`? Any dependencies inside that jar? – qaziqarta Sep 15 '22 at 06:27
  • With IDE there's an option inside the IntelliJ to package the project into jar. – Ahsan Saeed Sep 15 '22 at 09:45
  • _"java.lang.ClassNotFoundException: java.sql.Driver"_ suggests you have bigger problems, as that class is included in Java itself. Maybe you are using a modular project that is missing a `requires java.sql;` statement? Please provide a [mre]. – Mark Rotteveel Sep 15 '22 at 12:31
  • 1
    @MarkRotteveel afaik, omitting a `requires java.sql;` would not be enough (the error would look different). You also need to configure a runtime environment that doesn’t have the `java.sql` module. – Holger Sep 15 '22 at 14:17
  • @Holger runtime environment path is already added. – Ahsan Saeed Sep 19 '22 at 06:20
  • 1
    The type `java.sql.Driver` is provided by the JDK, if the module is included. You can not add it via runtime environment paths. You can use `java --list-modules` to check whether the `java.sql` module is present. – Holger Sep 19 '22 at 07:01
  • @Holger java.sql module is already there. – Ahsan Saeed Sep 19 '22 at 07:30
  • 1
    Then, someone tried really hard to prevent the class loader from finding the built-in class… – Holger Sep 19 '22 at 12:14
  • 1
    Note that the line number `URLClassLoader.java:445` looks implausible for JDK 11, which suggests that this is not the installation which produced the failure. – Holger Sep 19 '22 at 12:39
  • 1
    Did you try `java -cp $KOTLIN_LIB/kotlin-stdlib.jar:...` as explained [here](https://stackoverflow.com/a/34513057/12763954)? – Olivier Sep 20 '22 at 07:34
  • Thanks, @Olivier it's working with this command --> `java -cp dev_meet_dev_api.jar:mysql-connector-java-8.0.30.jar MainClassKt`. – Ahsan Saeed Sep 21 '22 at 14:30
  • @Olivier I can't trace the actual error but for now, I'm gonna run my APIs. Also can you please post this as an answer so that I can approve it? – Ahsan Saeed Sep 21 '22 at 14:33

3 Answers3

2

You can do this directly in Maven! In your pom.xml add the driver as a dependency.

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
</dependency>

Then you shade the dependency into the jar

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.3</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <artifactSet>
                            <includes>
                                <include>mysql:mysql-connector-java</include>
                            </includes>
                        </artifactSet>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Then directly execute the jar. If this does not help may I know which Java version you are using?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
David
  • 164
  • 1
  • 11
  • I also found that quite often while searching (https://stackoverflow.com/questions/17484764), but it doesn't explain why java.sql.Driver is missing. This solution seems to be for com.mysql.jdbc.Driver. This could also be a cross-compile problem when you mix java and kotlin code (https://discuss.kotlinlang.org/t/noclassdeffound-with-kotlin-java-project/20458/12) – Cactusroot Sep 17 '22 at 12:39
  • I mean when you execute it via java -jar it should not be possible for kotlin to mess it up – David Sep 18 '22 at 13:21
  • @David if we only include the `mysql-connector` then all other dependencies will be excluding. – Ahsan Saeed Sep 19 '22 at 06:19
1

Kotlin applications need the Kotlin runtime to run (mainly kotlin-stdlib.jar). It can be included in the application jar or not.

If the runtime is not included, you must add it to the classpath:

java -cp /path/to/kotlin-stdlib.jar:app.jar MainClassKt

You can also use the kotlin script, which automatically adds it:

kotlin -cp app.jar MainClassKt

In your case, the runtime is included thanks to the maven-shade-plugin, so you can run the app like this:

java -cp mysql-connector-java-8.0.30.jar:dev_meet_dev_api.jar MainClassKt
Olivier
  • 13,283
  • 1
  • 8
  • 24
0

Possibility 1

It is possible that some dependency that you manually added has a different version of java.sql.Driver. It is overriding the java.sql.Driver dependency version that your code flow needs.

To debug if this is actually the cause of your problem, you can use IntelliJ maven dependency plugin. It can show if there is any conflict in dependency causing the needed class to not load. https://www.jetbrains.com/help/idea/work-with-maven-dependencies.html#maven_dependency_diagram

Also, please note that in my experience, If multiple dependencies are loading different versions of same class, then you may get different results in different setup, since order of class loading may differ. This can result in your code working in IntellijIdea, but not when running from terminal.

Possibility 2

Check if the jdbc driver version is compatible with java and database versions that you are using. Try upgrading or downgrading the jdbc version to see if that resolves issue.

Debug approach 1: if above ways don't fix the issue

Since you say that your code works in Intellij, start your application in debug mode and put a debug point in java.sql.Driver. See which the library which contains this class and the dependency which contains this library. That can help you debug the cause of problem.

Debug approach 2: if above ways don't fix the issue

Use remote debugging. Start your jar application in console with remote debug enabled.

Refer this on steps to do it. https://www.jetbrains.com/help/idea/tutorial-remote-debug.html#ecd9fef1

Using this, you can find the code flow and the cause of problem for program that runs in console.

I hope that this helps you.

Amol Limaye
  • 108
  • 1
  • 4