当我使用H2数据库作为嵌入式设备时,Gluon应用程序无法在ios上加载FXML

时间:2018-07-12 09:13:52

标签: h2 gluon robovm

我已经创建了使用H2数据库作为嵌入式模式的Gluon移动应用程序。在Window,Mac,Android上运行正常。但不幸的是,它无法在iOS模拟器上运行(fxml无法加载)。

如果我注释了要加载驱动程序的代码,则用户界面将正确加载。

代码加载驱动程序

float f = 3.14f;
uint32_t u = pseudo_cast<uint32_t>(f);

我也检查了关于this group的讨论,但没有运气。

我的代码:

//load the driver class
        try {
            Class.forName(DBCONFIG.DB_DRIVER).newInstance();
        } catch (ClassNotFoundException e) {
            System.out.println("class not found");
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            System.out.println("IllegalAccessException");
            e.printStackTrace();
        } catch (InstantiationException e) {
            System.out.println("InstantiationException");
            e.printStackTrace();
        }

Build.gradle

private void createDB() {
        status.getItems().add("Creating a Database with H2");
        //Get the private storage directory from each platform to save database files;
        private_dir = GluonServices.getPrivateDirectory();
        System.out.println("path="+private_dir.toString());
        //load the driver class
        try {
            Class.forName(DBCONFIG.DB_DRIVER).newInstance();
        } catch (ClassNotFoundException e) {
            System.out.println("class not found");
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            System.out.println("IllegalAccessException");
            e.printStackTrace();
        } catch (InstantiationException e) {
            System.out.println("InstantiationException");
            e.printStackTrace();
        }
        //Build Database connection string to the correct file that we create depending on each platform;
        dbUrl = String.format(dbUrl,private_dir.toString(),DBCONFIG.DB_NAME);
        System.out.println("dbUrl="+dbUrl);

        List<Contact> list = new ArrayList<>();
        try {
            //Connect to database from the giving db url: If file doesn't exist H2 will automatically create it.
            System.out.println("getConnection=");
            connection = DriverManager.getConnection(dbUrl);
            status.getItems().add("Connection established: " + dbUrl);

            //create the statement object
            stmt = connection.createStatement();
            stmt.setQueryTimeout(30);
            String sql="DROP TABLE IF EXISTS contact;\n" +
                    "CREATE TABLE contact(\n" +
                    "        Id INT NOT NULL AUTO_INCREMENT,\n" +
                    "        Name VARCHAR(255) NOT NULL,\n" +
                    "        Email VARCHAR(255) NOT NULL UNIQUE,\n" +
                    "        PRIMARY KEY (ID)\n" +
                    ");";

            //execute query
            stmt.executeUpdate(sql);
            status.getItems().add("Starting Adding testing data and read it from database");
            stmt.executeUpdate("INSERT INTO CONTACT(NAME,EMAIL) VALUES('Sovandara LENG','lengsovandara@gmail.com')");
            stmt.executeUpdate("INSERT INTO CONTACT(NAME,EMAIL) VALUES('Chamroeun PANG','Chamroeun.p@gmail.com')");
            stmt.executeUpdate("INSERT INTO CONTACT(NAME,EMAIL) VALUES('Sovanarith LENG','lengsovanarith@gmail.com')");

            status.getItems().add("Retrieving records from table 'Contact'...");
            rs = stmt.executeQuery("SELECT * FROM CONTACT");
            while (rs.next()) {
                int id = rs.getInt("Id");
                String name = rs.getString("NAME");
                String email = rs.getString("Email");
                status.getItems().add(String.format("Record Added:{id: %s, name: %s, email: %s}",id,name,email));
                list.add(new Contact(id,name, email));
            }
            status.getItems().add("End creating table and retrieving records");
            if(list.size()>0)
                status.getItems().add("Record has beed added");

            System.out.println("Table Created");
            status.getItems().add("Table Created");

        } catch (Exception e) {
            status.getItems().add("SQL error  " + e.getMessage());
            e.printStackTrace();
        }finally {
            try {
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException ex) {
                status.getItems().add("SQL error " + ex.getSQLState());
            }
            try {
                if (stmt != null) {
                    stmt.close();
                }
            } catch (SQLException ex) {
                status.getItems().add("SQL error " + ex.getSQLState());
            }
        }
    }

登录

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.3.12'
        classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.0'
    }
}

apply plugin: 'org.javafxports.jfxmobile'
apply plugin: 'com.github.johnrengelman.shadow'

repositories {
    jcenter()
    maven {
        url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
    }
}

mainClassName = 'com.khmerdev.GluonApplication'

dependencies {
    compile 'com.gluonhq:charm:5.0.0'
    compile files('libs/h2-1.4.196.jar')
}
// Add desktop dependencies to the task
shadowJar {
    configurations = [project.configurations.desktopRuntime]
}

jfxmobile {
    downConfig {
        version = '3.8.0'
        // Do not edit the line below. Use Gluon Mobile Settings in your project context menu instead
        plugins 'display', 'lifecycle', 'statusbar', 'storage'
    }
    android {
        manifest = 'src/android/AndroidManifest.xml'
    }
    ios {
        infoPList = file('src/ios/Default-Info.plist')
        forceLinkClasses = [
                'com.khmerdev.**.*',
                'com.gluonhq.**.*',
                'javax.annotations.**.*',
                'javax.inject.**.*',
                'javax.json.**.*',
                'org.glassfish.json.**.*'
        ]
    }
}

请检查以下屏幕截图

Window

Tablet

Mac

iPad

1 个答案:

答案 0 :(得分:1)

在iOS上运行H2时,该问题与forceLinkClasses无关(反正可能是必需的),但与javax.management包的缺少实现有关,如您在日志中所见:

java.lang.NoClassDefFoundError: java/lang/management/ManagementFactory

这意味着Java软件包的RoboVM实现未添加java.lang.management / javax.management类。

由于H2是开源的,因此您可以删除JMX引用并使用自定义版本,或者我们可以尝试绕过iOS上的问题,从而提供缺少类的虚拟实现。

我只测试了GluonSQLite示例(但是使用H2而不是SQLite),添加了以下两个类:

java.lang.management.ManagementFactory

package java.lang.management;

import java.util.ArrayList;
import java.util.List;
import javax.management.MBeanServer;
import javax.management.ThreadMXBean;
import javax.management.GarbageCollectorMXBean;

public class ManagementFactory {

    public static synchronized MBeanServer getPlatformMBeanServer() {
        return new MBeanServer();
    }

    public static ThreadMXBean getThreadMXBean() {
        return new ThreadMXBean();
    }

    public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans() {
        return new ArrayList<>();
    }

    public static OperatingSystemMXBean getOperatingSystemMXBean() {
        return new OperatingSystemMXBean();
    }
}

java.lang.managementOperatingSystemMXBean

package java.lang.management;

public class OperatingSystemMXBean {

    public String getName() {
        return "";
    }

    public String getArch() {
        return "";
    }

    public String getVersion() {
        return "";
    }

    public int getAvailableProcessors() {
        return 0;
    }

    public double getSystemLoadAverage() {
        return 0;
    }
}

和这三个空类:

package javax.management;
public class GarbageCollectorMXBean { }

package javax.management;
public class MBeanServer { }

package javax.management;
public class ThreadMXBean { }

并包括:'org.h2.**.*''javax.management.**.*'强制build.gradle文件上的LinkLinkClasses,该示例在iOS上成功运行(H2连接,数据库创建,插入,选择...)。