parent
514f7e3328
commit
2a0a002bd3
|
@ -186,15 +186,28 @@ In Java, you can, for example, write the following:
|
|||
----
|
||||
====
|
||||
|
||||
In Kotlin, with reified type parameters and `GenericApplicationContext`
|
||||
Kotlin extensions, you can instead write the following:
|
||||
In Kotlin, with reified type parameters and `GenericApplicationContext` Kotlin extensions,
|
||||
you can instead write the following:
|
||||
|
||||
====
|
||||
[source,kotlin,indent=0]
|
||||
----
|
||||
val context = GenericApplicationContext().apply {
|
||||
registerBean<Foo>()
|
||||
registerBean { Bar(it.getBean<Foo>()) }
|
||||
registerBean { Bar(it.getBean()) }
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
If the class `Bar` has a single constructor, you can even just specify the bean class,
|
||||
the constructor parameters will be autowired by type:
|
||||
|
||||
====
|
||||
[source,kotlin,indent=0]
|
||||
----
|
||||
val context = GenericApplicationContext().apply {
|
||||
registerBean<Foo>()
|
||||
registerBean<Bar>()
|
||||
}
|
||||
----
|
||||
====
|
||||
|
@ -208,39 +221,23 @@ how beans are registered. The following example creates a `Play` profile:
|
|||
====
|
||||
[source,kotlin,indent=0]
|
||||
----
|
||||
fun beans() = beans {
|
||||
bean<UserHandler>()
|
||||
bean<Routes>()
|
||||
bean<WebHandler>("webHandler") {
|
||||
RouterFunctions.toWebHandler(
|
||||
ref<Routes>().router(),
|
||||
HandlerStrategies.builder().viewResolver(ref()).build()
|
||||
)
|
||||
}
|
||||
bean("messageSource") {
|
||||
ReloadableResourceBundleMessageSource().apply {
|
||||
setBasename("messages")
|
||||
setDefaultEncoding("UTF-8")
|
||||
val myBeans = beans {
|
||||
bean<Foo>()
|
||||
bean<Bar>()
|
||||
bean("bazBean") {
|
||||
Baz().apply {
|
||||
message = "Hello world"
|
||||
}
|
||||
}
|
||||
bean {
|
||||
val prefix = "classpath:/templates/"
|
||||
val suffix = ".mustache"
|
||||
val loader = MustacheResourceTemplateLoader(prefix, suffix)
|
||||
MustacheViewResolver(Mustache.compiler().withLoader(loader)).apply {
|
||||
setPrefix(prefix)
|
||||
setSuffix(suffix)
|
||||
}
|
||||
}
|
||||
profile("play") {
|
||||
bean<Play>()
|
||||
profile("foobar") {
|
||||
bean { FooBar(ref("bazBean")) }
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
In the preceding example, `bean<Routes>()` uses autowiring by constructor, and `ref<Routes>()`
|
||||
is a shortcut for `applicationContext.getBean(Routes::class.java)`.
|
||||
NOTE: This DSL is programmatic, meaning it allows custom registration logic of beans
|
||||
through an `if` expression, a `for` loop, or any other Kotlin constructs.
|
||||
|
||||
You can then use this `beans()` function to register beans on the application context,
|
||||
as the following example shows:
|
||||
|
@ -249,19 +246,16 @@ as the following example shows:
|
|||
[source,kotlin,indent=0]
|
||||
----
|
||||
val context = GenericApplicationContext().apply {
|
||||
beans().initialize(this)
|
||||
myBeans.initialize(this)
|
||||
refresh()
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: This DSL is programmatic, meaning it allows custom registration logic of beans
|
||||
through an `if` expression, a `for` loop, or any other Kotlin constructs.
|
||||
|
||||
See https://github.com/sdeleuze/spring-kotlin-functional/blob/master/src/main/kotlin/functional/Beans.kt[spring-kotlin-functional beans declaration]
|
||||
for a concrete example.
|
||||
See https://github.com/sdeleuze/spring-kotlin-functional[spring-kotlin-functional beans declaration] for a concrete example.
|
||||
|
||||
NOTE: Spring Boot is based on Java configuration and
|
||||
NOTE: Spring Boot is based on JavaConfig and
|
||||
https://github.com/spring-projects/spring-boot/issues/8115[does not yet provide specific support for functional bean definition],
|
||||
but you can experimentally use functional bean definitions through Spring Boot's `ApplicationContextInitializer` support.
|
||||
See https://stackoverflow.com/questions/45935931/how-to-use-functional-bean-definition-kotlin-dsl-with-spring-boot-and-spring-w/46033685#46033685[this Stack Overflow answer]
|
||||
|
@ -278,8 +272,8 @@ for more details and up-to-date information.
|
|||
|
||||
Spring Framework now comes with a
|
||||
{doc-root}/spring-framework/docs/{spring-version}/kdoc-api/spring-framework/org.springframework.web.reactive.function.server/-router-function-dsl/[Kotlin routing DSL]
|
||||
that lets you use the <<web-reactive#webflux-fn,WebFlux functional
|
||||
API>> to write clean and idiomatic Kotlin code, as the following example shows:
|
||||
that lets you use the <<web-reactive#webflux-fn,WebFlux functional API>> to write clean and idiomatic Kotlin code,
|
||||
as the following example shows:
|
||||
|
||||
====
|
||||
[source,kotlin,indent=0]
|
||||
|
@ -307,7 +301,7 @@ NOTE: This DSL is programmatic, meaning that it allows custom registration logic
|
|||
through an `if` expression, a `for` loop, or any other Kotlin constructs. That can be useful when you need to register routes
|
||||
depending on dynamic data (for example, from a database).
|
||||
|
||||
See https://github.com/mixitconf/mixit/tree/bad6b92bce6193f9b3f696af9d416c276501dbf1/src/main/kotlin/mixit/web/routes[MiXiT project routes]
|
||||
See https://github.com/mixitconf/mixit/tree/dafd5ccc92dfab6d9c306fcb60b28921a1ccbf79/src/main/kotlin/mixit/web/routes[MiXiT project routes]
|
||||
for a concrete example.
|
||||
|
||||
|
||||
|
@ -583,9 +577,43 @@ all HTTP methods will be matched, not only the `GET` one.
|
|||
|
||||
=== Testing
|
||||
|
||||
This section address testing with the combination of Kotlin and the Spring Framework.
|
||||
This section addresses testing with the combination of Kotlin and Spring Framework. The recommended testing framework
|
||||
is https://junit.org/junit5/[JUnit 5], as well as https://mockk.io/[Mockk] for mocking.
|
||||
|
||||
|
||||
==== Constructor injection
|
||||
|
||||
As described in the <<testing#testcontext-junit-jupiter-di#spring-web-reactive,dedicated section>>, JUnit 5 allows
|
||||
constructor injection of beans which is pretty useful with Kotlin in order to use `val` instead of `lateinit var `.
|
||||
|
||||
|
||||
====
|
||||
[source]
|
||||
----
|
||||
@SpringJUnitConfig(TestConfig::class)
|
||||
class OrderServiceIntegrationTests(@Autowired val orderService: OrderService,
|
||||
@Autowired val customerService: CustomerService) {
|
||||
|
||||
// tests that use the injected OrderService and CustomerService
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
You can also use `@Autowired` at constructor level to autowire all parameters.
|
||||
|
||||
====
|
||||
[source]
|
||||
----
|
||||
@SpringJUnitConfig(TestConfig::class)
|
||||
class OrderServiceIntegrationTests @Autowired constructor(
|
||||
val orderService: OrderService,
|
||||
val customerService: CustomerService) {
|
||||
|
||||
// tests that use the injected OrderService and CustomerService
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
==== `PER_CLASS` Lifecycle
|
||||
|
||||
|
@ -681,20 +709,15 @@ See also the related https://jira.spring.io/browse/SPR-16057[SPR-16057] issue.
|
|||
[[kotlin-getting-started]]
|
||||
== Getting Started
|
||||
|
||||
This section describes the fastest way to get started with a project that combines
|
||||
Kotlin and the Spring Framework.
|
||||
The easiest way to learn how to build a Spring application with Kotlin is to follow
|
||||
https://spring.io/guides/tutorials/spring-boot-kotlin/[the dedicated tutorial].
|
||||
|
||||
|
||||
|
||||
=== Using `start.spring.io`
|
||||
=== `start.spring.io`
|
||||
|
||||
The easiest way to start a new Spring Framework 5 project in Kotlin is to create a new Spring
|
||||
Boot 2 project on https://start.spring.io/#!language=kotlin[start.spring.io].
|
||||
|
||||
You can also create a standalone WebFlux project, as described in
|
||||
https://spring.io/blog/2017/08/01/spring-framework-5-kotlin-apis-the-functional-way[this blog post].
|
||||
|
||||
|
||||
|
||||
=== Choosing the Web Flavor
|
||||
|
||||
|
@ -702,11 +725,11 @@ Spring Framework now comes with two different web stacks: <<web#mvc,Spring MVC>>
|
|||
<<web-reactive#spring-web-reactive,Spring WebFlux>>.
|
||||
|
||||
Spring WebFlux is recommended if you want to create applications that will deal with latency,
|
||||
long-lived connections, o streaming scenarios or if you want to use the web functional
|
||||
long-lived connections, streaming scenarios or if you want to use the web functional
|
||||
Kotlin DSL.
|
||||
|
||||
For other use cases, especially if you are using blocking technologies such as JPA, Spring
|
||||
MVC and its annotation-based programming model is a perfectly valid and fully supported choice.
|
||||
MVC and its annotation-based programming model is the recommended choice.
|
||||
|
||||
|
||||
|
||||
|
@ -724,27 +747,6 @@ Kotlin and the Spring Framework:
|
|||
* https://kotlin.link/[Awesome Kotlin]
|
||||
|
||||
|
||||
|
||||
=== Tutorials
|
||||
|
||||
We recommend the following tutorials:
|
||||
|
||||
* https://spring.io/guides/tutorials/spring-boot-kotlin/[Building web applications with Spring Boot and Kotlin]
|
||||
* https://kotlinlang.org/docs/tutorials/spring-boot-restful.html[Creating a RESTful Web Service with Spring Boot]
|
||||
|
||||
|
||||
|
||||
=== Blog posts
|
||||
|
||||
The following blog posts provide further details:
|
||||
|
||||
* https://spring.io/blog/2016/02/15/developing-spring-boot-applications-with-kotlin[Developing Spring Boot applications with Kotlin]
|
||||
* https://spring.io/blog/2016/03/20/a-geospatial-messenger-with-kotlin-spring-boot-and-postgresql[A Geospatial Messenger with Kotlin, Spring Boot and PostgreSQL]
|
||||
* https://spring.io/blog/2017/01/04/introducing-kotlin-support-in-spring-framework-5-0[Introducing Kotlin support in Spring Framework 5.0]
|
||||
* https://spring.io/blog/2017/08/01/spring-framework-5-kotlin-apis-the-functional-way[Spring Framework 5 Kotlin APIs, the functional way]
|
||||
|
||||
|
||||
|
||||
=== Examples
|
||||
|
||||
The following Github projects offer examples that you can learn from and possibly even extend:
|
||||
|
@ -764,22 +766,19 @@ The following Github projects offer examples that you can learn from and possibl
|
|||
The following list categorizes the pending issues related to Spring and Kotlin support:
|
||||
|
||||
* Spring Framework
|
||||
** https://jira.spring.io/browse/SPR-16057[Unable to use WebTestClient with mock server in Kotlin]
|
||||
** https://jira.spring.io/browse/SPR-15942[Support null-safety at generics, varargs and array elements level]
|
||||
** https://jira.spring.io/browse/SPR-15413[Add support for Kotlin coroutines]
|
||||
** https://github.com/spring-projects/spring-framework/issues/20606[Unable to use WebTestClient with mock server in Kotlin]
|
||||
** https://github.com/spring-projects/spring-framework/issues/20496[Support null-safety at generics, varargs and array elements level]
|
||||
** https://github.com/spring-projects/spring-framework/issues/19975[Add support for Kotlin coroutines]
|
||||
* Spring Boot
|
||||
** https://github.com/spring-projects/spring-boot/issues/8762[Allow `@ConfigurationProperties` binding for immutable POJOs]
|
||||
** https://github.com/spring-projects/spring-boot/issues/1254[Allow `@ConfigurationProperties` binding on interfaces]
|
||||
** https://github.com/spring-projects/spring-boot/issues/8115[Expose the functional bean registration API via `SpringApplication`]
|
||||
** https://github.com/spring-projects/spring-boot/issues/10712[Add null-safety annotations on Spring Boot APIs]
|
||||
** https://github.com/spring-projects/spring-boot/issues/9486[Use Kotlin's bom to provide dependency management for Kotlin]
|
||||
* Kotlin
|
||||
** https://youtrack.jetbrains.com/issue/KT-6380[Parent issue for Spring Framework support]
|
||||
** https://youtrack.jetbrains.com/issue/KT-5464[Kotlin requires type inference where Java doesn't]
|
||||
** https://github.com/Kotlin/KEEP/issues/79[Better generics null-safety support]
|
||||
** https://youtrack.jetbrains.com/issue/KT-20283[Smart cast regression with open classes]
|
||||
** https://youtrack.jetbrains.com/issue/KT-14984[Impossible to pass not all SAM argument as function]
|
||||
** https://youtrack.jetbrains.com/issue/KT-19592[Apply JSR 305 meta-annotations to generic type parameters]
|
||||
** https://youtrack.jetbrains.com/issue/KT-18398[Provide a way for libraries to avoid mixing Kotlin 1.0 and 1.1 dependencies]
|
||||
** https://youtrack.jetbrains.com/issue/KT-15125[Support JSR 223 bindings directly via script variables]
|
||||
** https://youtrack.jetbrains.com/issue/KT-15467[Support all-open and no-arg compiler plugins in Kotlin Eclipse plugin]
|
||||
** https://youtrack.jetbrains.com/issue/KT-6653[Kotlin properties do not override Java-style getters and setters]
|
||||
|
||||
|
|
Loading…
Reference in New Issue