Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support routers which inject beans #67

Merged
merged 1 commit into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions docs/webmvc.md
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ open class AopApplication : SpringFunkApplication {

override fun dsl(): SpringDslContainer.() -> Unit = {
webmvc {
router {
GET("dsl"){
ServerResponse.ok().body("dsl")
routes {
route {
GET("dsl"){
ServerResponse.ok().body("dsl")
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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

@SpringDslMarker
class RoutesDsl {
private val routes = mutableListOf<BeanDefinitionDsl.BeanSupplierContext.() -> RouterFunction<ServerResponse>>()

@SpringDslMarker
fun router(f: BeanDefinitionDsl.BeanSupplierContext.() -> RouterFunction<ServerResponse>) {
routes.add(f)
}

@SpringDslMarker
fun route(router: RouterFunctionDsl.() -> Unit) {
routes.add { org.springframework.web.servlet.function.router(router) }
}

internal fun merge(f: BeanDefinitionDsl.BeanSupplierContext): RouterFunction<ServerResponse> =
routes.map { it.invoke(f) }.reduce(RouterFunction<ServerResponse>::and)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<ServerResponse>? = null
internal var routes: RoutesDsl? = null
internal var enableWebmvcDsl: EnableWebMvcDsl? = null
internal var converterDsl: WebMvcConverterDsl? = null

Expand All @@ -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)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -55,8 +56,12 @@ class WebmvcInitializer : ApplicationContextInitializer<GenericApplicationContex
standardJacksonObjectMapperBuilderCustomizer(context, jacksonProps)
}
}
routerDsl?.run {
context.registerBean<RouterFunction<ServerResponse>> { this }
routes?.also { r ->
beans {
bean {
r.merge(this)
}
}.initialize(context)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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(
Expand All @@ -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<ServiceClass>()
}
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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ class ExampleApplication : SpringFunkApplication {
enableWebMvc {
jetty()
}
router {
GET("/dsl") {
log.debug { "handling hello world request" }
ServerResponse.ok().body("Hello World")
routes {
route {
GET("/dsl") {
log.debug { "handling hello world request" }
ServerResponse.ok().body("Hello World")
}
}
}
}
Expand Down