Integração via REST com OpenWS
Nesse exemplo quero mostrar como podemos usar o OpenWS como repositório de objetos ao invés de termos que criar toda a parte dos web services REST dentro da aplicação.
Para quem não conhece, o OpenWS (http://openws-app.herokuapp.com) é uma plataforma para armazenar objetos JSON. Após se cadastrar gratuitamente temos acesso a um tutorial sobre como utilizá-lo e também acesso as coleções de objetos que criamos.
Algo bem transparente do OpenWS é que não precisamos criar previamente estruturas de objetos ou as coleções que queremos usar, isso é feito automaticamente pelo próprio OpenWS, e também utilizandos os métodos HTTP (GET, POST, PUT e DELETE) para acessar os objetos.
Nesse exemplo vamos criar um CRUD de Abastecimentos (quando você abastece o carro com alcool ou gasolina), estou usando JSF + Bootstrap (http://getbootstrap.com/) para fazer a parte visual, a tela da aplicação vai ficar assim:
Para começar crie um novo projeto web, nesse exemplo chamei o projeto de OpenWSCliente.
Vamos criar uma classe que representa um Abastecimento:
package exemplo.modelo;
import java.util.Date;
public class Abastecimento {
private String _id;
private String tipoCombustivel;
private double valorLitro;
private double quantidade;
private Date dataAbastecimento;
private String local;
public String getId() {
return _id;
}
public void setId(String id) {
this._id = id;
}
public String getTipoCombustivel() {
return tipoCombustivel;
}
public void setTipoCombustivel(String tipoCombustivel) {
this.tipoCombustivel = tipoCombustivel;
}
public double getValorLitro() {
return valorLitro;
}
public void setValorLitro(double valorLitro) {
this.valorLitro = valorLitro;
}
public double getQuantidade() {
return quantidade;
}
public void setQuantidade(double quantidade) {
this.quantidade = quantidade;
}
public Date getDataAbastecimento() {
return dataAbastecimento;
}
public void setDataAbastecimento(Date dataAbastecimento) {
this.dataAbastecimento = dataAbastecimento;
}
public String getLocal() {
return local;
}
public void setLocal(String local) {
this.local = local;
}
}
A seguir temos o código da página index.xhtml com o cadastro e tabela para apresentar os abastecimentos salvos.
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<h:outputStylesheet library="css" name="bootstrap.min.css"/>
<h:outputStylesheet library="css" name="bootstrap-theme.min.css"/>
<title>Abastecimentos</title>
</h:head>
<h:body>
<div style="width: 100%; text-align: center">
<h1>Abastecimentos</h1>
</div>
<br/>
<h:form id="formulario">
<h:panelGroup id="dados">
<div class="form-group">
<div class="row">
<div class="col-md-2">
<h:outputText value="Tipo combustivel: " class="control-label"/>
</div>
<div class="col-md-3">
<h:selectOneMenu id="tipoCombustivel"
value="#{abastecimentoMB.abastecimento.tipoCombustivel}"
class="form-control">
<f:selectItem itemLabel="Álcool" itemValue="Álcool"/>
<f:selectItem itemLabel="Gasolina" itemValue="Gasolina"/>
</h:selectOneMenu>
</div>
</div>
<div class="row">
<div class="col-md-2">
<h:outputText value="Valor litro: " class="control-label"/>
</div>
<div class="col-md-3">
<h:inputText id="valorLitro"
value="#{abastecimentoMB.abastecimento.valorLitro}"
class="form-control"/>
</div>
</div>
<div class="row">
<div class="col-md-2">
<h:outputText value="Quantidade: " class="control-label"/>
</div>
<div class="col-md-3">
<h:inputText id="quantidade"
value="#{abastecimentoMB.abastecimento.quantidade}"
class="form-control"/>
</div>
</div>
<div class="row">
<div class="col-md-2">
<h:outputText value="Data: " class="control-label"/>
</div>
<div class="col-md-3">
<h:inputText id="dataAbastecimento"
value="#{abastecimentoMB.abastecimento.dataAbastecimento}"
pt:placeholder="dd/mm/aaaa" class="form-control">
<f:convertDateTime for="dataAbastecimento"
timeZone="America/Sao_Paulo" pattern="dd/MM/yyyy" />
</h:inputText>
</div>
</div>
<div class="row">
<div class="col-md-2">
<h:outputText value="Local " class="control-label"/>
</div>
<div class="col-md-9">
<h:inputText id="local" value="#{abastecimentoMB.abastecimento.local}"
class="form-control"/>
</div>
</div>
<h:commandButton value="Novo" action="#{abastecimentoMB.novo}"
style="width: 80px;" class="btn btn-default"/>
<h:commandButton value="Salvar" action="#{abastecimentoMB.salvar}"
style="width: 80px;" class="btn btn-success"/>
</div>
</h:panelGroup>
<h:panelGroup id="groupAbastecimento">
<div class="table-responsive">
<h:dataTable value="#{abastecimentoMB.abastecimentos}" var="a"
width="100%" class="table table-hover">
<h:column>
<f:facet name="header">
<h:outputText value="Tipo combustivel"/>
</f:facet>
<h:outputText value="#{a.tipoCombustivel}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Valor livro"/>
</f:facet>
<h:outputText value="#{a.valorLitro}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Quantidade"/>
</f:facet>
<h:outputText value="#{a.quantidade}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Data"/>
</f:facet>
<h:outputText value="#{a.dataAbastecimento}">
<f:convertDateTime for="dataAbastecimento"
timeZone="America/Sao_Paulo" pattern="dd/MM/yyyy" />
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Local"/>
</f:facet>
<h:outputText value="#{a.local}"/>
</h:column>
<h:column>
<h:commandButton value="Editar" action="#{abastecimentoMB.editar(a)}"
style="width: 80px;" class="btn btn-primary">
<f:ajax render=":formulario:dados"/>
</h:commandButton>
</h:column>
<h:column>
<h:commandButton value="Remover" action="#{abastecimentoMB.remover(a)}"
style="width: 80px;" class="btn btn-danger">
<f:ajax render=":formulario:groupAbastecimento"/>
</h:commandButton>
</h:column>
</h:dataTable>
</div>
</h:panelGroup>
</h:form>
</h:body>
</html>
Observação: Os arquivos do bootstrap: bootstrap.min.css e bootstrap-theme.min.css devem ser colocados dentro de Páginas Web / resources / css.
Agora vamos implementar o ManagedBean:
package exemplo.mb;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import exemplo.modelo.Abastecimento;
import java.io.Serializable;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class AbastecimentoMB implements Serializable {
private static final long serialVersionUID = -8340695008346767777L;
private Abastecimento abastecimento = new Abastecimento();
private List<Abastecimento> abastecimentos;
private Client c = Client.create();
private Gson gson = new Gson();
private static final String URL = "https://openws.herokuapp.com/abastecimento";
//Coloque sua API Key aqui.
private static final String MINHA_CHAVE = "?apiKey=xxxxxxxxxxxxx";
public AbastecimentoMB() {
recarregar();
}
public void recarregar() {
WebResource wr = c.resource(URL + MINHA_CHAVE);
String json = wr.get(String.class);
abastecimentos = gson.fromJson(json, new TypeToken<List<Abastecimento>>() {
}.getType());
}
public String novo() {
this.abastecimento = new Abastecimento();
return "index";
}
public String salvar() {
if (abastecimento.getId() == null) {
WebResource wr = c.resource(URL + MINHA_CHAVE);
wr.type("application/json").accept("application/json")
.post(gson.toJson(abastecimento));
} else {
WebResource wr = c.resource(URL + "/" + abastecimento.getId()
+ MINHA_CHAVE);
wr.type("application/json").accept("application/json")
.put(gson.toJson(abastecimento));
}
abastecimento = new Abastecimento();
recarregar();
return "index";
}
public void remover(Abastecimento a) {
WebResource wr = c.resource(URL + "/" + a.getId() + MINHA_CHAVE);
wr.delete();
recarregar();
}
public void editar(Abastecimento a) {
System.out.println(a);
this.abastecimento = a;
}
public Abastecimento getAbastecimento() {
return abastecimento;
}
public void setAbastecimento(Abastecimento abastecimento) {
this.abastecimento = abastecimento;
}
public List<Abastecimento> getAbastecimentos() {
return abastecimentos;
}
public void setAbastecimentos(List<Abastecimento> abastecimentos) {
this.abastecimentos = abastecimentos;
}
}
No ManagedBean informe qual a sua chave (API Key) obtida no OpenWS:
//Coloque sua API Key aqui.
private static final String MINHA_CHAVE = "?apiKey=xxxxxxxxxxxxx";
Criei uma URL com o endereço:
private static final String URL = "https://openws.herokuapp.com/abastecimento";
Isso informa para o OpenWS criar uma coleção de objetos chamado abastecimento
e dentro dela ele vai guardar os objetos.
Agora só testar a aplicação, veja que não precisamos criar o Web Service, o próprio OpenWS faz isso, precisamos apenas criar o cliente.