1

I am developing an embedded java application (jar) which consumed by Android application. (the Android device (API19) it's just the view, I imported the JAR with Gradle to my Android Studio's project).

I'm using H2 database (tested on Android) and I'm trying to use it with connection pool (tried C3P0 and HakiriCP).

Here is the jar pom file content (with HakiriCP):

<?xml version="1.0" encoding="UTF-8"?>
<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>com.app</groupId>
    <artifactId>reactor</artifactId>
    <version>1.0-SNAPSHOT</version>


    <properties>
        <log4j.version>1.2.15</log4j.version>
        <rx.version>1.3.8</rx.version>
        <dbh2.version>1.4.196</dbh2.version>
        <junit.version>4.7</junit.version>
        <json.version>20180813</json.version>
        <slf4j-log4j12.version>1.7.21</slf4j-log4j12.version>
        <log4j.version>1.2.17</log4j.version>
    </properties>

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>3.1.1</version>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
                            <overWriteReleases>false</overWriteReleases>
                            <overWriteSnapshots>false</overWriteSnapshots>
                            <overWriteIfNewer>true</overWriteIfNewer>
                            <includeScope>provided</includeScope>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.1.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <finalName>uber-${artifactId}-${version}</finalName>
                </configuration>
            </plugin>
        </plugins>
    </build>


    <dependencies>
        <!-- https://mvnrepository.com/artifact/io.reactivex/rxjava -->
        <dependency>
            <groupId>io.reactivex</groupId>
            <artifactId>rxjava</artifactId>
            <version>${rx.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>${dbh2.version}</version>
        </dependency>
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP-java7</artifactId>
            <version>2.4.13</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.json/json -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>${json.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j-log4j12.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j-log4j12.version}</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/log4j/apache-log4j-extras -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>apache-log4j-extras</artifactId>
            <version>${log4j.version}</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.ghgande</groupId>
            <artifactId>j2mod</artifactId>
            <version>2.5.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/j2mod.jar</systemPath>
        </dependency>
    </dependencies>


</project>

To build the jar I used maven plugins (assembly, one-jar...) to make sure all dependencies are in the class path.

When I'm running the JAR everything is working well, but when I'm trying to run the Android application (with that jar) I'm getting some errors. Here is my Android project gradle file content:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    buildToolsVersion '27.0.3'
    defaultConfig {
        applicationId 'com.app.android'
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    dataBinding {
        enabled = true
    }
    productFlavors {
    }
}

dependencies {
    def lifecycle_version = "1.1.1"
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    implementation 'com.android.support:recyclerview-v7:26.1.0'
    implementation 'com.android.support:design:26.1.0'
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    implementation (group: 'com.zaxxer', name: 'HikariCP-java7', version: '2.4.13')
    implementation files('libs/reactor.jar')
}

The errors I'm getting are mostly Class-not-found Exception, such: Caused by: java.lang.ClassNotFoundException: Class io.prometheus.client.Collector not found

In HakiriCP there are some dependencies which under provided scope so I tried to import those dependencies in my Android gradle file but I'm still getting errors such as:

10-03 10:55:17.960 18268-18281/com.atlantium.aio.android E/dalvikvm: Could not find class 'javax.naming.InitialContext', referenced from method com.zaxxer.hikari.HikariConfig.getObjectOrPerformJndiLookup
10-03 10:55:17.960 18268-18281/com.atlantium.aio.android W/dalvikvm: VFY: unable to resolve new-instance 4434 (Ljavax/naming/InitialContext;) in Lcom/zaxxer/hikari/HikariConfig;
10-03 10:55:17.960 18268-18281/com.atlantium.aio.android D/dalvikvm: VFY: replacing opcode 0x22 at 0x0004
10-03 10:55:17.960 18268-18281/com.atlantium.aio.android W/dalvikvm: VFY: unable to resolve exception class 4437 (Ljavax/naming/NamingException;)
    VFY: unable to find exception handler at addr 0x11
    VFY:  rejected Lcom/zaxxer/hikari/HikariConfig;.getObjectOrPerformJndiLookup (Ljava/lang/Object;)Ljava/lang/Object;
    VFY:  rejecting opcode 0x0d at 0x0011
    VFY:  rejected Lcom/zaxxer/hikari/HikariConfig;.getObjectOrPerformJndiLookup (Ljava/lang/Object;)Ljava/lang/Object;
    Verifier rejected class Lcom/zaxxer/hikari/HikariConfig;

Is there something I'm missing?

Is it possible to use JDBC connection pools on android? (according to Establish pooled connection to MySQL in android it's possible but still I can't get it work).

Maybe someone can recommend about another connection pool which tested on android?

Thanks

Update

According to H2 documentation:

Currently only the JDBC API is supported (it is planned to support the Android database API in future releases)......

Limitations: Using a connection pool is currently not supported, because the required javax.sql. classes are not available on Android.

Community
  • 1
  • 1
sharonooo
  • 684
  • 3
  • 8
  • 25
  • 2
    You shouldn't use JDBC on android devices. It is inherently insecure to have your database credentials in your application, not to mention requiring to have your database server publicly accessible. You should build a rest service that communicates with the database, and let your android device talk to that reset service. Also: Android != Java, it is missing parts that are present in real Java (as demonstrated by this error). – Mark Rotteveel Oct 03 '18 at 08:44
  • `javax` packages do not exist for Android. Please follow Mark's advice. – m0skit0 Oct 03 '18 at 08:49
  • @MarkRotteveel The device isn't connected to any server, everything is local. The database is embedded. – sharonooo Oct 03 '18 at 09:53
  • Then you should wonder why you want to use a connection pool at all. It won't give much benefit when using an embedded database, as the overhead of creating connections is much smaller compared to the delay causes by network communication. In any case, a lot of JDBC libraries and drivers use things not available on the Android platform. – Mark Rotteveel Oct 03 '18 at 09:58
  • @MarkRotteveel I'm considering to use connection pool because there is many insertions (saving the states of each entity), the insertion rate is quite high (read data from multiple sensors for example). Would you suggest to use one opened connection for the whole life cycle of the application instead of using connection pool? – sharonooo Oct 03 '18 at 10:10
  • 1
    The primary reason for using a connection pool is when the cost of creating a new connection is high (for example caused by the network roundtrip delay), that cost is - usually - negligble for embedded database. Also consider using the native SQLite support in Android instead. – Mark Rotteveel Oct 03 '18 at 10:27
  • @MarkRotteveel I want to decouple as much as I can from Android. The whole core of my application is written in pure java because there is chance it will consume by other platforms (linux, win) in the future, so I want to make it easy as possible to create just a dummy client for my app. I will test it without using connection pool. – sharonooo Oct 03 '18 at 10:41

0 Answers0