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.

2
  • Have you just tried it out, e.g. by putting this bean definition into a controller (which is discovered by spring boot)?
    – guenhter
    Aug 30, 2017 at 5:52
  • 1
    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. Aug 30, 2017 at 9:11

4 Answers 4

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.

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! Mar 3, 2018 at 20:22
  • Yes and not yet. Mar 12, 2018 at 8:11
  • 1
    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. Feb 7, 2019 at 9:21
  • 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.
    – yuranos
    Apr 1, 2019 at 12:58
  • Declaring the initializer like that will disable all other ones provided by spring boot, won't it? Apr 12, 2020 at 18:25
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
                }
        )
    }
}
1
  • 4
    The drawback of that approach is that the initializer won't be taken in account for tests. May 31, 2019 at 8:22
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"))
}
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...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.