0

I am building an workflow for Corda. I want to use the Hikari connection pool library for connecting to MySql database. I AM NOT trying to replace the, ledger H2 database. This database is for storing/retrieving some information, which is not needed in the ledger. I am able to connect to MySql WITHOUT Hikari. However when I use Hikari, I get an error. java.lang.ClassNotFoundException: com.mysql.cj.jdbc.MysqlConnectionPoolDataSource

I have tested the Hikari code, as a standalone jar file. It works fine. It is a combination of the way corda loads and runs the jar files, inside cordapps directory, which is causing the issue. Since the class is part of the jar. This seems it a little off

I have added the MySql dependency, inline with what is mentioned in https://docs.corda.net/cordapp-build-systems.html#setting-your-dependencies I am also able to connect to the MySql DB, if I am not using Hikari.

I explored the cordapp jar . And I could see that the requisite jar is present inside the cordapp jar.

Gradle dependencies for the cordapp

dependencies {
    testCompile "junit:junit:$junit_version"

    // Corda dependencies.
    cordaCompile "$corda_release_group:corda-core:$corda_release_version"
    cordaRuntime "$corda_release_group:corda:$corda_release_version"

    testCompile "$corda_release_group:corda-node-driver:$corda_release_version"
    runtime "mysql:mysql-connector-java:8.0.11"

    cordaCompile "com.zaxxer:HikariCP:2.5.1"

    // CorDapp dependencies.
    cordapp project(":contracts")
}

Sample code

public class DataSource {
    private static final Logger logger = LoggerFactory.getLogger(DataSource.class);
    private static HikariConfig config = new HikariConfig();
    private static HikariDataSource ds;

    static {
        try {
            logger.info("Connecting with connection pool datasource");
            config.setDataSourceClassName("com.mysql.cj.jdbc.MysqlConnectionPoolDataSource");
            config.addDataSourceProperty("useSSL", "false");
            config.addDataSourceProperty("user", "username");
            config.addDataSourceProperty("password", "password");
            config.addDataSourceProperty("serverName", "localhost");
            config.addDataSourceProperty("useSSL", "false");
            config.addDataSourceProperty("port",Integer.parseInt("3306"));
            config.addDataSourceProperty("cachePrepStmts", "true");
            config.addDataSourceProperty("prepStmtCacheSize", "250");
            config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
            config.addDataSourceProperty("requireSSL", "false");
            config.addDataSourceProperty("serverTimezone", "UTC");
            config.addDataSourceProperty("useServerPrepStmts", "true");
            config.addDataSourceProperty("allowPublicKeyRetrieval", "true");
            config.addDataSourceProperty("databaseName", "database");
            config.setPoolName("Hikari-MySql Pool Name");
            logger.error("-- Create Hikari Datasource with config {} --", config);
            ds = new HikariDataSource(config);
        } catch (Throwable t) {
            logger.error("Error Occurred during Datasource Initializaiton", t);
            throw t;
        }
    }

    private DataSource() {
    }

    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
}


public class MySqlConnection {
    static private final Logger logger = LoggerFactory.getLogger(MySqlConnection.class);
    public Connection getMySqlConnection() {
        Connection conn = null;
        try {

            conn = DataSource.getConnection();

            logger.info("------------> Got conne :: " + conn);
        } catch (SQLException e) {
            logger.error("SQLException :: " + e);
        }
        return conn;
    }
}
public class DataSourceTest {
    static private final Logger logger = LoggerFactory.getLogger(DataSourceTest.class);
    public static void main(String[] args) {
        MySqlConnection mySqlConnection = new MySqlConnection();
        Connection conn = null;
        try {

            conn = mySqlConnection.getMySqlConnection();

            logger.info("------------> Got connection :: " + conn);

            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("{some select statement}");
        } catch (SQLException e) {
            logger.error("SQLException :: " + e);
        }
    }
}

Exception:

Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: com.mysql.cj.jdbc.MysqlConnectionPoolDataSource
    at com.zaxxer.hikari.util.UtilityElf.createInstance(UtilityElf.java:90) ~[HikariCP-2.5.1.jar:?]
    at com.zaxxer.hikari.pool.PoolBase.initializeDataSource(PoolBase.java:314) ~[HikariCP-2.5.1.jar:?]
    at com.zaxxer.hikari.pool.PoolBase.<init>(PoolBase.java:108) ~[HikariCP-2.5.1.jar:?]
    at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:99) ~[HikariCP-2.5.1.jar:?]
    at com.zaxxer.hikari.HikariDataSource.<init>(HikariDataSource.java:71) ~[HikariCP-2.5.1.jar:?]

If I run the code from a main class inside a jar, it works. But it does not work from inside a cordapp

Ori Marko
  • 56,308
  • 23
  • 131
  • 233
pointerness
  • 323
  • 3
  • 12
  • Instead of Hikari I tried using the appache commons dbcp connection pool. But can't even build the jar when I try that. I get an error " ensure the 'cordapp.signing.options' entry contains correct keyStore configuration, or disable signing by 'cordapp.signing.enabled false'". If I change the dependency to cordaCompile, it compiles but still does not work – pointerness Jun 26 '19 at 09:32

2 Answers2

0

In MySQL for HikariCP use setJdbcUrl instead of setDataSourceClassName

config.setJdbcUrl("jdbc:mysql://localhost:3306/simpsons");

The MySQL DataSource is known to be broken with respect to network timeout support. Use jdbcUrl configuration instead.

Community
  • 1
  • 1
Ori Marko
  • 56,308
  • 23
  • 131
  • 233
  • This is not related. The code works when deployed as a springboot app. This is something specific to the corda runtime – pointerness Jul 04 '19 at 15:14
0

Check your dependency tree. I think you have some collision with "mysql-connector-java" dependency, which cause mess in class loader.

shpitc
  • 305
  • 2
  • 5