Back-End

31 jan, 2018

Introdução ao Vert.X com Java

Publicidade

Você sabia que existe uma alternativa ao node.js que roda na JVM? Pois é! O framework Vert.x foi criado por Tim Fox, engenheiro da VMware, para aplicações web. Apesar de não ser específico para Java, podemos usá-lo com Javascript, Ruby, Groovy, Ceylon, Scala e até Kotlin.

O framework segue os princípios do paradigma reativo para que sua aplicação consiga se recuperar de falhas, e além disso, é elástico (se adéqua à demanda/carga e uso de múltiplos cores e múltiplos servidores), tem sistemas compostos de gerenciadores de eventos assíncronos e não bloqueantes em vez de compor aplicações por múltiplas threads síncronas e é responsivo, ou seja, atende aplicações que oferecem interações ricas e em “tempo real” com usuários.

Quer saber mais sobre programação reativa? Dê uma olhada nesse link. Além da concorrência, o framework inclui servidores e clientes que utilizam o protocolo TCP/SSL HTTP/HTTPS e dá suporte a WebSockets e SockJS.

Por fim, vale dizer que o Vert.x tem um conceito chamado Verticle, que nada mais é do que uma instância de uma aplicação “deployada” e implementada. Esses “Verticles” gerenciam um pequeno número de threads, uma para cada núcleo disponível no servidor. Os Verticles podem se comunicar entre si (desde que estejam em uma mesma instância) ou podem se comunicar com outros, em instâncias diferentes, por meio de um barramento específico de mensagens.

No site oficial é possível encontrar exemplos de implementações em outras linguagens, mas neste artigo vou mostrar como montar uma simples REST API com o uso do Vert.x e Java. Bora lá?

Pré-requisitos

  • Java 8
  • Eclipse
  • Maven

Criando o projeto

No Eclipse, vá em File > New > Maven Project e marque o checkbox “Create a Simple Project (skip archetype selection)” conforme a imagem abaixo, e depois clique em Next.

Na próxima janela, preencha as informações desta forma:

Agora é só clicar em Finish, e seu projeto Maven será gerado.

O próximo passo é adicionar as dependências necessárias para que nossa aplicação funcione corretamente com o Vert.x. Para isso, procure pelo arquivo pom.xml e adicione as dependências do vertx core e o vertx web. Vai ficar assim:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.concrete</groupId>
    <artifactId>vertxapi</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Exemplo de API com Vert.x</name>
    <description>Exemplo de aplicação que expõe uma REST API utilizando o framework Vert.x</description>

    <dependencies>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <version>3.3.3</version>
        </dependency>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-web</artifactId>
            <version>3.3.3</version>
        </dependency>
    </dependencies>
</project>

Com o nosso projeto configurado, mãos à obra! Vamos programar!

A princípio vamos criar uma classe responsável por colocar o nosso Server no ar.

Crie o pacote “com.concrete.vertxapi.server” dentro de src/main/java e dentro dele crie a classe ServerVerticle.java, dessa forma:

package com.concrete.vertxapi.server;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.ext.web.Router;

public class ServerVerticle extends AbstractVerticle {

    @Override
    public void start(Future<Void> future) {

        Router router = Router.router(vertx);

        router.route("/").handler(routingContext -> {
            HttpServerResponse response = routingContext.response();
            response.putHeader("content-type", "text/html").end("<h1>Meu Primeiro Server com Vertx Funcionando</h1>");
        });

        vertx.createHttpServer().requestHandler(router::accept).listen(config().getInteger("http.port", 9000),
                result -> {
                    if (result.succeeded()) {
                        future.complete();
                    } else {
                        future.fail(result.cause());
                    }
                });
    }

}

Repare que para implementar um verticle, criamos uma classe e fazemos o extends de AbstractVerticle. Também fizemos a sobreposição do método start, criando uma rota para a raiz da nossa aplicação. Por fim, criamos o server http que utiliza a porta 9000.

Temos nossa classe de Server criada, mas ainda precisamos rodar a aplicação. Para isso, basta criar uma Main class que instancie o Vertx e faça o deploy de um verticle. Assim:

package com.concrete.vertxapi.main;


import com.concrete.vertxapi.server.ServerVerticle;

import io.vertx.core.Vertx;

public class Run {
    
