简体   繁体   中英

No suitable driver found for jdbc:sqlite on app image

I have a JavaFX app that connects to SQLite using

Connection connection = DriverManager.getConnection("jdbc:sqlite:data.sqlite");

I have the dependency for SQLite driver on my pom file:

<dependency>
    <groupId>org.xerial</groupId>
    <artifactId>sqlite-jdbc</artifactId>
    <version>3.32.3.2</version>
</dependency>

I can run the App smoothly using Maven Goals javafx:compile and javafx:run , everything works as expected and the app has no trouble querying the db. The data.sqlite file is created on the project's root folder (same folder as src/ and pom.xml ).

However, when I try to run an executable file built with jlink , I get the error described on the thread's title. First, I ran maven goal javafx:jlink . This generates some stuff at target/image/ . I navigated to target/image/bin and ran ./java -m <name-of-my-module>/<group-id>.App , which is the command for running the file I built. Then I get:

No suitable driver found for jdbc:sqlite:data.sqlite

And a NullPointerException because of the database init routines that try to access my database connection. How can I fix this? Thanks in advance.

EDIT: It seems that the solution has something to do with adding a Class.forName() statement before calling DriverManager.getConnection() . I tried doing the following:

Class.forName("org.sqlite.JDBC");
Connection connection = DriverManager.getConnection("jdbc:sqlite:data.sqlite");

By doing that, now the app renders, However. it still crashes. I get ClassNotFoundException: org.sqlite.JDBC . Any hints...?

I fear this will not work directly with jlink because as far as I have seen SQLite is not yet modularized. I have described an alternative approach here https://github.com/dlemmermann/JPackageScriptFX which also uses jlink internally but only to create a dedicated runtime. With this approach linking SQLite works. I know that because my own applications also use the exact same version of the SQLite driver without problems.

I was able to solve this by using Draque Thompson's Module Info Inject . Basically what the program does is creating a module-info.class for your .jar , letting JLink see it as a module. (Sorry if the explanation is lacking, I don't have deep knowledge of Java's module system).

So basically what I done was:

  1. Clone Module-Info-Inject and run it.
  2. Select the desired jar folder and click "Inject".
  3. On the generated module-info.class file, get the module's name. In my case it was sqlite.jdbc .
  4. Add the new module to my project's module-info.java .

The generated module-info.class file for SQLite driver:

module sqlite.jdbc {
    requires transitive java.logging;
    requires transitive java.sql;

    exports org.sqlite;
    exports org.sqlite.core;
    exports org.sqlite.date;
    exports org.sqlite.javax;
    exports org.sqlite.jdbc3;
    exports org.sqlite.jdbc4;
    exports org.sqlite.util;

    provides java.sql.Driver with org.sqlite.JDBC;
}

Requiring the module in my project's module-info.java :

module com.demo {
    requires sqlite.jdbc;

    / * ... * /

    exports pkg.app;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM