helidon-io / helidon

Java libraries for writing microservices
https://helidon.io
Apache License 2.0
3.51k stars 566 forks source link

Native image support for databases #2339

Closed m0mus closed 2 months ago

m0mus commented 4 years ago
Tomas-Kraus commented 4 years ago

1st step is to modify existing tests to support all those JDBC drivers:

Tomas-Kraus commented 3 years ago

MS SQL Server works too but I'll add it later after PR 2442 is merged. https://github.com/Tomas-Kraus/helidon/tree/JPA_MSSQL_NTIM

rupesiro commented 10 months ago

TL;DR: Is the database native image support going to include non-JPA/Hibernate use cases, like plain JDBC usage with the Helidon DB Client?


Looking at the native image wiki page, the DB Client module is marked as "does not work (and we are working on it!)" but the current issue does mention that the Postgres JDBC driver should be supported. However, I've tried adding the DB Client module to a project and it fails to connect to a PostgreSQL database when a GraalVM native image is created, whilst it works if a regular JAR file is created (pointing to the problem indeed being with the native image support). Looking at the PR for the PostgreSQL native image support, it hints at including support only for the JPA/Hibernate usage of PostgreSQL.

Therefore, my question is: will the database native image support include non-JPA/Hibernate use cases, like plain JDBC usage with the Helidon DB Client, or is the native image support only intended to target the JPA/Hibernate use cases?


My particular project attempted to add the Helidon DB Client module to connect to a PostgreSQL database, using HikariCP as the connection pool. In order to do this, the helidon-dbclient{-hikari,-jdbc} libraries, along with helidon-integrations-db-pgsql and the official Postgres JDBC driver were included. The GraalVM native image was created correctly, however attempting to run it yielded:

SEVERE: null - Exception during pool initialization.
java.lang.NullPointerException
        at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:359)
        at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201)
        at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:470)
        at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561)
        at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:100)
        at com.zaxxer.hikari.HikariDataSource.<init>(HikariDataSource.java:81)
        at io.helidon.dbclient.hikari.HikariConnectionPool.<init>(HikariConnectionPool.java:50)
        at io.helidon.dbclient.hikari.HikariConnectionPool$Builder.build(HikariConnectionPool.java:124)
        at io.helidon.dbclient.hikari.HikariConnectionPoolProvider.create(HikariConnectionPoolProvider.java:45)
        at io.helidon.dbclient.hikari.HikariConnectionPoolProvider.create(HikariConnectionPoolProvider.java:25)
        at io.helidon.dbclient.jdbc.JdbcConnectionPool.create(JdbcConnectionPool.java:76)
        at io.helidon.config.ConfigValues.lambda$create$4(ConfigValues.java:168)
        at io.helidon.config.ConfigValues$GenericConfigValueImpl.asOptional(ConfigValues.java:255)
        at io.helidon.common.mapper.OptionalValue.ifPresent(OptionalValue.java:188)
        at io.helidon.dbclient.jdbc.JdbcClientBuilder.config(JdbcClientBuilder.java:56)
        at io.helidon.dbclient.jdbc.JdbcClientBuilder.config(JdbcClientBuilder.java:27)
        at io.helidon.dbclient.DbClient$Builder.config(DbClient.java:206)
        at io.helidon.dbclient.DbClient.builder(DbClient.java:151)
        at io.helidon.dbclient.DbClient.create(DbClient.java:87)
        at co.uk.rupesiro.DevDashboardServer.call(DevDashboardServer.java:47)
        at co.uk.rupesiro.DevDashboardServer.call(DevDashboardServer.java:18)
        at picocli.CommandLine.executeUserObject(CommandLine.java:2041)
        at picocli.CommandLine.access$1500(CommandLine.java:148)
        at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2461)
        at picocli.CommandLine$RunLast.handle(CommandLine.java:2453)
        at picocli.CommandLine$RunLast.handle(CommandLine.java:2415)
        at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2273)
        at picocli.CommandLine$RunLast.execute(CommandLine.java:2417)
        at picocli.CommandLine.execute(CommandLine.java:2170)
        at co.uk.rupesiro.DevDashboardServer.main(DevDashboardServer.java:42)
        at java.base@21.0.1/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)

com.zaxxer.hikari.pool.HikariPool$PoolInitializationException: Failed to initialize pool: null
        at com.zaxxer.hikari.pool.HikariPool.throwPoolInitializationException(HikariPool.java:596)
        at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:582)
        at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:100)
        at com.zaxxer.hikari.HikariDataSource.<init>(HikariDataSource.java:81)
        at io.helidon.dbclient.hikari.HikariConnectionPool.<init>(HikariConnectionPool.java:50)
        at io.helidon.dbclient.hikari.HikariConnectionPool$Builder.build(HikariConnectionPool.java:124)
        at io.helidon.dbclient.hikari.HikariConnectionPoolProvider.create(HikariConnectionPoolProvider.java:45)
        at io.helidon.dbclient.hikari.HikariConnectionPoolProvider.create(HikariConnectionPoolProvider.java:25)
        at io.helidon.dbclient.jdbc.JdbcConnectionPool.create(JdbcConnectionPool.java:76)
        at io.helidon.config.ConfigValues.lambda$create$4(ConfigValues.java:168)
        at io.helidon.config.ConfigValues$GenericConfigValueImpl.asOptional(ConfigValues.java:255)
        at io.helidon.common.mapper.OptionalValue.ifPresent(OptionalValue.java:188)
        at io.helidon.dbclient.jdbc.JdbcClientBuilder.config(JdbcClientBuilder.java:56)
        at io.helidon.dbclient.jdbc.JdbcClientBuilder.config(JdbcClientBuilder.java:27)
        at io.helidon.dbclient.DbClient$Builder.config(DbClient.java:206)
        at io.helidon.dbclient.DbClient.builder(DbClient.java:151)
        at io.helidon.dbclient.DbClient.create(DbClient.java:87)
        at co.uk.rupesiro.DevDashboardServer.call(DevDashboardServer.java:47)
        at co.uk.rupesiro.DevDashboardServer.call(DevDashboardServer.java:18)
        at picocli.CommandLine.executeUserObject(CommandLine.java:2041)
        at picocli.CommandLine.access$1500(CommandLine.java:148)
        at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2461)
        at picocli.CommandLine$RunLast.handle(CommandLine.java:2453)
        at picocli.CommandLine$RunLast.handle(CommandLine.java:2415)
        at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2273)
        at picocli.CommandLine$RunLast.execute(CommandLine.java:2417)
        at picocli.CommandLine.execute(CommandLine.java:2170)
        at co.uk.rupesiro.DevDashboardServer.main(DevDashboardServer.java:42)
        at java.base@21.0.1/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)
Caused by: java.lang.NullPointerException
        at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:359)
        at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201)
        at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:470)
        at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561)
        ... 27 more

Yet building the same project as a regular JAR works correctly and the connection to the database can be established.

(I'm not trying to have you debug my project, I'm just including the information so you have a better picture of the non-JPA/Hibernate use cases I'm mentioning)

tomas-langer commented 2 months ago

The databases we want supported are supported in Helidon 4.x. If you need native image support for another database, we can try to see if that is feasible on case by case basis, kindly open an issue if such a need arises.