    public static void main(String[] args) {
        Vertx vertx = Vertx.vertx();
 	   vertx.deployVerticle(new ServerVerticle());
 	   System.out.println(">>> Verticle iniciado e rodando na porta 9000");
    }

}

Agora execute a aplicação clicando com o botão direito sobre classe Run e em seguida escolha a opção Run As > Java Application. Abra o seu navegador de preferência e acesse http://localhost:9000. Você vai ver a seguinte mensagem:

Meu Primeiro Server com Vertx Funcionando

Para incrementar nossa aplicação

Agora que temos nosso Server verticle criado e funcionando, vamos adicionar as rotas que vão transformar nossa aplicação em uma REST API. Dentro da nossa classe ServerVerticle.java, vamos fazer a simulação de uma API que vai disponibilizar endpoints necessários para um CRUD de contatos. Primeiro vamos criar a classe que representa a entidade Contato. Ela deve ficar dentro do pacote com.concrete.vertxapi.entities, assim:

package com.concrete.vertxapi.entities;

import java.util.concurrent.atomic.AtomicInteger;

public class Contato {


    private int id;

    private String nome;

    private String telefone;

    public Contato() {}
    

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getTelefone() {
        return telefone;
    }

    public void setTelefone(String telefone) {
        this.telefone = telefone;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public int getId() {
        return id;
    }

Agora é só adicionar o trecho responsável por expor o endpoint de criação de um novo contato na classe ServerVerticle.java. Para isso, abaixo da criação da rota da raiz da aplicação (“/”) vamos adicionar as seguintes linhas de código:

router.route("/api/contatos*").handler(BodyHandler.create());
router.post("/api/contatos").handler(this::addContato);

A primeira linha serve para decodificar o body que será recebido na requisição. Repare que na segunda linha dentro do handler é esperado o método addContato. Vamos criá-lo também dentro dessa classe com o seguinte conteúdo:

private void addContato(RoutingContext routingContext) {
 	   final Contato contato = Json.decodeValue(routingContext.getBodyAsString(),
 	           Contato.class);
 	  
 	   contatos.put(contato.getId(), contato);

 	   routingContext.response()
 	       .setStatusCode(201)
 	       .putHeader("content-type", "application/json; charset=utf-8")
 	       .end(Json.encodePrettily(contato));
 	 }

Repare que existe um Map de contatos, basta criá-lo na classe para simular um repositório de dados “fake”.

Pronto? Então vamos testar. Suba o servidor por meio da classe Run.java e abra uma ferramenta REST (POSTMAN, por exemplo). Faça uma requisição para o endereço: http://localhost:9000/api/contatos utilizando o verbo POST e adicione o seguinte conteúdo ao body da requisição:

{
   "nome":"Luiz Evangelista",
   "telefone":"(13)3222-2222"
}

Se deu tudo certo, você vai receber uma resposta com o statusCode 201.

Para recuperar a lista de todos os contatos cadastrados, você deve adicionar uma linha abaixo da linha da rota de adição de contatos, deixando o bloco de código assim:

router.route("/api/contatos*").handler(BodyHandler.create());
router.post("/api/contatos").handler(this::addContato);
router.get("/api/contatos").handler(this::getAll);

Como no fluxo de adição de um novo contato é necessária a criação do método esperado, dentro do handler da rota GET implementada, você deve adicionar o seguinte método dentro da classe:

private void getAll(RoutingContext routingContext) {
        routingContext.response().putHeader("content-type", "application/json; charset=utf-8")
                .end(Json.encodePrettily(contatos.values()));
    }

O restante dos métodos, como busca de contato por id, por exemplo, devem seguir praticamente o mesmo fluxo dos métodos criados anteriormente. O código completo da aplicação, se você tiver interesse, está aqui.

E é isso! Espero que tenham aprendido um pouco sobre o Vert.x e como utilizá-lo de maneira simples. Para saber mais sobre o framework, recomendo a leitura da documentação das principais dependências core e web. Neste artigo também tem algumas informações interessantes sobre o Vert.x. Ficou alguma dúvida ou tem algo a dizer?Aproveite os campos abaixo. Até a próxima!

***

Este artigo foi publicado originalmente em: https://www.concrete.com.br/2018/01/12/introducao-ao-vert-x-com-java/