Introdução

Neste tutorial, iremos explorar a construção de microserviços utilizando Kotlin, Ktor e Exposed. O microserviço é uma arquitetura que permite desenvolver aplicações de forma modular, facilitando a escalabilidade e a manutenção. Vamos abordar desde a configuração do ambiente até a implementação de um serviço RESTful completo, incluindo o acesso a banco de dados e testes unitários. Este guia é ideal para desenvolvedores que desejam aproveitar o poder do Kotlin e a simplicidade do Ktor para construir aplicações modernas e eficientes. Você aprenderá a criar serviços que podem ser facilmente integrados e que respondem rapidamente às demandas do usuário em um ambiente de produção.

Etapas

  1. Configuração do Ambiente de Desenvolvimento

    Para começar, você precisará ter o JDK 11 ou superior e o IntelliJ IDEA instalado na sua máquina. Verifique se você possui o JDK com o comando `java -version`. Além disso, instale o Ktor e o Exposed como dependências no IntelliJ.

    commands
    # Verifique a versão do JDK
    java -version

  2. Criação do Projeto Ktor

    Utilize o Ktor para criar um novo projeto. Abra o IntelliJ IDEA, e selecione ‘New Project’. Escolha Ktor e configure seu projeto básico com o plugin Ktor. Inclua as dependências ‘Ktor Server Core’, ‘Ktor Server Netty’, ‘Ktor Serialization’, e ‘Exposed’.

    build.gradle.kts
    plugins {
        application
        kotlin("plugin.serialization") version "1.5.31"
    }
    
    application {
        mainClass.set("io.ktor.server.netty.EngineMain")
    }
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        implementation("io.ktor:ktor-server-core-jvm:1.6.7")
        implementation("io.ktor:ktor-server-netty-jvm:1.6.7")
        implementation("io.ktor:ktor-serialization:1.6.7")
        implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
        implementation("org.jetbrains.exposed:exposed-core:0.37.2")
        implementation("org.jetbrains.exposed:exposed-dao:0.37.2")
        implementation("org.jetbrains.exposed:exposed-jdbc:0.37.2")
        implementation("com.h2database:h2:1.4.200")
        testImplementation("io.ktor:ktor-server-tests-jvm:1.6.7")
    }

  3. Configuração do Banco de Dados com Exposed

    Crie uma nova classe para configurar a conexão com o banco de dados H2 utilizando Exposed. Esta classe habilitará a configuração do banco de dados em memória para testes rápidos.

    DatabaseFactory.kt
    import org.jetbrains.exposed.sql.*
    import org.jetbrains.exposed.sql.transactions.transaction
    
    object DatabaseFactory {
        fun init() {
            Database.connect(
                url = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;"
                driver = "org.h2.Driver",
                user = "root",
                password = ""
            )
            transaction { SchemaUtils.create(Produtos) }
        }
    }

  4. Criação da Tabela `Produtos`

    Implemente a tabela `Produtos` utilizando Exposed. Esta tabela armazenará os dados dos produtos que seu microserviço irá manipular.

    Produto.kt
    import org.jetbrains.exposed.sql.Table
    
    object Produtos : Table() {
        val id = long("id").autoIncrement().primaryKey()
        val nome = varchar("nome", 50)
        val preco = decimal("preco", 10, 2)
    }

  5. Implementação do Service `ProdutoService`

    Crie a classe `ProdutoService` que contém a lógica de negócios para gerenciar os produtos. Use Exposed para interagir com a tabela Produtos no banco de dados.

    ProdutoService.kt
    import org.jetbrains.exposed.sql.*
    import org.jetbrains.exposed.sql.transactions.transaction
    
    data class Produto(val id: Long, val nome: String, val preco: Double)
    
    class ProdutoService {
        fun findAll(): List<Produto> = transaction {
            Produtos.selectAll().map { Produto(it[Produtos.id], it[Produtos.nome], it[Produtos.preco].toDouble()) }
        }
    
        fun create(nome: String, preco: Double): Produto = transaction {
            val id = Produtos.insertAndGetId {
                it[this.nome] = nome
                it[this.preco] = preco.toBigDecimal()
            }
            Produto(id.value, nome, preco)
        }
    }

  6. Implementação do Controlador `ProdutoController`

    Implemente o controlador `ProdutoController` para expor os endpoints RESTful que permitirão operações CRUD.

    ProdutoController.kt
    import io.ktor.application.*
    import io.ktor.response.*
    import io.ktor.routing.*
    import io.ktor.http.*
    import io.ktor.request.*
    
    fun Route.produtoRoutes(produtoService: ProdutoService) {
        route("/produtos") {
            get {
                call.respond(produtoService.findAll())
            }
            post {
                val produto = call.receive<Produto>()
                call.respond(produtoService.create(produto.nome, produto.preco))
            }
        }
    }

  7. Configuração do Ktor Application

    No arquivo `Application.kt`, configure as rotas do Ktor e inicie a aplicação Ktor.

    Application.kt
    import io.ktor.application.*
    import io.ktor.features.*
    import io.ktor.serialization.*
    import io.ktor.server.engine.*
    import io.ktor.server.netty.*
    
    fun main() {
        embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
            install(ContentNegotiation) { json() }
            DatabaseFactory.init()
            routing {
                produtoRoutes(ProdutoService())
            }
        }.start(wait = true)
    }

  8. Implementação de Testes Unitários

    Utilize as bibliotecas de teste do Ktor para criar testes unitários para seu `ProdutoService` e garanta que a lógica esté funcionando corretamente.

    ProdutoServiceTest.kt
    import io.ktor.server.testing.*
    import kotlin.test.Test
    import kotlin.test.assertEquals
    import kotlin.test.assertTrue
    
    class ProdutoServiceTest {
        @Test
        fun `test criar produto`() {
            withTestApplication({}) {
                val produtoService = ProdutoService()
                val produto = produtoService.create("Produto Teste", 10.0)
                assertTrue(produto.id > 0)
            }
        }
    }

  9. Executando a Aplicação e Testes

    Compile e inicie a aplicação utilizando o Gradle. Use ferramentas como Postman ou cURL para testar os endpoints da API que você criou.

    commands
    # Compilar e executar a aplicação
    gradle run
    # Testar a criação de um produto
    curl -X POST -H 'Content-Type: application/json' -d '{"nome":"Produto Novo","preco":29.99}' http://localhost:8080/produtos

Conclusão

Neste guia, você aprendeu a implementar um microserviço utilizando Kotlin, Ktor e Exposed. Desde a configuração do ambiente até a criação de um serviço RESTful abrangente, cobrimos todos os aspectos importantes. A arquitetura de microserviços permite que você desenvolva aplicações escaláveis e manuteníveis. Agora, você está preparado para criar suas próprias aplicações com Kotlin e explorar suas ricas bibliotecas e frameworks. Lembre-se de que a prática contínua é fundamental para aprimorar suas habilidades em desenvolvimento de software.

Hashtags

#Kotlin #Ktor #Exposed #Microserviços #DesenvolvimentoDeSoftware