scala 在HikariCP使用Guice在Play Framework中启动连接之前强制加载类

pn9klfpd  于 2023-08-05  发布在  Scala
关注(0)|答案(1)|浏览(147)

我有一个用例,我需要在HikariCP初始化和创建到数据库的连接之前加载我的一个应用程序类(一个单例服务)。
由于HikariCP是由Play开箱即用的“自动”初始化的,我不知道如何执行它。
基本上,我有一个类如下所示:

@Singleton
class MyClassThatNeedToBeLoadedBeforeHikariCP() {

  // Setup some global state for OpenTelemetry

}

字符串
如果我想在我自己的另一个类之前初始化它,我会使用常规的DI:

@Singleton
class OtherClassToLoadAfterMyClass() @Inject()(myClass: MyClassThatNeedToBeLoadedBeforeHikariCP) {
}


但这个“其他类”实际上是HikariCP。

如何定义HikariCP和我自己的类之间的依赖关系(根据Guice)?

为了给予完整的上下文,我需要这样做,因为我正在使用一个JDBC驱动程序,它也试图设置一些全局状态,如果在MyClassThatNeedToBeLoadedBeforeHikariCP类之前初始化,那么我的类将无法初始化。
这是因为在后台,OpenTelemetry全局状态只能定义一次。
请参阅JDBC驱动程序(特里诺)跟踪问题中的related discussion
为了帮助达到这个主题的可见性,如果遇到相同的问题,这里是堆栈跟踪:

Caused by: java.lang.IllegalStateException: GlobalOpenTelemetry.set has already been called. GlobalOpenTelemetry.set must be called only once before any calls to GlobalOpenTelemetry.get. If you are using the OpenTelemetrySdk, use OpenTelemetrySdkBuilder.buildAndRegisterGlobal instead. Previous invocation set to cause of this exception.
         at io.opentelemetry.api.GlobalOpenTelemetry.set(GlobalOpenTelemetry.java:104)
         at io.opentelemetry.sdk.OpenTelemetrySdkBuilder.buildAndRegisterGlobal(OpenTelemetrySdkBuilder.java:85)
         at com.myapp.metrics.setup.OTELService.<init>(OTELService.scala:41)
         ^^^^^^^^^ == MyClassThatNeedToBeLoadedBeforeHikariCP
         at com.myapp.metrics.setup.OTELService$$FastClassByGuice$$1270092a.newInstance(<generated>)
         at com.google.inject.internal.DefaultConstructionProxyFactory$FastClassProxy.newInstance(DefaultConstructionProxyFactory.java:89)
...
Caused by: java.lang.Throwable
         at io.opentelemetry.api.GlobalOpenTelemetry.set(GlobalOpenTelemetry.java:112)
         at io.opentelemetry.api.GlobalOpenTelemetry.get(GlobalOpenTelemetry.java:82)
         at io.trino.jdbc.NonRegisteringTrinoDriver.instrumentClient(NonRegisteringTrinoDriver.java:68)
         at io.trino.jdbc.NonRegisteringTrinoDriver.connect(NonRegisteringTrinoDriver.java:62)
         at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)
         at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:358)

vmpqdwk3

vmpqdwk31#

解决办法是:

  • 禁用与Play捆绑的HikariCP模块
  • 创建并启用自定义模块来替换它,将依赖项添加到MyClassThatNeedToBeLoadedBeforeHikariCP

请参阅Play文档的相关部分。
在Play配置文件中:

play.modules.disabled += "play.api.db.HikariCPModule"
play.modules.enabled += "com.myapp.modules.HikariCPModuleWithCustomDependency"

字符串
并创建以下模块:

class HikariCPModuleWithCustomDependency extends SimpleModule(
  bind[ConnectionPool].to[HikariCPConnectionPoolWithCustomDependency]
)

@Singleton
class HikariCPConnectionPoolWithCustomDependency @Inject() (
    environment: Environment,
    @nowarn myClass: MyClassThatNeedToBeLoadedBeforeHikariCP
  )
  extends HikariCPConnectionPool(environment) {}

相关问题