Criando um Web Service base no Spring Boot com Kotlin

Alex Felipe
CollabCode
Published in
11 min readSep 25, 2017
Data Center com diversos servidores

Já precisou criar um ambiente capaz de permitir uma comunicação comum entre diversas plataformas distintas? Como por exemplo, uma aplicação Web se comunicando com aplicações Android ou iOS ou Desktop e vice-versa…

Se você já passou por essa necessidade e não chegou a uma conclusão, seus problemas acabaram!

Entendendo a utilização de Web Service para integrar sistemas

Quando lidamos com esse tipo de necessidade, uma solução bem comum é a utilização de um Web Service que é uma entidade na qual permite uma comunicação direta entre aplicações por meio de uma linguagem comum.

Em outras palavras, as nossas aplicações se comunicam diretamente com o WS com uma linguagem que ambas sabem lidar, como por exemplo, JSON, XML, CSV e etc… Em uma representação visual, temos o seguinte diagrama:

Diagrama apresentando a forma visual de um ambiente com Web Service

Observe que ambas as aplicações não fazem a mínima ideia da existência das outras, ou seja, a única interface que elas conhecem é apenas o WS…

Portanto, toda a raiz da nossa aplicação, como é o caso do nosso banco de dados, fica centralizado no WS e, dessa forma, todas as aplicações que consomem esse WS mantém as mesmas informações…

Como podemos ver, temos inúmeras vantagens, além das que vimos nesse resumo, ao optar por esse tipo de solução, mas também, chegamos a seguinte situação:

“Como faço para implementar um WS?”

Existem diversas maneiras de implementarmos um WS, de forma geral, tratá-se de uma aplicação Web servidora que pode ser desenvolvida em diversas linguagens de programação.

Neste artigo, aprenderemos a criar e configurar um WS base, isto é, utilizando o framework Spring Boot com Kotlin. Nesse momento você pode estar se perguntando:

“Mas o que é um WS base?”

De forma geral, trata-se de um WS que não vai ter uma integração com banco de dados, não fará um CRUD e nem vai responder da maneira ideal as requisições algo comum quando criamos as famosas APIs…

Enfim, o nosso foco inicial será apenas entender toda a parte base para construirmos um WS utilizando o Spring Framework.

Preparado? Bora começar então!

Preparando o ambiente

Para criar o projeto Spring Boot com todas as dependências necessárias, podemos utilizar o Spring Initializr que trata-se de uma ferramenta online para setup de projeto Spring Boot fornecida pela Pivotal (Empresa que mantém o Spring Framework).

Para este exemplo, iremos criar o projeto com a seguinte configuração:

Configuração utilizada para criar o projeto Spring Boot com Kotlin, Stack Web, JPA, hsqldb e DevTools

Repara que realizamos diversas configurações de uma vez, sendo assim, vamos esclarecer cada uma delas:

  • Gradle Project: essa configuração indica que o projeto será criado e gerenciado pela Build Tool Gradle. (Fique à vontade em usar o Maven caso seja sua preferida)
  • Kotlin: com essa opção o projeto já vem configurado para dar suporte a linguagem Kotlin
  • 1.5.6: trata-se da versão do Spring Boot que será configurado
  • Group: indica a organização que desenvolverá o projeto, ou seja, também reflete na construção dos nossos pacotes básicos
  • Artifact: refere-se ao nome do nosso projeto, nesse caso ceepws (Web Service)
  • Selected Dependencies: são as dependências padrões que iremos utilizar para configurar o nosso WS

