Java – How do I define a data source programmatically?

How do I define a data source programmatically?… here is a solution to the problem.

How do I define a data source programmatically?

I’m trying to collect data source metrics using OpenTelemetry. According to the OpenTelemetry documentation , DataSource the instance must be wrapped into OpenTelemetryDataSource the data source like this:

new OpenTelemetryDataSource(dataSource);

I’ve been through the Quarkus documentation and haven’t found a way to programmatically override the data source.

How do I programmatically override a data source in Quarkus? Or how do you connect OpenTelemetry to data sources in Quarkus in general?

Update:
When I set the JDBC URL with the configuration property(quarkus.datasource.jdbc.url=jdbc:otel:postgresql://localhost:5432/my_dbs), the application fails on startup with NPE:

ERROR: Failed to start application (with profile dev)
java.lang.NullPointerException
        at io.quarkus.opentelemetry.runtime.QuarkusContextStorage.getVertxContext(QuarkusContextStorage.java:62)
        at io.quarkus.opentelemetry.runtime.QuarkusContextStorage.current(QuarkusContextStorage.java:54)
        at io.opentelemetry.context.Context.current(Context.java:86)
        at io.opentelemetry.instrumentation.jdbc.internal.OpenTelemetryStatement.wrapCall(OpenTelemetryStatement.java:277)
        at io.opentelemetry.instrumentation.jdbc.internal.OpenTelemetryPreparedStatement.executeQuery(OpenTelemetryPreparedStatement.java:53)
        at io.agroal.pool.wrapper.PreparedStatementWrapper.executeQuery(PreparedStatementWrapper.java:78)
        at org.flywaydb.core.internal.database.base.BaseDatabaseType.getSelectVersionOutput(BaseDatabaseType.java:195)
        at org.flywaydb.core.internal.database.cockroachdb.CockroachDBDatabaseType.handlesDatabaseProductNameAndVersion(CockroachDBDatabaseType.java:81)
        at org.flywaydb.core.internal.database.DatabaseTypeRegister.getDatabaseTypeForConnection(DatabaseTypeRegister.java:136)
        at org.flywaydb.core.internal.jdbc.JdbcConnectionFactory.<init>(JdbcConnectionFactory.java:69)
        at org.flywaydb.core.Flyway.execute(Flyway.java:510)
        at org.flywaydb.core.Flyway.migrate(Flyway.java:170)
        at io.quarkus.flyway.runtime.FlywayRecorder.doStartActions(FlywayRecorder.java:75)
        at io.quarkus.deployment.steps.FlywayProcessor$createBeansAndStartActions-1520831253.deploy_0(FlywayProcessor$createBeansAndStartActions-1520831253.zig:84)
        at io.quarkus.deployment.steps.FlywayProcessor$createBeansAndStartActions-1520831253.deploy(FlywayProcessor$createBeansAndStartActions-1520831253.zig:40)
        at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:754)
        at io.quarkus.runtime.Application.start(Application.java:101)
        at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:101)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:66)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:42)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:119)
        at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:98)
        at java.base/java.lang.Thread.run(Thread.java:829)

Solution

Some workarounds seem to be proposed in this open issue, but configuring the Quarkus data source programmatically is still a feature request.

This other issue , while related to OpenTracing rather than OpenTelemetry, seems to confirm this.

Probably the best approach is to try configuring this integration using configuration properties.

Based on Quarkus documentation and OpenTracing as an example, try the following configuration:

quarkus.datasource.db-kind=postgresql
quarkus.datasource.jdbc.driver=io.opentelemetry.instrumentation.jdbc.OpenTelemetryDriver
quarkus.datasource.jdbc.url=jdbc:otel:postgresql://localhost:5432/hibernate_orm_test
# other configuration properties ...

Note the prefix in the URL. The example is for PostgreSql, but should be very similar to other databases.

The configuration is inspired by OpenTelemetry documentation .

At your opinion, this configuration conflicts with the Flyway database migration process that Quarkus performs at initialization.

To solve this problem, you can disable Quarkus Flyway migration at startup and perform the migration programmatically.

As described in the Quarkus documentation , you can achieve this behavior by first setting the configuration property quarkus.flyway.migrate-at-start to false(the default is true).

Then, run the migration programmatically:

@ApplicationScoped
public class MigrationService {
    // You can Inject the object if you want to use it manually
    @Inject
    Flyway flyway; 

    public void checkMigration() {
        flyway.clean(); 
        flyway.migrate();
    }
}

Related Problems and Solutions