Search code examples
javajavafxjarjpackage

JPackage (incubator) and SQLite database problem


I could use some help again, out of ideas. :( I am making JavaFX application that will use SQLite database. OpenJDK 14 with OpenJFX14 is used. In my Eclipse all is working perfectly. I tried for test to make installer with JPackage and that worked too. When I start installed application it starts ok, but for some reason refuse to connect with database.

Here is my project structure:

enter image description here

I have a button where when Stage is loaded I check connection. It is in file PocetnaController:

    //testiranje konekcije nakon instalacije
@FXML
public void btnObracunClick(ActionEvent event) {
    lblStatus.setText(model.povezanaBaza());
}

And this is code from PocetnaModel that is called:

    public String povezanaBaza() {
    this.konekcija = Konekcija.poveziBazu();
    return (this.konekcija != null) ? "Веза са базом успостављена" : "Повезивање са базом није успело.";
}

When true it returns "Database connection established" in my language and when false "Connection with database failed".

I repeat, in Eclipse all works well. But, when start installed app I am getting "Connection with database failed". So connection returning null for some reason.

My db file is coppied by JPackage in /app folder. I tried to copy manualy Porez.db to root folder where *.exe is. Strange thing, status label doesn't change in that case. And it should, it must return true or false, don't understand that.

This is stage look when started:

enter image description here

Even if I rename database file in /app folder, so it can't be found my connection still returning false and update status accordingly which is ok.

Here is entire Konekcija file who has a role to take care of connection:

    public static Connection poveziBazu() {
    File baza = new File("Porez.db");
    try {
        if (baza.exists()) {
            Connection con = DriverManager.getConnection("jdbc:sqlite:Porez.db");
            return con;
        } else {
            return null;
        }
    } catch (Exception e) {
        return null;
    }
}

My first suspect is something is wrong with my created JAR, but can't be sure. Makes no sense to me to work in Eclipse and no after install.


Solution

  • There are several places you need to check and possibly fix if you ran jpackage with:

     jpackage --name SQLiteTest --input C:\Users\Dalibor\Documents\NetBeansProjects\SQLiteTest\dist --main-jar SQLiteTest.jar --runtime-image hello\myjre
    

    Turn on Windows console so that you can see the error messages it is providing - use jpackage --win-console.

    After installing your jpackaged release, check the release directory structure.

    1. Make sure it contains the sqllite-jdbc.jar file. If NOT found fix your --input directories to add the jar.

    2. Check the app\xxx.cfg file for your generated application. It must contain all your jar dependencies including sqlite-jdbc.jar such as:

      app.classpath=$ROOTDIR\app\jars\xxxx.jar;$ROOTDIR\app\jars\sqlite-jdbc.jar
      
    3. Check that the jlink command you used to build the runtime image hello\myjre includes --add-modules java.sql to combine with the required SQL dependencies.

    4. The app structure created by the installer that jpackage builds is different to the structure you have in Eclipse - files are under app directory, and most importantly the release is only editable with Administrator privileges. Use System property java.launcher.path to adjust the location of the SqlLite database to an editable location and don't mask exceptions:

       public static Connection poveziBazu() {
           File baza = new File("Porez.db");
           String jhome = System.getProperty("java.launcher.path");
           if (jhome != null) {
               baza = new File(System.getProperty("user.home"), "Porez.db");
           }
           System.out.println("Connecting to "+baza.getAbsolutePath()+" exists()="+baza.exists());
           try {
               return DriverManager.getConnection("jdbc:sqlite:"+baza.getAbsolutePath());
           } catch (Exception e) {
               System.out.println("Failed connecting to: "+baza);
               throw new RuntimeException("Failed to open or create db: "+baza, e);
           }
       }