Estoy tratando de crear una data class configuración en Kotlin con Spring Boot. Tengo la siguiente clase:
@Configuration @ConfigurationProperties(prefix = "spring.braintree") data class BraintreeConfigProperties( val merchantId: String = "", val publicKey: String = "", val privateKey: String = "", val environment: Environment = Environment.SANDBOX )Y las siguientes propiedades:
spring.braintree.merchantId=${BRAINTREE_MERCHANT_ID} spring.braintree.publicKey=${BRAINTREE_PUBLIC_KEY} spring.braintree.privateKey=${BRAINTREE_PRIVATE_KEY}Cuando ejecuto la aplicación obtengo la siguiente excepción:
APPLICATION FAILED TO START *************************** Description: Failed to bind properties under 'spring.braintree' to com.x.ps.config.BraintreeConfigProperties$$EnhancerBySpringCGLIB$$311e0531: Property: spring.braintree.merchant-id Value: ${BRAINTREE_MERCHANT_ID} Origin: class path resource [application.properties] - 5:29 Reason: java.lang.IllegalStateException: No setter found for property: merchant-id Action: Update your application's configuration Sin embargo, también tengo una clase que es exactamente igual a la clase BraintreeConfigProperties . Esta clase ( DatabaseConfigProperties ) funciona. Son completamente idénticos.
Lo que he probado:
APPLICATION FAILED TO START *************************** Description: Failed to bind properties under 'spring.braintree' to com.x.ps.config.BraintreeConfigProperties$$EnhancerBySpringCGLIB$$62509e61: Property: spring.braintree.merchant-id Value: 1234 Origin: class path resource [application.properties] - 5:29 Reason: java.lang.IllegalStateException: No setter found for property: merchant-id Action: Update your application's configurationEl problema aquí es que val es final y var se puede cambiar. Entonces deberías cambiar tus propiedades a var .
Más información aquí: https://medium.com/mindorks/kotlin-series-val-vs-var-difference-android-kotlin-ecad780daeb7
Kotlin solo genera un captador cuando declara un campo como val . Sin embargo, Spring usa un setter para inyectar valores de propiedades en el objeto.
Con las versiones más nuevas de Spring Boot, puede hacer uso de data class es con campos val , inyectando valores a través del constructor en lugar de usar setters.
Puede hacerlo usando @ConstructorBinding , vea el siguiente ejemplo de los documentos oficiales :
@ConstructorBinding @ConfigurationProperties("example.kotlin") data class KotlinExampleProperties( val name: String, val description: String, val myService: MyService) { data class MyService( val apiToken: String, val uri: URI ) } Al usar lateinit var o una var que se inicializa en nulo también funciona. Lo más probable es que no desee cambiar esos campos después de la inicialización, por lo que val parece encajar mejor la mayor parte del tiempo en lugar de declarar una var y generar un setter bajo el capó.