$30 off During Our Annual Pro Sale. View Details »

Microserviços em Kotlin com Dropwizard

Microserviços em Kotlin com Dropwizard

Apresentação para o Kotlin Meetup São Paulo em 25 de Julho de 2020

felipecsl

June 25, 2020
Tweet

More Decks by felipecsl

Other Decks in Technology

Transcript

  1. Microserviços em Kotlin com
    Dropwizard
    Felipe Lima
    Kotlin Meetup São Paulo
    25 de Junho de 2020
    felipecsl.com
    @felipecsl

    View Slide

  2. Introdução

    View Slide

  3. Um pouco de história…

    View Slide

  4. View Slide

  5. View Slide

  6. Dropwizard

    View Slide

  7. Dropwizard @ Airbnb

    View Slide

  8. Fonte: website oficial - dropwizard.io
    “Dropwizard is a Java framework for
    developing ops-friendly, high-
    performance, RESTful web services.”

    View Slide

  9. “Elefante na sala"

    View Slide

  10. “Tá, mas por que diabos eu
    deveria usar Dropwizard ao invés
    de ”

    View Slide

  11. Fonte: https://blog.overops.com/java-bootstrap-dropwizard-vs-spring-boot
    Dropwizard vs. Spring Boot

    View Slide

  12. View Slide

  13. Meu favorito

    View Slide

  14. • Criado em 2011 no Yammer

    • Arquitetura modular

    • Foco em produtividade, “get things done”

    • Java centric

    • Utiliza Jersey e Jetty
    Características

    View Slide

  15. Modularidade
    https://modules.dropwizard.io/official/

    View Slide

  16. Simplicidade
    companion object {
    @Throws(Exception::class)
    @JvmStatic
    fun main(args: Array) {
    BrokerApplication().run(*args)
    }
    }

    View Slide

  17. Simplicidade
    class BrokerApplication : Application() {
    override fun initialize(bootstrap: Bootstrap) {
    bootstrap.apply {
    addBundle(webSocketBundle)
    addBundle(SslReloadBundle())
    addBundle(RedirectBundle(HttpsRedirect()))
    }
    }
    override fun run(configuration: BrokerConfiguration, environment: Environment) {
    userDao = DaoFactory(environment, configuration).newDao(UserDao::class.java)
    sessionManager = SessionManagerFactory.newInstance(
    userDao, objectMapper, configuration
    )
    environment.jersey().register(StatusResource(sessionManager))
    environment.healthChecks().register("template", BrokerHealthCheck())
    environment.jersey().register(UsersResource(userDao, sessionManager))
    }

    View Slide

  18. View Slide

  19. REST
    "Eclipse Jersey is a REST framework
    that provides a JAX-RS (JSR-370)
    implementation”
    https://eclipse-ee4j.github.io/jersey/

    View Slide

  20. REST
    https://github.com/jax-rs/spec/blob/master/spec.pdf

    View Slide

  21. REST
    @Path("/status")
    @Produces(MediaType.APPLICATION_JSON)
    class StatusResource(private val sessionManager: SessionManager) {
    @GET
    @Timed
    fun healthStatus(): HealthStatus {
    return HealthStatus(sessionManager.totalActiveSessions())
    }
    }

    View Slide

  22. REST
    @Path("/users")
    @Produces(MediaType.APPLICATION_JSON)
    class UsersResource(
    private val userDao: UserDao,
    private val sessionManager: SessionManager
    ) {
    @POST
    @Timed
    @Consumes(MediaType.APPLICATION_JSON)
    fun create(user: User): Response {
    userDao.insert(user)
    return Response.ok().build()
    }
    @PUT
    @Timed
    @Consumes(MediaType.APPLICATION_JSON)
    fun update(user: User): Response {
    userDao.updateUserIdByFcmToken(user)
    return Response.ok().build()
    }
    }

    View Slide

  23. Configurações
    • Único arquivo YAML

    • Passado por parâmetro para o server via linha de comando

    • Pode ser utilizado para centralizar todas as configurações do servidor

    View Slide

  24. Configurações
    // build.gradle
    run {
    args 'server', 'src/dist/config/broker.dev.yml'
    }

    View Slide

  25. Configurações
    database:
    driverClass: org.postgresql.Driver
    user: felipecsl
    password:
    url: jdbc:postgresql://localhost/clairvoyance_dev
    properties:
    charSet: UTF-8
    # the maximum amount of time to wait on an empty pool before throwing an exception
    maxWaitForConnection: 1s
    # the SQL query to run when validating a connection's liveness
    validationQuery: "/* MyService Health Check */ SELECT 1"
    # the minimum number of connections to keep open
    minSize: 8
    logValidationErrors: true
    # the maximum number of connections to keep open
    maxSize: 32
    # whether or not idle connections should be validated
    checkConnectionWhileIdle: false
    # the amount of time to sleep between runs of the idle connection validation, abandoned cleaner and idle pool resizing
    evictionInterval: 10s
    # the minimum amount of time an connection must sit idle in the pool before it is eligible for eviction
    minIdleTime: 1 minute
    server:
    applicationContextPath: /
    applicationConnectors:
    - type: http
    port: 8080

    View Slide

  26. Configurações
    class BrokerApplication : Application() {
    // ...
    }

    View Slide

  27. Configurações
    class BrokerConfiguration : Configuration() {
    @JsonProperty
    var fcmCredentialJsonPath: String? = null
    @JsonProperty
    var iceConfigFilePath: String? = null
    @JsonProperty
    var database: DataSourceFactory = DataSourceFactory()
    }

    View Slide

  28. Database
    implementation "io.dropwizard:dropwizard-jdbi3:$dropwizardVersion"

    View Slide

  29. Database
    @RegisterRowMapper(UserMapper::class)
    interface UserDao {
    @SqlQuery("SELECT * FROM users") fun all(): List
    @SqlQuery("SELECT * FROM users WHERE user_id = :user_id")
    fun findByUserId(@Bind("user_id") userId: String): User?
    @SqlUpdate("UPDATE users SET user_id = :user_id,
    fcm_token = :fcm_token WHERE ID = :id")
    fun updateById(@BindBean user: User): Int
    @SqlUpdate("INSERT INTO users (user_id, fcm_token)
    VALUES (:user_id, :fcm_token)")
    fun insert(@BindBean user: User): Int
    @SqlUpdate("DELETE FROM users") fun deleteAll(): Int
    }

    View Slide

  30. Database Migrations
    // build.gradle
    plugins {
    id "org.flywaydb.flyway" version "6.4.0"
    }
    flyway {
    url = 'jdbc:h2:file:./clairvoyance_test'
    user = ‘fulano_de_tal’
    }

    View Slide

  31. Database Migrations
    private fun initFlyway(configuration: BrokerConfiguration) {
    val database = configuration.database
    Flyway.configure()
    .dataSource(database.url, database.user, database.password)
    .load()
    .migrate()
    }

    View Slide

  32. Database Migrations

    View Slide

  33. Frontend
    • Freemarker

    • Mustache

    View Slide

  34. Testing
    testImplementation "io.dropwizard:dropwizard-testing:$dropwizardVersion"

    View Slide

  35. Testing @ExtendWith(DropwizardExtensionsSupport::class)
    class BrokerApplicationTest {
    private val client = OkHttpClient.Builder().build()
    private val localPort = DROPWIZARD.localPort
    @Test fun status() {
    val client = JerseyClientBuilder().build()
    val result = client
    .target(“http://localhost:$localPort/status")
    .request()
    .get(String::class.java)
    assertThat(result).isEqualTo("""{"activeSessions":0}""")
    }
    companion object {
    private val DROPWIZARD = DropwizardAppExtension(
    BrokerApplication::class.java,
    ResourceHelpers.resourceFilePath("broker.yml")
    )
    }
    }

    View Slide

  36. Perguntas?

    View Slide

  37. Obrigado!

    View Slide