Dentre as configurações mencionadas acima, não tem muito segredo… Mas ainda não está muito claro o motivo de optar pelas dependências selecionadas, sendo assim, vamos entender cada uma delas:

  • Web: permite a utilização de toda stack de desenvolvimento Web do Spring, ou seja, a partir dela, teremos a capacidade de configurar o nosso projeto para que ele seja um servidor capaz de responder a requisições tanto para aplicações Web convencionais como também para criarmos o nosso WS
  • JPA: habilita a possibilidade de utilizar o conceito de ORM por meio da especificação JPA. Também, essa dependência permite a utilização do projeto Spring Data que facilita e muito o processo de persistência e recuperação de dados
  • HSQLDB: é um driver para um banco de dados que pode ser salvo tanto em memória quanto em um arquivo, em outras palavras, com essa dependência temos a capacidade de usar um banco de dados sem a necessidade de instalar um programa pra isso, como é o caso do MySQL, SQL Server, Oracle e etc
  • DevTools: essa dependência é uma ferramenta do próprio Spring Boot para agilizar o processo de deployment do nosso servidor durante o desenvolvimento, para mais detalhes deixo a referência

Após adicionar todas as configurações mencionadas acima, basta apenas pedir para gerar o projeto no botão Generate Project. Em seguida, começará o download de um arquivo zip.

Este arquivo é o nosso projeto Spring, ou seja, assim que finalizar, extraia o projeto no local onde costuma deixar os seus projetos.

O objetivo do artigo é criar um WS capaz de armazenar as informações da App Ceep, que criamos neste artigo, futuramente. Dessa forma, seremos capazes de integrá-lo com o Ceep 😉

Ferramenta de desenvolvimento

Como ferramenta de desenvolvimento eu vou utilizar o IntelliJ IDEA Ultimate, por já dar suporte para o Kotlin e Gradle de forma nativa. Como também, por questão de preferência! 😅

Porém, nada impede de você usar outra ferramenta, como é o caso do Eclipse ou Netbeans. Caso preferir o Eclipse, recomendo que utilize a versão Spring Tool Suite, pois é uma ferramenta desenvolvida especificamente para projetos Spring.

Lembre-se: o suporte nativo para o Kotlin é por meio do IntelliJ, portanto, se escolher outra IDE, como é o caso do Eclipse ou Netbeans, vai precisar configurar o suporte da linguagem.

Em outras palavras, com o IntelliJ o desenvolvimento será bem mais fácil.

Se optar pelo Eclipse (ou o STS) e o projeto for Gradle, provavelmente você vai precisar instalar um plugin do Gradle para que a IDE dê o suporte necessário.

Primeiros passos com o projeto

Após realizar o import do projeto temos os seguintes arquivos:

Estrutura do projeto criado

Observe que já temos um pacote criado de acordo com o nosso Group (no meu caso br.com.alexf) junto do artifact (ceepws), também, temos um arquivo CeepwsApplication.kt.

Este arquivo é a classe padrão que é criada com a finalidade de rodar o Spring Boot pra gente, vamos dar uma olhada no código dela:

Classe Application para rodar o Spring Boot

Repara que trata-se de uma classe anotada com @SpringBootApplication que serve justamente para indicar a classe base de configuração do Spring. Em outras palavras, temos a capacidade de realizar as configurações desejadas no nosso projeto a partir dessa classe.

Essa classe também é conhecida como classe Application do Spring Boot, ou seja, é muito comum a chamarmos dessa maneira.

Não se preocupe com configurações do Spring Framework, pois a proposta do Spring Boot é justamente evitar ao máximo que o desenvolvedor realize configurações comuns em projeto. Em outras palavras, não precisamos realizar configurações \o/

Agora vamos para o que interessa que é justamente ver o projeto funcionar!

Executando o projeto

Para isso, execute a classe CeepwsApplication e veja o log do console até aparecer que o servidor está de pé conforme a imagem abaixo:

Log após execução do Spring Boot

Repara que ele apresenta a mensagem Tomcat started on port(s): 8080 (http), isso significa que o servidor está operando na porta 8080, ou seja, podemos acessá-lo via navegador:

Acesso ao servidor com resposta 404

Observe que o Spring Boot respondeu a requisição! Claro, recebemos um 404 porque não configuramos nenhum tipo de Controller para receber a requisição e responder da maneira esperada.

