How to use "Functional bean definition Kotlin DSL" with Spring Boot and Spring WebFlux?
Asked Answered
M

4

19

At https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/main/kotlin/org/springframework/context/support/BeanDefinitionDsl.kt the comment shows how to define Spring Beans via the new "Functional bean definition Kotlin DSL". I also found https://github.com/sdeleuze/spring-kotlin-functional. However, this example uses just plain Spring and not Spring Boot. Any hint how to use the DSL together with Spring Boot is appreciated.

Marketa answered 29/8, 2017 at 9:51 Comment(2)
Have you just tried it out, e.g. by putting this bean definition into a controller (which is discovered by spring boot)?Ratan
Yes, I tried a @Configuration class with an @Bean method returning the result of beans {...}. Then I got the exception "... No qualifying bean of type '...' available ..." when I remove @Service and declare the service class inside the beans {...} lambda above.Marketa
W
29

Spring Boot is based on Java Config, but should allow experimental support of user-defined functional bean declaration DSL via ApplicationContextInitializer support as described here.

In practice, you should be able to declare your beans for example in a Beans.kt file containing a beans() function.

fun beans() = beans {
    // Define your bean with Kotlin DSL here
}

Then in order to make it taken in account by Boot when running main() and tests, create an ApplicationContextInitializer class as following:

class BeansInitializer : ApplicationContextInitializer<GenericApplicationContext> {

    override fun initialize(context: GenericApplicationContext) =
        beans().initialize(context)

}

And ultimately, declare this initializer in your application.properties file:

context.initializer.classes=com.example.BeansInitializer  

You will find a full example here and can also follow this issue about dedicated Spring Boot support for functional bean registration.

Wadley answered 4/9, 2017 at 9:3 Comment(6)
Two questions regarding your answer: * This initialisation will be picked up by the test setup with using a SpringRunner with JUnit, right? * Is there any other way of having this behaviour without having to create properties files, including this initialisation being picked up on tests? Thanks!Glisten
Yes and not yet.Philipps
Side note: we are currently exploring full functional bean definition for Boot with Java or Kotlin DSL in github.com/spring-projects/spring-fu incubator project.Philipps
What if I want to override a bean? I added allow-bean-definition-overriding: true and am trying to declare a test bean via @Bean but it seems to be ignored. I have tried an exact same setup(basically, just copy pasted) on a project withotu bean DSL and it worked.Cumbrance
Declaring the initializer like that will disable all other ones provided by spring boot, won't it?Bertabertasi
Is that what your tests seems to indicate?Philipps
J
7

Another way to do it in Spring Boot would be :

fun main(args: Array<String>) {
    runApplication<DemoApplication>(*args) {
        addInitializers(
                beans {
                    // Define your bean with Kotlin DSL here
                }
        )
    }
}
Janeyjangle answered 22/7, 2018 at 14:59 Comment(1)
The drawback of that approach is that the initializer won't be taken in account for tests.Philipps
C
2

You can define your beans in *Config.kt file and implement initalize method of ApplicationContextInitializer interface.

override fun initialize(applicationContext: GenericApplicationContext) {
    ....
}

Some bean definition here.

bean<XServiceImpl>("xService")

bean("beanName") {
        BeanConstructor(ref("refBeanName"))
}
Cusk answered 22/10, 2019 at 7:5 Comment(0)
S
0

That same example project you mentioned has a boot git branch, with the BeanDefinitionDsl configuration for Spring Boot in a Beans.kt file. That is not how you should use git branches...

Sniggle answered 28/2 at 16:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.