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

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

7fd4ba468da56bb5330a6352c1b54f52?s=128

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
  2. Introdução

  3. Um pouco de história…

  4. None
  5. None
  6. Dropwizard

  7. Dropwizard @ Airbnb

  8. Fonte: website oficial - dropwizard.io “Dropwizard is a Java framework

    for developing ops-friendly, high- performance, RESTful web services.”
  9. “Elefante na sala"

  10. “Tá, mas por que diabos eu deveria usar Dropwizard ao

    invés de <insert other framework name>”
  11. Fonte: https://blog.overops.com/java-bootstrap-dropwizard-vs-spring-boot Dropwizard vs. Spring Boot

  12. None
  13. Meu favorito

  14. • Criado em 2011 no Yammer • Arquitetura modular •

    Foco em produtividade, “get things done” • Java centric • Utiliza Jersey e Jetty Características
  15. Modularidade https://modules.dropwizard.io/official/

  16. Simplicidade companion object { @Throws(Exception::class) @JvmStatic fun main(args: Array<String>) {

    BrokerApplication().run(*args) } }
  17. Simplicidade class BrokerApplication : Application<BrokerConfiguration>() { override fun initialize(bootstrap: Bootstrap<BrokerConfiguration>)

    { 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)) }
  18. None
  19. REST "Eclipse Jersey is a REST framework that provides a

    JAX-RS (JSR-370) implementation” https://eclipse-ee4j.github.io/jersey/
  20. REST https://github.com/jax-rs/spec/blob/master/spec.pdf

  21. REST @Path("/status") @Produces(MediaType.APPLICATION_JSON) class StatusResource(private val sessionManager: SessionManager) { @GET

    @Timed fun healthStatus(): HealthStatus { return HealthStatus(sessionManager.totalActiveSessions()) } }
  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() } }
  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
  24. Configurações // build.gradle run { args 'server', 'src/dist/config/broker.dev.yml' }

  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
  26. Configurações class BrokerApplication : Application<BrokerConfiguration>() { // ... }

  27. Configurações class BrokerConfiguration : Configuration() { @JsonProperty var fcmCredentialJsonPath: String?

    = null @JsonProperty var iceConfigFilePath: String? = null @JsonProperty var database: DataSourceFactory = DataSourceFactory() }
  28. Database implementation "io.dropwizard:dropwizard-jdbi3:$dropwizardVersion"

  29. Database @RegisterRowMapper(UserMapper::class) interface UserDao { @SqlQuery("SELECT * FROM users") fun

    all(): List<User> @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 }
  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’ }
  31. Database Migrations private fun initFlyway(configuration: BrokerConfiguration) { val database =

    configuration.database Flyway.configure() .dataSource(database.url, database.user, database.password) .load() .migrate() }
  32. Database Migrations

  33. Frontend • Freemarker • Mustache

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

  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") ) } }
  36. Perguntas?

  37. Obrigado!