Não se preocupe, veremos como é possível responder as requisições utilizando o conceito de WS na arquitetura REST.

Configurando o servidor com o Spring MVC

A stack Web do Spring Framework nos disponibiliza o projeto Spring MVC que é justamente o módulo que nos permite configurar o nosso servidor por meio do padrão MVC. Em outras palavras, iremos utilizar as features desse projeto para configurar o nosso WS.

Criando um Controller

Para criarmos um Controller, precisamos primeiro criar a classe que vai representar o nosso Controller dentro do mesmo pacote da nossa classe Application (pacote base, no meu caso br.com.alexf.ceepws) ou em um subpacote.

De modo geral, tentamos deixar o nosso projeto cada vez mais organizado, portanto, faz todo o sentido criarmos o nosso Controller dentro do pacote controller. Sendo assim, vamos criar o nosso NoteController:

Classe para representar o Controller de notas

Agora que criamos a classe, precisamos indicar para o Spring que essa classe será um Controller que ele irá gerenciar. Para isso, precisamos apenas adicionar a annotation @Controller:

Indicando o Controller para o Spring com a annotation @Controller

Neste momento, a nossa classe NoteController será gerenciada pelo Spring como um Controller capaz de atender requisições.

Entretanto, perceba que ainda não existe nenhum tipo de configuração que indique o endereço que esse Controller vai atender. Portanto, ele não vai responder a nenhuma requisição! Então como podemos fazer isso?

Configurando o mapeamento de requisição

Para indicarmos ao Controller o endereço que ele vai atender, basta apenas configurarmos o mapeamento da requisição a partir da annotation RequestMapping:

Adicionando o mapeamento de requisição no Controller

A partir de agora, o nosso Controller ficará responsável em atender todas as requisições a partir do endereço /notes, ou seja, nesse caso, http://localhost:8080/notes.

Porém, mesmo que acessemos esse endereço ainda recebemos um 404! E agora?

Entendendo a maneira como os servidores funcionam

Como sabemos, todos os acessos ao nosso servidor estão sendo feitos a partir do protocolo HTTP, que de forma resumida, permite transferir texto do lado do cliente para o servidor e vice-versa.

Entretanto, quando estamos configurando um servidor por meio do protocolo HTTP, precisamos também indicar sobre quais métodos do HTTP ele irá responder!

Por exemplo, quando acessamos a URL http://localhost:8080/notes via navegador, estamos pedindo ao nosso Controller por uma resposta a partir do método GET.

Já que ele não tem nada configurado para responder a esse tipo de requisição, a resposta 404…

Em outras palavras, precisamos também mapear o nosso Controller para responder requisições a partir do método GET. Mas como podemos fazer esse tipo de configuração?

Configurando o mapeamento para o métodos HTTP

Para configurarmos o mapeamento do método HTTP, primeiro precisamos criar uma função para o nosso controller. Sendo assim, vamos criar a função que vai listar todas as notas, ou seja, a list():

Criando uma função para o Controller

Em seguida, vamos anotá-la com a annotation @GetMapping:

Adicionando suporte ao método GET do HTTP no Controller

Agora, que temos uma função que vai atender às requisições via GET, precisamos apenas indicar o que ela vai devolver quando alguém acessar o servidor, nesse caso, devolveremos uma lista de notas, certo?

Portanto, vamos criar a nossa classe pra representar uma nota no pacote model:

Mode de notas para o WS

Então vamos devolver uma lista de notas a partir da função listOf:

Devolvendo lista de notas para requisições do tipo GET do HTTP

Se tentarmos acessar novamente o nosso Controller pela URL http://localhost:8080/notes, recebemos um erro 500…

Isso acontece porque o nosso Controller não sabe lidar com esse tipo de retorno, ou seja, precisamos agora indicar o que esse retorno significa pra ele.

Nesse caso, queremos que a resposta seja apresentada no corpo da requisição, certo? Indicamos esse comportamento adicionando a annotation @ResponseBody na nossa função:

