Quando comecei a programar, sempre tive um apreço imenso pelo Java (um pouco masoquista da minha parte). Criar aplicações desktop cross-platform parecia simples com auxílio do Netbeans e isso era suficiente para eu estar convicto de que era um programador de verdade.

Eu era um militante Java, até o dia em que comecei o tortuoso percurso de especialização na especificação de JavaEE (diga-se o Java para web). Depois de criar algumas aplicações, comecei a perceber que os workarounds eram grandes para features simples, se o caso fosse UX era PrimeFaces neles!

Como minhas justificativas para os workarounds da plataforma eram sempre a UX, comecei a estudar técnicas de Client-side Rendering utilizando frameworks como React(tão masoquista quanto), Angular, por último e principalmente Vue.JS.

Pela facilidade que era casar esses frameworks frontend com outros frameworks como Express.js (Node.js), Bottle (Python), Laravel e Slim (PHP) e a incorporação em serviços IOT-like, fui cada vez mais me distanciando do JavaEE. Até o dia que conheci o Spark.

Começando no Spark

Depois dessa introdução de cair lágrimas, vamos ao que interessa, primeiro destacar algumas características que me motivaram a abrir a IDE e utilizar o Spark:

  • Java 8 - lambdas expressions compatível
  • Kotlin compatível
  • API similar ao express
  • Uma das melhores documentações que já vi. Simples,clara,objetiva…
  • Tem suporte da comunidade para vários plugins de templates (pra quem gosta de Server-side rendering)
  • Pode ser usado de maneira standalone ou em conjunto com servidores de aplicação

Para mostrar o quão prático é começar com Spark, utilizando maven, adicionamos a dependência no nosso pom.xml:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-core</artifactId>
    <version>2.7.2</version>
</dependency>

Agora na nossa classe principal, de forma similiar ao express, declaramos nossa primeira rota, aguardando o método GET:

import static spark.Spark.*;

public class HelloWorld {
    public static void main(String[] args) {
        get("/hello", (req, res) -> "Hello World");
    }
}

Executando nossa classe, teremos o servidor rodando e aguardando a requisição.

Acesse http://localhost:4567/hello

Nosso Olá mundo está de pé.

Podemos mudar nossa porta, utilizando o método port do Spark:

port(8080);

Com facilidade podemos acessar os Routes Parameters e Query Parameters

get("/hello/:name", (request, response) -> {
    return "Hello: " + request.params(":name") + request.queryParams("sobrenome");
});

Acesse http://localhost:4567/hello/Joao?sobrenome=Silva

A manipulação da sessão e de comportamento da resposta também é absurdamente prática, exatamente por isso vou pular essa parte. Quero essencialmente mostrar o sistema de templates e de transformação de resposta, para mostrar que o framework agrada à gregos e troianos.

Antes de avançar, a pasta src/main/resources vai ser o nosso ponto de partida para os arquivos estáticos (estilos, páginas e scripts) e também para o diretório de templates.

Server Side Rendering

Para renderizar as páginas do lado do servidor, é conveniente utilizar uma engine de templates para montar nossas views. Neste exemplo, optei pelo handlebars, porém podemos usar também outras template-engines como Velocity, Mustache, Freemarker, Twig, etc.

Adicionamos o wrapper do handlebars para Spark no nosso pom.xml

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-template-handlebars</artifactId>
    <version>2.7.1</version>
</dependency>

Adicionamos nosso template à pasta src/main/resources/templates, com o nome de index.hbs:

<html>
<head>
    <title>Exemplo</title>
    <meta charset="UTF-8">
</head>
<body>
    <h2>
        Olá {{nome}}
    </h2>
    Seus emails:
    <ul>
        {{#each emails}}
            <li>
                {{this}}
            </li>
        {{/each}}
    </ul>
</body>
</html>

E por fim adicionar um pouco de código:

get("/", (request, response) -> {
                    HashMap<String, Object> params = new HashMap();
                    params.put("nome", "Joazinho");
                    params.put("emails",
                    	new String[]{
                            "Email do trabalho", 
                            "Email da faculdade", 
                            "Email do Pedrinho"});
                    return new ModelAndView(params, "index.hbs");
                }, new HandlebarsTemplateEngine());

Agora quando acessamos nosso localhost denovo, temos a seguinte mensagem:


<!DOCTYPE html>
<html>
<head>
    <title>Exemplo</title>
    <meta charset="UTF-8">
</head>
<body>
    <h2>
        Olá Joazinho
    </h2>
    Seus emails:
    <ul>
            <li>
                Email do trabalho
            </li>
            <li>
                Email da faculdade
            </li>
            <li>
                Email do Pedrinho
            </li>
    </ul>
</body>
</html>

Pronto! finalizamos a renderização de nossa View. Simples e facil, não?!

RESTful

Se nosso foco não for server-side rendering, outra alternativa pode ser construir um servidor REST. O Spark provê ótimas maneiras de fazer isso de forma limpa e concisa.

Para demonstrar, vamos ver um exemplo de um servidor REST que utiliza JSON para a troca de mensagens.

Para isso primeiramente precisamos de uma forma de mapear um Objeto Java para JSON, para facilitar nosso trabalho existem bibliotecas com Jackson ou Gson.

No exemplo, iremos utilizar o Gson e para isso precisaremos importá-la em nosso pom.xml

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.5</version>
</dependency>

O Gson é extremamente simples de ser utilizado, precisamos apenas instanciar e chamar o método toJson(). Considerando a entidade Aviso:

public class Aviso {
    private int id;
    private String descricao;
    private Date dataInsercao;
    
    public Aviso(String descricao, Date dataInsercao){
        this.descricao = descricao;
        this.dataInsercao = dataInsercao;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getDescricao() {
        return descricao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }

    public Date getDataInsercao() {
        return dataInsercao;
    }

    public void setDataInsercao(Date dataInsercao) {
        this.dataInsercao = dataInsercao;
    }
   
}

O código à seguir para converter em JSON:

Aviso aviso = new Aviso("Hora de dormir", new Date());
Gson gson = new Gson();
String toDoJson = gson.toJson(aviso);
// {"id":0,"descricao":"Hora de dormir","dataInsercao":"Sep 12, 2018 5:54:56 PM"}

Bom, agora que já sabemos como converter nossa entidade em JSON, podemos levar isso para o Spark.

Gson gson = new Gson();
AvisoDao avisoDao = new AvisoDao();
get("/avisos/:id",
    "application/json", 
    (request, response) -> avisoDao.getAviso(request.params(":id")), 
    gson::toJson);

Esse exemplo, considera que já implementamos uma classe para acessar nossa entidade, o AvisoDao. Para facilitar podemos passar o Content-Type no segundo parâmetro e o último parâmetro é uma instância de um ResponseTransformer, interface funcional que recebe um Objeto como parâmetro e devolve uma String, dessa forma conseguimos inferir com Methods References a chamada ao método toJson().

Com isso já é possível acessar http://localhost:/avisos/1 e ter nossa resposta em JSON.

Acho que esse post foi o suficiente para dar um gostinho do que é o Spark (e o que ele representa rsrs). A documentação completa pode ser acessada aqui, e alguns tutoriais bem bacanas aqui