From b82671ae835dba261da78188d9e8642aaa4d90a0 Mon Sep 17 00:00:00 2001 From: wakingrufus Date: Fri, 9 Aug 2024 13:22:30 -0500 Subject: [PATCH] support routers which inject beans --- docs/webmvc.md | 33 ++++++++++++++++--- .../wakingrufus/funk/webmvc/RoutesDsl.kt | 24 ++++++++++++++ .../wakingrufus/funk/webmvc/WebmvcDsl.kt | 9 ++--- .../funk/webmvc/WebmvcInitializer.kt | 9 +++-- .../funk/webmvc/DslIntegrationTest.kt | 24 ++++++++++++-- .../funk/webmvc/JacksonIntegrationTest.kt | 8 +++-- 6 files changed, 89 insertions(+), 18 deletions(-) create mode 100644 spring-funk-webmvc/src/main/kotlin/com/github/wakingrufus/funk/webmvc/RoutesDsl.kt diff --git a/docs/webmvc.md b/docs/webmvc.md index f12ea00..748372a 100644 --- a/docs/webmvc.md +++ b/docs/webmvc.md @@ -28,14 +28,39 @@ open class TestKotlinApplication : SpringFunkApplication { ## Router DSL The Router DSL exposes the Spring built-in `RouterFunctionDsl`. -### Example +#### Example ```kotlin open class TestKotlinApplication : SpringFunkApplication { override fun dsl(): SpringDslContainer.() -> Unit = { webmvc { - router { - GET("/dsl") { - ServerResponse.ok().body(Dto("Hello World")) + routes { + route { + GET("/dsl") { + ServerResponse.ok().body(Dto("Hello World")) + } + } + } + } + } +} +``` + +### Routers with Bean Injection + +In order to use bean injection in your routers, declare a separate router function. +Then register this function using `ref()` to inject, similar to the beans DSL. + +#### Example +```kotlin +fun helloWorldApi(serviceClass: ServiceClass) = router { + GET("/hello", serviceClass::get) +} +open class TestKotlinApplication : SpringFunkApplication { + override fun dsl(): SpringDslContainer.() -> Unit = { + webmvc { + routes { + router { + helloWorldApi(ref()) } } } diff --git a/spring-funk-webmvc/src/main/kotlin/com/github/wakingrufus/funk/webmvc/RoutesDsl.kt b/spring-funk-webmvc/src/main/kotlin/com/github/wakingrufus/funk/webmvc/RoutesDsl.kt new file mode 100644 index 0000000..d0c3ba2 --- /dev/null +++ b/spring-funk-webmvc/src/main/kotlin/com/github/wakingrufus/funk/webmvc/RoutesDsl.kt @@ -0,0 +1,24 @@ +package com.github.wakingrufus.funk.webmvc + +import com.github.wakingrufus.funk.core.SpringDslMarker +import org.springframework.context.support.BeanDefinitionDsl +import org.springframework.web.servlet.function.RouterFunction +import org.springframework.web.servlet.function.RouterFunctionDsl +import org.springframework.web.servlet.function.ServerResponse + +class RoutesDsl { + private val routes = mutableListOf RouterFunction>() + + @SpringDslMarker + fun router(f: BeanDefinitionDsl.BeanSupplierContext.() -> RouterFunction) { + routes.add(f) + } + + @SpringDslMarker + fun route(router: RouterFunctionDsl.() -> Unit) { + routes.add { org.springframework.web.servlet.function.router(router) } + } + + fun merge(f: BeanDefinitionDsl.BeanSupplierContext): RouterFunction = + routes.map { it.invoke(f) }.reduce(RouterFunction::and) +} \ No newline at end of file diff --git a/spring-funk-webmvc/src/main/kotlin/com/github/wakingrufus/funk/webmvc/WebmvcDsl.kt b/spring-funk-webmvc/src/main/kotlin/com/github/wakingrufus/funk/webmvc/WebmvcDsl.kt index 02a9c04..aa1abe8 100644 --- a/spring-funk-webmvc/src/main/kotlin/com/github/wakingrufus/funk/webmvc/WebmvcDsl.kt +++ b/spring-funk-webmvc/src/main/kotlin/com/github/wakingrufus/funk/webmvc/WebmvcDsl.kt @@ -3,13 +3,10 @@ package com.github.wakingrufus.funk.webmvc import com.github.wakingrufus.funk.core.SpringDsl import com.github.wakingrufus.funk.core.SpringDslContainer import com.github.wakingrufus.funk.core.SpringDslMarker -import org.springframework.web.servlet.function.RouterFunction -import org.springframework.web.servlet.function.RouterFunctionDsl -import org.springframework.web.servlet.function.ServerResponse @SpringDslMarker class WebmvcDsl : SpringDsl { - internal var routerDsl: RouterFunction? = null + internal var routes: RoutesDsl? = null internal var enableWebmvcDsl: EnableWebMvcDsl? = null internal var converterDsl: WebMvcConverterDsl? = null @@ -22,8 +19,8 @@ class WebmvcDsl : SpringDsl { } @SpringDslMarker - fun router(config: RouterFunctionDsl.() -> Unit) { - routerDsl = org.springframework.web.servlet.function.router(config) + fun routes(config: RoutesDsl.() -> Unit) { + routes = RoutesDsl().apply(config) } /** diff --git a/spring-funk-webmvc/src/main/kotlin/com/github/wakingrufus/funk/webmvc/WebmvcInitializer.kt b/spring-funk-webmvc/src/main/kotlin/com/github/wakingrufus/funk/webmvc/WebmvcInitializer.kt index 64cb4aa..f68531c 100644 --- a/spring-funk-webmvc/src/main/kotlin/com/github/wakingrufus/funk/webmvc/WebmvcInitializer.kt +++ b/spring-funk-webmvc/src/main/kotlin/com/github/wakingrufus/funk/webmvc/WebmvcInitializer.kt @@ -17,6 +17,7 @@ import org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier import org.springframework.context.ApplicationContextInitializer import org.springframework.context.support.GenericApplicationContext +import org.springframework.context.support.beans import org.springframework.context.support.registerBean import org.springframework.web.filter.RequestContextFilter import org.springframework.web.servlet.function.RouterFunction @@ -55,8 +56,12 @@ class WebmvcInitializer : ApplicationContextInitializer> { this } + routes?.also { r -> + beans { + bean { + r.merge(this) + } + }.initialize(context) } } } diff --git a/spring-funk-webmvc/src/test/kotlin/com/github/wakingrufus/funk/webmvc/DslIntegrationTest.kt b/spring-funk-webmvc/src/test/kotlin/com/github/wakingrufus/funk/webmvc/DslIntegrationTest.kt index 94a0496..fde75d6 100644 --- a/spring-funk-webmvc/src/test/kotlin/com/github/wakingrufus/funk/webmvc/DslIntegrationTest.kt +++ b/spring-funk-webmvc/src/test/kotlin/com/github/wakingrufus/funk/webmvc/DslIntegrationTest.kt @@ -1,6 +1,7 @@ package com.github.wakingrufus.funk.webmvc import com.github.wakingrufus.funk.base.SpringFunkApplication +import com.github.wakingrufus.funk.beans.beans import com.github.wakingrufus.funk.core.SpringDslContainer import io.github.oshai.kotlinlogging.KotlinLogging import org.assertj.core.api.Assertions.assertThat @@ -11,7 +12,9 @@ import org.springframework.boot.test.web.client.TestRestTemplate import org.springframework.boot.test.web.client.getForEntity import org.springframework.context.ApplicationContext import org.springframework.test.context.ContextConfiguration +import org.springframework.web.servlet.function.ServerRequest import org.springframework.web.servlet.function.ServerResponse +import org.springframework.web.servlet.function.router import java.net.URI @SpringBootTest( @@ -34,19 +37,34 @@ internal class DslIntegrationTest { assertThat(response.statusCode.value()).isEqualTo(200) context.beanDefinitionNames.forEach { log.info { it } } } + } internal class FunkApplication : SpringFunkApplication { override fun dsl(): SpringDslContainer.() -> Unit = { + beans { + bean() + } webmvc { enableWebMvc { jetty() } - router { - GET("/dsl") { - ServerResponse.ok().build() + + routes { + router { + helloWorldApi(ref()) } } } } } + +class ServiceClass { + fun get(req: ServerRequest): ServerResponse { + return ServerResponse.ok().body("Hello, World") + } +} + +fun helloWorldApi(serviceClass: ServiceClass) = router { + GET("/dsl", serviceClass::get) +} diff --git a/spring-funk-webmvc/src/test/kotlin/com/github/wakingrufus/funk/webmvc/JacksonIntegrationTest.kt b/spring-funk-webmvc/src/test/kotlin/com/github/wakingrufus/funk/webmvc/JacksonIntegrationTest.kt index ea7cb07..1fdfcbe 100644 --- a/spring-funk-webmvc/src/test/kotlin/com/github/wakingrufus/funk/webmvc/JacksonIntegrationTest.kt +++ b/spring-funk-webmvc/src/test/kotlin/com/github/wakingrufus/funk/webmvc/JacksonIntegrationTest.kt @@ -42,9 +42,11 @@ internal class JacksonFunkApplication : SpringFunkApplication { converters { jackson() } - router { - GET("/dsl") { - ServerResponse.ok().body(Dto("Hello World")) + routes { + route { + GET("/dsl") { + ServerResponse.ok().body(Dto("Hello World")) + } } } }