Kotlin Micronaut未加载application.yml属性。

huangapple go评论67阅读模式
英文:

Kotlin Micronaut is not loading application.yml properties

问题

以下是您提供的代码部分的翻译:

// SftpConfig.kt
@ConfigurationProperties("sftp")
class SftpConfig {
    var knownHostFile: String = FileConverterConstant.SFTP_KNOWN_HOSTS_FILE_PATH
    var privateKeyFile: String = FileConverterConstant.SFTP_PRIVATE_KEY_PATH
    var privateKeyPass: CharArray = FileConverterConstant.SFTP_PRIVATE_KEY_PASS.toCharArray()

    @NotBlank
    lateinit var username: String

    @NotBlank
    lateinit var remoteHost: String
    var remotePort: Int = FileConverterConstant.SFTP_REMOTE_PORT
    var verifyTimeout: Long = FileConverterConstant.SFTP_VERIFY_TIMEOUT
}
// 在测试函数内
"测试" {
    val items: MutableMap<String, Any> = HashMap()
    items["sftp.username"] = "test"
    items["sftp.remoteHost"] = "1.0.0.0"

    val ctx = ApplicationContext.run(items)
    val sftpConfig = ctx.getBean(SftpConfig::class.java)
    println(sftpConfig.username)
}
// 使用 @Inject 创建 bean 并尝试使用 bean
@Inject
val sftpConfig = SftpConfig()

关于您的问题,这是有关Micronaut应用程序配置的内容,您是否需要任何进一步的帮助?

英文:

After following 5. Team Configuration with @ConfigurationProperties in this document https://guides.micronaut.io/latest/micronaut-configuration-maven-kotlin.html. And created a configuration bean like this

micronaut:
  application:
    name: sftp-test
netty:
  default:
    allocator:
      max-order: 3
sftp:
  known-hosts-file: &quot;testKnownHost&quot;
  private-key-file: &quot;testPk&quot;
  username: &quot;testUser&quot;
  password:
  remote-host: &quot;1.0.0.0&quot;
  remote-port: 22
  verify-timeout: 20000
// SftpConfig.kt
@ConfigurationProperties(&quot;sftp&quot;)
class SftpConfig {
    var knownHostFile: String = FileConverterConstant.SFTP_KNOWN_HOSTS_FILE_PATH
    var privateKeyFile: String = FileConverterConstant.SFTP_PRIVATE_KEY_PATH
    var privateKeyPass: CharArray = FileConverterConstant.SFTP_PRIVATE_KEY_PASS.toCharArray()

    @NotBlank
    lateinit var username: String

    @NotBlank
    lateinit var remoteHost: String
    var remotePort: Int = FileConverterConstant.SFTP_REMOTE_PORT
    var verifyTimeout: Long = FileConverterConstant.SFTP_VERIFY_TIMEOUT
}
// Inside a test function
    &quot;Test&quot; {
        val items: MutableMap&lt;String, Any&gt; = HashMap()
        items[&quot;sftp.username&quot;] = &quot;test&quot;
        items[&quot;sftp.remoteHost&quot;] = &quot;1.0.0.0&quot;

        val ctx = ApplicationContext.run(items)
        val sftpConfig = ctx.getBean(SftpConfig::class.java)
        println(sftpConfig.username)
    }

If I remove the properties from the items map for example items[&quot;sftp.username&quot;] = &quot;test&quot;, the missing properties was filled with the properties from the application.yml file I configured. Everything seems to be working in the test like this page documented.

So now I moved this to an Singleton bean class
When I use @Inject like below to create the bean and try to use the bean. It wont read anything from the application.ym

@Inject
val sftpConfig = SftpConfig()

Now it gives me this error message Message: lateinit property username has not been initialized If I allow the filed to be null. It is null after calling the bean. So the values in application.yml file is not being loaded at all.

While in the test the ApplicationContext was manually created, in here I am relying on Micronaut, am I missing certain dependency? What could be the reason the values in application.yml is not loaded? Side note, if I assign a health endpoint in the application.yml file, it does work after server starts. So the file is being read, but the values I configured for sftp is not being injected in to the configuration bean.

答案1

得分: 1

在测试配置时,您应该使用 @MicronautTest 并像下面所示注入配置-DTO。

import io.kotest.assertions.assertSoftly
import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.string.shouldNotBeEmpty
import io.micronaut.test.extensions.kotest5.annotation.MicronautTest

@MicronautTest
class SftpConfigPropertiesTest(sut: SftpConfig) : BehaviorSpec({

    Given("在application.yml中填充了SFTP配置") {
        Then("所有字段应该填充") {
            assertSoftly(sut){
                it.username.shouldNotBeEmpty()
                /** 添加剩下的断言 */
            }
        }
    }
})

我认为最佳实践是使用构造函数注入,而不是 @Inject。示例:

@Singleton
class MyService(private val sftpConfig: SftpConfig) {

  /** 类体部分在这里 */
}
英文:

For testing your config, you should use @MicronautTest and inject the config-DTO like shown below.

import io.kotest.assertions.assertSoftly
import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.string.shouldNotBeEmpty
import io.micronaut.test.extensions.kotest5.annotation.MicronautTest

@MicronautTest
class SftpConfigPropertiesTest(sut: SftpConfig) : BehaviorSpec({

    Given(&quot;populated sftp in application.yml&quot;) {
        Then(&quot;all fields should be populated&quot;) {
            assertSoftly(sut){
                it.username.shouldNotBeEmpty()
                /** add remaining assertions */
            }
        }
    }
})

I believe best practice is to use constructor injection instead of @Inject. Example:

@Singleton
class MyService(private val sftpConfig : SftpConfig) {

  /** class body goes here */
}

huangapple
  • 本文由 发表于 2023年3月4日 04:46:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/75631728.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定