Desenvolvimento

6 set, 2016

Vamos falar sobre Kotlin no backend

Publicidade

Este artigo é o primeiro de uma série que pretende abordar como fazer um backend em Kotlin. Hoje, a ideia é apresentar o Kotlin com um programa simples e mostrar como configurar um ambiente inicial de desenvolvimento.

O que é Kotlin?

Kotlin é uma linguagem de programação criada pela JetBrains, que roda em cima da JVM, concisa, segura, pragmática e focada em interoperabilidade. Pode ser uma alternativa ao Java, uma vez que sua capacidade Funcional e Orientada a Objetos inova nas possibilidades de criação.

Por que Kotlin?

Porque é muito mais gostoso “codar” com ela (sim, estou realmente curtindo bons momentos estudando).

  • Open Source;
  • 100% interoperável com Java, gerando bytecode da JVM;
  • Pode ser utilizada em conjunto com diversos frameworks e bibliotecas disponíveis;
  • Menos código;
  • Null Safety;
  • Funcional e Orientada a Objetos;
  • Pode ser utilizada no desenvolvimento de apps Android.

Como começar?

Primeiro, é preciso baixar e instalar o Intellij IDEA neste site. É preciso também ter uma JDK instalada e configurada.

Com o Intellij IDEA instalado e iniciado, vá em Preferences (OSX) ou Settings (Windows/Linux) -> Plugins -> Browse Repositories e escreva Kotlin. Clique em Install. Pronto, agora que está tudo instalado é hora de “codar”!

Criando seu primeiro programa com Kotlin

Clique em File -> New -> Project, selecione Kotlin(JVM) e clique em Next:

0--DQ4O6NylFljjf8G-

O meu Project Name será OlaKotlin. Escolha o seu e clique em Finish:

0-06Ng1jPTcey4BZI_-

Criei o pacote ola.kotlin. Você pode escolher o que quiser!

0-xyZQlGjWQgOVLQfh-

Clique com o botão direito no pacote recém-criado e crie um novo arquivo Kotlin:

0-X7Nt3Ps6vPN_ItJs-

Dei o nome de Ola (por falta de criatividade mesmo kkk).

Primeira função Kotlin

Por que não começar com o famoso Hello World simples e básico? Em Java escrevemos este código em um método main, mas no Kotlin escreveremos este código no fun main.

Abra o arquivo Ola.kt (no meu caso) e escreva o seguinte código:

package ola.kotlin
 
/**
 * Created by Kleber on 30/05/2016.
 */
fun main(args: Array<String>) {
    val stringKotlin = "Kotlin"
    println("Olá $stringKotlin")
}

Clique com o botão direito e execute.

Veja o resultado no console: Olá, Kotlin!

Note algumas coisas interessantes neste programa: menos código, variável sem definir qual o tipo, println menos verboso e interpolação de strings com strings templates ($). Simples, não?!

Agora vamos criar algo um pouco mais complexo usando o SpringBoot para levantar um serviço REST simples em Jersey.

Início

Vamos utilizar o Gradle para fazer build e gerenciar as dependências do SpringBoot no projeto. Para isso, crie uma pasta, execute o gradle e importe no IntelliJ. Criei a pasta ServicoKotlin, mas fique à vontade para escolher a sua.

gradle init –type java-library

Ele vai criar a seguinte estrutura:

1-xI21J1RD44CkVH5t6KZ_sg

Com o projeto importado no IntelliJ IDEA, vamos configurar o Gradle para resolver dependências, plugins e o build de nosso projeto.

Abra o arquivo build.gradle, que se encontra na raiz do projeto, e substitua pelo o seguinte conteúdo:

buildscript {
    // Neste bloco declare variaveis das versoes das principais dependencias e plugins
    ext {
        kotlinVersion = '1.0.3'
        springBootVersion = '1.4.0.RELEASE'
        jacksonModuleKotlinVersion = '2.7.5'
    }
    // Neste bloco declare onde encontrar dependencias para os plugins
    repositories {
        //mavenLocal()
        mavenCentral()
        //jcenter()
    }
    // Neste bloco declare as dependencias dos plugins
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
    }
}
 
// Aplique os plugins abaixo para o suporte do Gradle
apply plugin: 'idea'
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'spring-boot'
 
// Neste bloco declare onde encontrar dependencias para o projeto
repositories {
    // Use 'jcenter' para resolver dependencias do projeto
    // Podem ser declarados repositorios Maven/Ivy/file
    jcenter()
    //mavenLocal()
    //mavenCentral()
}
 