Indicando que o retorno da função será devolvido no corpo da requisição com a annotation @ResponseBody

Se testamos acessar novamente a URL http://localhost:8080/notes temos o seguinte resultado:

Retornando JSON ao acessar o Controller

Veja que ele retorna o JSON com as informações das nossas notas, inclusive, por ser o Firefox, veja que da pra apresentar os dados como JSON:

Modificando a visualização do JSON

Bem bacana, né? Porém, ainda existe um detalhe importante que precisamos saber quando estamos em um projeto do Spring com o intuito de configurar um WS REST.

Entendendo o que é um Controller no Spring Framework

Como vimos, para configurarmos um Controller, utilizamos a annotation @Controller, porém, essa annotation é destinada justamente para uma configuração mais ampla do que apenas devolver respostas com objetos no corpo da requisição.

Em outras palavras, essa configuração é destinada também para projetos convencionais que aplicam o modelo MVC para responder com páginas web, que por sinal, é a forma padrão de resposta para esse tipo de Controller...

É justamente por esse motivo que tivemos que indicar que o retorno do nosso objeto seria uma resposta enviada no corpo da requisição… Será que não tem uma maneira mais objetiva?

Configurando um Controller para a arquitetura REST

Pensando justamente em melhorar essa experiência em desenvolver WS, desde a versão 4.0 do Spring MVC, podemos configurar o nosso Controller para que ele dê um suporte melhor durante o desenvolvimento de WS.

Para isso, ao invés de utilizarmos um Controller genérico e amplo, fazemos com o que ele seja um Controller destinado para a arquitetura REST, ou seja, utilizamos a annotation @RestController:

Indicando que o Controller é um @RestController

Se testarmos novamente a nossa aplicação ela ainda funciona!

“Então o que mudou em relação ao que fizemos com o @Controller?”

A ideia do @RestController é fazer com que a resposta das funções do Controller que foram mapeadas, como é o caso da nossa list(), tenham o @ResponseBody por padrão, ou seja, não precisamos mais indicá-lo!

Removendo o @ResponseBody dentro do @RestController

Testando novamente o nosso servidor, percebemos que agora ele devolve novamente a nossa lista! Porém, sem a necessidade de ficar indicando que é uma resposta no corpo da requisição 😃

Para saber mais

Vimos que o Controller permite devolver nossos objetos diretamente, entretanto, por mais que essa abordagem seja válida, a maneira ideal de fazermos esse tipo de retorno é por meio da classe HttpEntity<T> do Spring.

Quer aprender mais sobre Kotlin tanto no mundo mobile como no back-end? Então confira este agregador de conteúdo onde listo todos os conteúdos que escrevi de Kotlin e os que serão publicados mais pra frente 😉

Dessa forma, temos a capacidade de manipular mais informações do protocolo HTTP, como headers, status code entre outras opções que veremos a utilidade mais pra frente.

Código fonte

Caso fique com dúvida em alguma parte do artigo, não se preocupe! Estou disponibilizando o código fonte do projeto via GitHub.

Conclusão

Neste artigo vimos que temos a capacidade de fazer com que aplicações distintas se comuniquem por meio de WS. Também, aprendemos a criar um WS base com o Spring Boot.

Para isso vimos que temos a necessidade de usar o projeto Spring MVC que nos fornece toda a estrutura capaz de facilitar a nossa vida durante esse tipo de configuração.

Também vimos que uma das maneira mais comuns de criarmos esse tipo de solução dentro do Spring MVC é utilizando RestControllers.

Lembrando que vimos apenas o comecinho desse projeto, ou seja, fique atento que logo mais veremos como é possível configurar o banco de dados e realizar um CRUD do nosso WS.

O que achou do Spring Boot em relação à forma que ele nos provê para desenvolvermos os nossos WS? Aproveite e deixe o seu comentário 😉

--

--