Esse artigo é dedicado a responder uma pergunta que me fizeram sobre como utilizar o padrão de comunicação REST com HTML. Vou aproveitar a oportunidade para refrescar um pouco a paisagem de desenvolver REST em Java.
Para quem ainda não leu, recomendo o ótimo artigo sobre REST em Java do Alexandre Saudate.
Alguns anos se passaram desde que o artigo foi publicado; e nesse tempo muito foi discutido, evoluído e distorcido sobre arquiteturas REST. Hoje se fala todo dia em microservices, JSON e etc. e já não se fala tanto em SOA (no sentido tradicional). Mas uma coisa é certa: o uso de arquiteturas REST só cresceu e se tornou quase obrigatório para qualquer desenvolvedor (desde o back-end até o front-end). E por que será?
É comum vocês lerem artigos que ressaltam como o uso de smartphones vêm ganhando o mercado digital. Também é comum artigos que tratam sobre API first (iniciar seu produto por uma camada de serviços digitais pública). É justamente nesse cenário que temos o REST como central.
Lembrando do que se trata REST: é um padrão de arquitetura de serviços web, basicamente como uma boa parte da web funciona. Ele é pautado no HTTP para acrescentar o mínimo possível de burocracia. Assim, usamos URIs para identificar recursos (e seus caminhos e relacionamentos), um código de status mais um conjunto de headers HTTP e um corpo para fazermos todas as operações que precisamos (no link mencionado há uma descrição bem melhor do que realmente é REST em toda sua glória).
Uma coisa pode ter soado estranho na última frase: “… é basicamente como uma boa parte da web funciona”. Como assim? Quer dizer que abrir a página de um portal como o UOL ou a Globo.com é consumir um serviço REST? Exatamente. Sem por nem tirar nenhum detalhe.
Vamos entender o que o browser faz neste momento:
- Abrimos o Firefox (por exemplo);
- Digitamos http://www.uol.com.br (na verdade só digitamos “uol”… estou simplificando para não falar de tudo o que o browser faz por trás dos panos para resolver o que digitamos na barra de endereços);
- O browser faz, então, um request usando o verbo do HTTP ‘GET’ com essa URI;
- Na requisição do browser vai um header “Accept: ” dizendo o qual o conteúdo da resposta que ele quer. Neste caso, poderia ser “text/html”. Isso quer dizer que ele só aceita conteúdo no formato HTML;
- O servidor recebe o request (se não tiver nenhum problema de conexão), processa e responde com um status 200 (ok);
- A resposta contém um header ‘Content-type’ confirmando o tipo da resposta e o corpo da resposta será neste formato.
Simples, não?! Porém, quando pensamos em REST muitas vezes lembramos apenas de JSONs. Isso está errado. Em REST, tanto quem produz a informação quanto quem consome pode definir o formato, melhor dizendo, MIME TYPE, de seu conteúdo.
Vamos ao código. Manterei o framework utilizado no artigo anterior. Trata-se do Jersey que é a implementação de referência da especificação Java para serviços REST: JAX-RS (Java API for Restful Web Services).
Para nosso exemplo, vamos implementar um serviço que responda uma página HTML. Portanto, queremos o seguinte:
- Um serviço que responda por todas as requisições de uma URI relativa (após o host)
- Este serviço irá responder com o conteúdo HTML, status 200 e o header ‘Content-type: text/html’.
Simples! Para isso, basta um controller JAX-RS que declare tudo isso:
import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; @Path("/") public class IndexResource { @GET @Produces("text/html") public String getIndex() { return "<html><head><title>REST respondendo HTML</title></head><body> <h1>Olá mundo REST com HTML!</h1> </body></html>"; } }
O truque para implementar serviços REST que respondam HTML está em dizer que o conteúdo da resposta será do tipo “text/html”. Fazemos isso usando a anotação ‘@Produces(“text/html”)’.
Para ver o resultado, precisamos subir um servidor e apontar o browser para a URL que configuramos. O browser sempre faz uma requisição GET ao digitar um endereço URI.
Espero que o exemplo mostre um dos problemas desta solução: renderizar HTML direto em uma String não é o melhor dos mundos. Por isso que existem milhares de frameworks que não são RESTful (não implementam toda a arquitetura REST), mas que focam apenas em renderizar HTML a partir de URIs. Com eles fica mais fácil ter templates de renderização, mapeamento de URLs entre outras coisas. São frameworks que nos ajudam a criar a parte visual da nossa aplicação web. Alguns exemplos são: Spring MVC, VRaptor, JSF, JSP (por que não?), Struts etc.
Isso não quer dizer que temos que descartar implementar nossas rotas HTML em REST. Se quisermos seguir utilizando REST como nosso controlador de serviços (sejam eles de dados ou de visualização), é interessante procurar um framework de templating de HTML que facilite criar o documento final de forma mais produtiva. Entre eles podemos citar o Velocity e o FreeMarker como os predominantes em Java.
Por último, vale ressaltar que recentemente há um grande movimento para arquiteturas baseadas inteiramente em serviços de dados (e não visuais). Mas aí como eu faço minha página? Simples, basta usar um framework client-side. Nestes frameworks, temos toda a renderização controlada com JavaScript, HTML e CSS no lado do cliente. Assim, todos estes arquivos ficam hospedados em algum servidor (normalmente a parte do seu servidor de dados) que após serem carregados, sabem fazer as chamadas para os serviços de dados e criar a navegação dinamicamente conforme o usuário vai navegando. São chamados de SPA ou Single Page Applications (apesar de normalmente não obrigarem que seja uma única página mesmo) e como exemplo temos: AngularJS, EmberJS, BackboneJS, ReactJS etc.
A vantagem desta última abordagem é que com uma única camada de serviços REST, todos os seus canais, ou seja, Android, iOS, WindowsPhone, UbuntuPhone e WEB usam a mesma interface de serviços e seu servidor fica focado nas APIs de negócio.
Ficou alguma dúvida? Ótimo! Poste nos comentários que estamos sempre de olho. Sugestões de outros temas também são bem-vindas!