Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Micronaut with Kotlin Coroutines

Mohit S
February 03, 2021

Micronaut with Kotlin Coroutines

Learn how to build microservices with Micronaut.

Mohit S

February 03, 2021
Tweet

More Decks by Mohit S

Other Decks in Programming

Transcript

  1. Micronaut with Kotlin Coroutines • Building REST API • Coroutines

    • Data Access • Circuit breakers • Load Balancing
  2. What is Micronaut? • JVM Framework for building microservices •

    Created by Graham Rose • Polygot - Java, Kotlin or Groovy
  3. Benefits • Fast Startup & Small Memory • Meta programming

    • Reactive • Ahead-of-Time Compilation (AOT)
  4. Project Creation CLI Tool • Download via SDKMAN • Create

    scaffolding for app • Create controllers, beans or clients
  5. Create Controller mn create-controller com.learn.micronautapp.Greeting | Rendered controller to src/

    ... /GreetingController.kt | Rendered test to src/…/GreetingControllerTest.kt
  6. Testing @MicronautTest class GreetingControllerTest(val embeddedServer: EmbeddedServer) { 
 @Client("/") interface

    GreetingClient { @Get("/greet/{name}") fun greetings(name: String): String } }
  7. Testing @MicronautTest class GreetingControllerTest(val embeddedServer: EmbeddedServer) { 
 @Test fun

    `should get greeting`() { val greeting = greetingClient.greetings("Micronaut") } }
  8. Testing @MicronautTest class GreetingControllerTest(val embeddedServer: EmbeddedServer) { 
 @Test fun

    `should get greeting`() { val greeting = greetingClient.greetings("Micronaut") greeting shouldEqual "Greetings Micronaut" } }
  9. Services HTTP/1.1 200 OK 
 
 content-type: text/plain 
 


    content-length: 19 
 
 connection: keep-alive 
 
 Greetings micronaut 
 GET http: // localhost:8080/greet/micronaut
  10. Coroutines Support class Router { 
 Flowable.defer(() -> { if

    (isKotlinSuspendingFunction) { return executeKotlinSuspendingFunction( ... ); } else { ... } }) }
  11. Coroutines Support class Router { 
 Flowable.defer(() -> { if

    (isKotlinSuspendingFunction) { return executeKotlinSuspendingFunction( ... ); } else { ... } }) }
  12. Coroutines Support Publisher executeKotlinSuspendingFunction( ... ) { if (isKotlinCoroutineSuspended) {

    if (isKotlinFunctionReturnTypeUnit) { return Completable.fromPublisher( ... ).toFlowable(); } else { } } }
  13. Coroutines Support Publisher executeKotlinSuspendingFunction( ... ) { if (isKotlinCoroutineSuspended) {

    if (isKotlinFunctionReturnTypeUnit) { return Completable.fromPublisher( ... ).toFlowable(); } else { return Publishers.fromCompletableFuture(…); } } }
  14. Using Dispatcher @Controller class GreetingController(val executor: ExecutorService) { 
 val

    coroutineDispatcher: CoroutineDispatcher init { coroutineDispatcher = executor.asCoroutineDispatcher() } }
  15. Using Dispatcher @Controller class GreetingController(val executor: ExecutorService) { 
 @Get(uri="/greet/{name}")

    suspend fun greetings(name: String) = 
 withContext(coroutineDispatcher) { } }
  16. Coroutine Support class FlowConverterRegistrar { @Override public void register( ...

    ) { addConverter( ... , flow -> Flowable.fromPublisher(ReactiveFlowKt.asPublisher(flow)) ); } }
  17. Coroutine Support class FlowConverterRegistrar { @Override public void register( ...

    ) { addConverter( ... , flow -> Flowable.fromPublisher(ReactiveFlowKt.asPublisher(flow)) ); } }
  18. Micronaut with Kotlin Coroutines • Building REST API • Coroutines

    • Data Access • Circuit breakers • Load Balancing
  19. Task REST API GET /tasks/list GET /tasks/{taskId} POST /tasks {

    “id”: taskId “description”: “ ” }
  20. Task REST API GET /tasks/list GET /tasks/{taskId} PUT /tasks {

    “id”: taskId “description”: “ ” } POST /tasks
  21. Data Access data class Task( @Column(name = "description", nullable =

    false, unique = true) val description: String = "" )
  22. Data Access class TasksRepository(val entityManager: EntityManager) { fun findById(taskId: Long):

    Task { return entityManager.find(Task :: class.java, taskId) } }
  23. Data Access class TasksRepository(val entityManager: EntityManager) { fun save(description: String):

    Task { val task = Task(description = description) entityManager.persist(task) return task } }
  24. Data Access class TasksRepository(val entityManager: EntityManager) { fun update(taskId: Long,

    description: String): Int { val query = "UPDATE Task t SET description = :description where taskId = :taskId" } }
  25. Data Access class TasksRepository(val entityManager: EntityManager) { fun update(taskId: Long,

    description: String): Int { return entityManager.createQuery(sql) }
  26. Data Access class TasksRepository(val entityManager: EntityManager) { fun update(taskId: Long,

    description: String): Int { return entityManager.createQuery(sql) .setParameter(”taskId", taskId) .setParameter(“description", description) .executeUpdate() }
  27. Data Access class TasksRepository(val entityManager: EntityManager) { fun delete(taskId: Long)

    { val task = findById(taskId) task ?. let { entityManager.remove(it) } } }
  28. Data Access @Controller("/tasks") class TaskController(private val taskRepository: TaskRepository) { @Post

    suspend fun save(@Body @Valid command: TaskSaveCommand) { val task = taskRepository.save(command.description) } }
  29. Data Access @Controller("/tasks") class TaskController(private val taskRepository: TaskRepository) { @Post

    suspend fun save(@Body @Valid command: TaskSaveCommand) { val task = taskRepository.save(command.description) return HttpResponse.created(task) } }
  30. Data Access @Controller("/tasks") class TaskController(private val taskRepository: TaskRepository) { @Delete("/{taskId}")

    fun delete(taskId: Long): HttpResponse<Task> { taskRepository.delete(taskId) return HttpResponse.noContent() } }
  31. @Controller("/tasks") class TaskController(private val taskRepository: TaskRepository) { @Delete("/{taskId}") fun delete(taskId:

    Long): HttpResponse<Task> { taskRepository.delete(taskId) return HttpResponse.noContent() } } Services org.hibernate.dialect.Dialect - Using dialect: org.hibernate.dialect.H2Dialect
  32. Configure Database micronaut: application: name: complete datasources: default: url: {JDBC_URL:`

    ... `} username: ${JDBC_USER:sa} password: ${JDBC_PASSWORD:""} driverClassName: ${JDBC_DRIVER:org.h2.Driver}
  33. Summary • Setup Controller for REST API • HTTP Requests

    & Responses • Data Access • Create Client 

  34. Micronaut with Kotlin Coroutines • Building REST API • Coroutines

    • Data Access • Circuit breakers • Load Balancing
  35. Micronaut with Kotlin Coroutines • Building REST API • Coroutines

    • Data Access • Circuit breakers • Load Balancing
  36. @Controller("/tasks") class TaskController(private val taskRepository: TaskRepository) { @Delete("/{taskId}") fun delete(taskId:

    Long): HttpResponse<Task> { taskRepository.delete(taskId) return HttpResponse.noContent() } } Services Registered service with Consul io.micronaut.runtime.Micronaut - Server Running: http: // localhost:44004
  37. Micronaut with Kotlin Coroutines • Building REST API • Coroutines

    • Data Access • Circuit breakers • Load Balancing
  38. Resources • Introduction to Micronaut • Graeme Rocher 
 •

    Talk on coroutines! 
 
 https: // codingwithmohit.com/talks/