I have worked with Spring Framework for ages and it still manages to surprise me with how cutting edge it continues to be but at the same time enabling a developer to put together a fairly sane app.
The most recent surprise was with how it enables programming a web application with Kotlin coroutines. Coroutines is a fairly complicated concept to get my head around, but it is starting to click now and while trying out some samples I thought it may be a good idea to put an end to end web application in place.
Thanks to the excellent Spring Boot starters it was not difficult at all. Along the way I also decided to experiment with r2dbc which is another involved technology to interact with a database using reactive streams. Combining reactive streams for interacting with the database but using coroutines in the rest of the layers was not difficult at all. In this post I will not be covering the nuances of what I had to do to get the sample to work, but will cover one thin slice of what it looks like. The sample is here in my github repo and should be fairly self explanatory.
I have to acknowledge that Nicolas Frankel's blog post provided me a lot of pointers in getting the working code just right
A Slice of functionality
import org.springframework.data.repository.kotlin.CoroutineCrudRepository import samples.geo.domain.City interface CityRepo : CoroutineCrudRepository<City, Long>
fun getCities(): Flow<City> { return cityRepo.findAll() } suspend fun getCity(id: Long): City? { return cityRepo.findById(id) }
suspend fun getCities(request: ServerRequest): ServerResponse { val cities = cityService.getCities() .toList() return ServerResponse.ok().bodyValueAndAwait(cities) } suspend fun getCity(request: ServerRequest): ServerResponse { val id = request.pathVariable("id").toLong() val city = cityService.getCity(id) return city ?.let { ServerResponse.ok().bodyValueAndAwait(it) } ?: ServerResponse.notFound().buildAndAwait() }which is then composed at the web layer the following way:
object AppRoutes { fun routes(cityHandler: CityHandler): RouterFunction<*> = coRouter { accept(MediaType.APPLICATION_JSON).nest { GET("/cities", cityHandler::getCities) GET("/cities/{id}", cityHandler::getCity) ... } } }The "coRouter" dsl above provides the functionality to convert the Kotlin coroutine types to the Spring WebFlux RouterFunction type This is essentially it. The code and tests for all this fairly sophisticated set of technology(r2dbc, coroutines, webflux, reactive streams etc) that this encompasses is fairly small as can be seen from the github repository
No comments:
Post a Comment