title: Spring Boot Rest Service With Kotlin Coroutines
body: <p>I am writing a Spring Boot Rest Service in Kotlin. I want to use coroutines as an alternative to Webflux to achieve non-blocking asynchronous behavior. I am using Spring Boot 2.1 and know that I cannot achieve true non-blocking behavior because I am blocking at <code>Controller</code>. However, I am okay with that for now till the time Spring Boot 2.2 is generally available.</p>
  
  <p>My app is three-layered ie Controller->Service->Repository. In repository, I am calling other services ie network calls and have marked the method as suspend.</p>
  
  <p>I want to ensure if this is the right approach, additionally, does call to suspend fun inside <code>ResourceService</code> blocks the caller thread?</p>
  
  <p>Also after reading <a href="https://medium.com/@elizarov/blocking-threads-suspending-coroutines-d33e11bf4761" rel="nofollow noreferrer">https://medium.com/@elizarov/blocking-threads-suspending-coroutines-d33e11bf4761</a> by Roman Elizarov I am not sure if I should use <code>withContext</code> along with all of my suspending functions?</p>
  
  <pre class="lang-java prettyprint-override"><code>package my.springbootapp
  
  import kotlinx.coroutines.Dispatchers
  import kotlinx.coroutines.asCoroutineDispatcher
  import kotlinx.coroutines.runBlocking
  import kotlinx.coroutines.withContext
  import mu.KotlinLogging
  import org.springframework.boot.SpringApplication
  import org.springframework.boot.autoconfigure.SpringBootApplication
  import org.springframework.stereotype.Repository
  import org.springframework.stereotype.Service
  import org.springframework.web.bind.annotation.GetMapping
  import org.springframework.web.bind.annotation.PathVariable
  import org.springframework.web.bind.annotation.RestController
  import java.util.concurrent.Executors
  
  val logger = KotlinLogging.logger { }
  
  @SpringBootApplication
  class App
  
  fun main(args: Array&lt;String&gt;) {
      SpringApplication.run(App::class.java, *args)
  }
  
  @RestController
  class Controller(private val resourceService: ResourceService) {
      private val dispatcher = Executors.newFixedThreadPool(5).asCoroutineDispatcher()
  
      @GetMapping("/resource/{id}")
      fun getResource(@PathVariable("id") id: String) = runBlocking(dispatcher) {
          resourceService.get(id).also { logger.info { Thread.currentThread().name + "Returning $it" } }
      }
  }
  
  @Service
  class ResourceService(private val networkResourceRepository: NetworkResourceRepository) {
  
      suspend fun get(id: String): Resource {
          logger.info { Thread.currentThread().name + "Getting resource" }
          return networkResourceRepository.get(id)
      }
  }
  
  @Repository
  class NetworkResourceRepository {
      suspend fun get(id: String): Resource = withContext(Dispatchers.IO) {
          logger.info { Thread.currentThread().name + "Getting resource from n/w" }
          //IO operation
          Resource("resource data")
      }
  }
  
  data class Resource(val data: String)
  </code></pre>