// Neste bloco declare suas dependecias
dependencies {
    compile("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
    compile("org.jetbrains.kotlin:kotlin-runtime:$kotlinVersion")
    compile("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")
 
    compile("org.springframework.boot:spring-boot-starter:$springBootVersion")
    compile("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
    compile("org.springframework.boot:spring-boot-starter-jersey:$springBootVersion")
    compile("org.springframework.boot:spring-boot-starter-undertow:$springBootVersion")
 
    compile("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonModuleKotlinVersion")
 
    testCompile("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
    testCompile("org.jetbrains.kotlin:kotlin-test-junit:$kotlinVersion")
    testCompile("org.springframework.boot:spring-boot-starter-test:$springBootVersion")
}
 
// Neste bloco declare o nome e versao do arquivo .jar
jar {
    baseName = 'ServicoKotlin'
    version =  '1.0.0-SNAPSHOT'
}
 
// Neste bloco declare onde ficarao os sources e testes
sourceSets {
    main {
        kotlin {
            srcDirs 'src/main/kotlin'
        }
    }
    test {
        kotlin {
            srcDirs 'src/test/kotlin'
        }
    }
}

Criando nossas classes

Clique com o botão direito nas pastas java em main.java e test.java e as delete. Também com o botão direito, clique na pasta main, crie o diretório kotlin e marque este como Sources Root. A estrutura deve ficar assim: src/main/kotlin, igual ao que está no sourceSets do script build.gradle.

Crie um pacote à sua escolha (o meu é org.kotlin) e crie um arquivo kotlin dentro com o nome de App. A extensão dos arquivos kotlin é .kt. Neste arquivo vamos criar nossa classe e a função main para o SpringBoot.

package org.kotlin
 
import com.fasterxml.jackson.module.kotlin.KotlinModule
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.Bean
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder
import org.springframework.web.client.RestTemplate
 
/**
 * Created by Kleber on 04/08/2016.
 */
@SpringBootApplication
open class App {
 
    @Bean
    open fun restTemplate(): RestTemplate {
        val restTemplate = RestTemplate()
        return restTemplate
    }
 
    @Bean
    open fun objectMapperBuilder(): Jackson2ObjectMapperBuilder = Jackson2ObjectMapperBuilder().modulesToInstall(KotlinModule())
}
 
fun main(args: Array<String>) {
    SpringApplication.run(App::class.java, *args)
}

Vamos, agora, detalhar este trecho:

@SpringBootApplication é uma anotação de conveniência, que marca a classe com as seguintes anotações com seus atributos default:

  • @Configuration: anota a classe como uma fonte de definições de beans para o contexto da aplicação;
  • @EnableAutoConfiguration: diz ao SpringBoot para começar a adicionar beans com base nas configurações de classpath e várias configurações de propriedade;
  • @ComponentScan: diz ao Spring para procurar outros componentes, configurações e serviços no pacote atual.

Modificador open na classe é o oposto do final do Java. Em Kotlin, todas as classes e métodos são final por padrão, e para o Spring elas não podem ser final devido ao uso de proxy CGLIB.

Uma função restTemplate com anotação @Bean cria uma instância do RestTemplate como um Bean do Spring.

Uma função objectMapperBuilder sem corpo (sim, em Kotlin isto é possível) tem anotação @Bean para registrá-lo no Jackson ObjectMapper.

Em Java, o método main( ) de um aplicativo é convencionalmente definido dentro da classe de aplicação anotada. Isso ocorre porque Java não suporta métodos de nível superior. Em Kotlin, no entanto, nós temos funções top-level. Assim, podemos tornar o principal ponto de entrada do SpringBoot muito mais simples. Com isto, a função main() é definida em uma classe chamada AppKt e não em uma classe App.

A função main() utiliza o método SpringApplication.run() do SpringBoot para iniciar um aplicativo.

O método run() retorna um ApplicationContext e este aplicativo, em seguida, recupera todos os beans que foram criados pela aplicação ou foram adicionados automaticamente graças ao SpringBoot. Note que o método run() recebe dois parâmetros: a classeApp::class.java e um *args, que detalharei melhor a seguir:

  • App::class.java: (::) logo após o nome da classe indica que iremos pegar uma referência à classe por reflection. O (.java) indica que queremos uma referência Java e nãoKotlin;
  • *args: * operador spread antes do array, insere todo o conteúdo do array no vararg do método run().

Vamos criar agora nossa configuração do Jersey. Crie uma arquivo Kotlin com nome de JerseyConfig e configure o Jersey como a seguir:

package org.kotlin.config
 
import org.glassfish.jersey.server.ResourceConfig
import org.springframework.context.annotation.Configuration
 
/**
 * Created by Kleber on 04/08/2016.
 */
@Configuration
open class JerseyConfig : ResourceConfig() {
    init {
        this.packages("org.kotlin")
    }
}

Vamos aos detalhes:

  • JerseyConfig : ResourceConfig(): herança e implementação de interfaces em Kotlin;
  • init { … }: Bloco inicializador será criado junto com a instância da classe.

Para criar nossa endpoint, crie um pacote chamado API e dentro crie um arquivo Kotlin com o nome de JerseyAPI. Veja o exemplo:

ackage org.kotlin.api
 
import org.springframework.stereotype.Component
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.QueryParam
import javax.ws.rs.core.MediaType
 
/**
 * Created by Kleber on 04/08/2016.
 */
@Component
@Path("/jersey")
class JerseyAPI {
 
    @GET
    @Path("/ola")
    @Produces(MediaType.APPLICATION_JSON)
    fun ola(@QueryParam("nome") nome: String): String {
        return "Olá, $nome, sou um ENDPOINT Jersey /GET"
    }
}

Crie um arquivo chamado application.properties com o conteúdo abaixo dentro da pasta resources do projeto. Aqui diremos ao SpringBoot que o Undertow (WebServer) vai subir na porta configurada.

server.port=1010

Execute com um duplo click a task bootRun, na visão de Gradle do IntelliJ IDEA.

1-WFsFrks2b42PUOZ4FqlXRQ

Abra um navegador e digite o seguinte na barra de endereços: http://localhost:1010/jersey/ola?nome=Mundo

Veja o resultado:

Olá, Mundo, sou um ENDPOINT Jersey /GET

E aí, deu certo? Se tiver qualquer dúvida, ou quiser dar alguma contribuição, fique à vontade nos comentários.

Espero que tenha gostado! Até a próxima.