Skip to content

Instantly share code, notes, and snippets.

@alexandreaquiles
Last active September 21, 2017 15:34
Show Gist options
  • Save alexandreaquiles/7aa85c422bce322aade7 to your computer and use it in GitHub Desktop.
Save alexandreaquiles/7aa85c422bce322aade7 to your computer and use it in GitHub Desktop.

Utilizando Link do JAX-RS 2.0 para HATEOAS

  1. Removida classe Link caseira dos projetos livraria e payfast.

  2. Na classe PagamentoResource do payfast, foi criado o método getTransitions que retorna um array de Link do JAX-RS com as transições possíveis, de acordo com o status do pagamento.

  3. O array de Link é utilizado no método links do ResponseBuilder do JAX-RS:

    Response.ok().entity(pagamento).links(links).build()
  4. Na classe ClienteRest da livraria, foi modificado o código dos métodos criarPagamento e confirmarPagamento para utilizar o Link do JAX-RS.

  5. Para obter o link a partir do Pagamento no confirmarPagamento, colocamos o Response como atributo. Gambi!

package br.com.caelum.livraria.modelo;
import java.io.Serializable;
import java.math.BigDecimal;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.Response;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
public class Pagamento implements Serializable {
private static final long serialVersionUID = 1L;
private static final String STATUS_CRIADO = "CRIADO";
private static final String STATUS_CONFIRMADO = "CONFIRMADO";
private static final String STATUS_CANCELADO = "CANCELADO";
@Id
private Integer id;
private String status;
private BigDecimal valor;
@Transient
private Response response;
public void setStatus(final String status) {
this.status = status;
}
public void setValor(final BigDecimal valor) {
this.valor = valor;
}
public void setId(final Integer id) {
this.id = id;
}
public void setResponse(Response response) {
this.response = response;
}
public String getStatus() {
return this.status;
}
public BigDecimal getValor() {
return this.valor;
}
public Integer getId() {
return this.id;
}
public Response getResponse() {
return response;
}
public boolean ehCriado() {
return STATUS_CRIADO.equals(this.status);
}
public boolean ehConfirmado() {
return STATUS_CONFIRMADO.equals(this.status);
}
public boolean ehCancelado() {
return STATUS_CANCELADO.equals(this.status);
}
@Override
public String toString() {
return "Pagamento [id=" + this.id + ", status=" + this.status + ", valor=" + this.valor + "]";
}
public Link getLinkPeloRel(String rel) {
return this.response.getLink(rel);
}
}
package br.com.caelum.livraria.rest;
import java.io.Serializable;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.Response;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import br.com.caelum.livraria.modelo.Pagamento;
import br.com.caelum.livraria.modelo.Transacao;
@Component
@Scope("request")
public class ClienteRest implements Serializable {
private static final long serialVersionUID = 1L;
private static final String SERVER_URI = "http://localhost:8080/fj36-webservice";
private static final String ENTRY_POINT = "/pagamentos/";
public Pagamento criarPagamento(Transacao transacao) {
Client cliente = ClientBuilder.newClient();
Response response = cliente
.target(SERVER_URI + ENTRY_POINT)
.request()
.buildPost(Entity.json(transacao))
.invoke();
Pagamento pagamento = response.readEntity(Pagamento.class);
System.out.println("Id do pagamento criado: " + pagamento.getId());
pagamento.setResponse(response);
return pagamento;
}
public Pagamento confirmarPagamento(Pagamento pagamento) {
Client cliente = ClientBuilder.newClient();
Link linkConfirmar = pagamento.getLinkPeloRel("confirmar");
Pagamento resposta = cliente
.target(SERVER_URI + linkConfirmar.getUri())
.request()
.build(linkConfirmar.getType())
.invoke(Pagamento.class);
System.out.println("Pagamento confirmado, id: " + resposta.getId());
return resposta;
}
}
package br.com.caelum.payfast.modelo;
import java.math.BigDecimal;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Pagamento {
private static final String STATUS_CRIADO = "CRIADO";
private static final String STATUS_CONFIRMADO = "CONFIRMADO";
private static final String STATUS_CANCELADO = "CANCELADO";
private Integer id;
private String status;
private BigDecimal valor;
public void comStatusCriado() {
if (this.id == null) {
throw new IllegalArgumentException("id do pagamento deve existir");
}
this.status = STATUS_CRIADO;
}
public void comStatusConfirmado() {
if (this.id == null) {
throw new IllegalArgumentException("id do pagamento deve existir");
}
if(this.status == null || !this.status.equals(STATUS_CRIADO)) {
throw new IllegalStateException("status deve ser " + STATUS_CRIADO);
}
this.status = STATUS_CONFIRMADO;
}
public void comStatusCancelado() {
if (this.id == null) {
throw new IllegalArgumentException("id do pagamento deve existir");
}
if(this.status == null || !this.status.equals(STATUS_CRIADO)) {
throw new IllegalStateException("status deve ser " + STATUS_CRIADO);
}
this.status = STATUS_CANCELADO;
}
public void setValor(BigDecimal valor) {
this.valor = valor;
}
public void setId(Integer id) {
this.id = id;
}
public String getStatus() {
return status;
}
public BigDecimal getValor() {
return valor;
}
public Integer getId() {
return id;
}
public boolean ehCriado() {
return STATUS_CRIADO.equals(this.status);
}
public boolean ehConfirmado() {
return STATUS_CONFIRMADO.equals(this.status);
}
public boolean ehCancelado() {
return STATUS_CANCELADO.equals(this.status);
}
@Override
public String toString() {
return "Pagamento [id=" + id + ", status=" + status + ", valor=" + valor + "]";
}
}
package br.com.caelum.payfast.rest;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import br.com.caelum.payfast.modelo.Pagamento;
import br.com.caelum.payfast.modelo.Transacao;
@Path("/pagamentos")
@Singleton
public class PagamentoResource {
private Map<Integer, Pagamento> repositorio = new HashMap<>();
private Integer idPagamento = 1;
public PagamentoResource() {
Pagamento pagamento = new Pagamento();
pagamento.setId(idPagamento++);
pagamento.setValor(BigDecimal.TEN);
pagamento.comStatusCriado();
repositorio.put(pagamento.getId(), pagamento);
}
@GET
@Path("/{id}")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) // cuidado
// javax.ws.rs
public Pagamento buscaPagamento(@PathParam("id") Integer id) {
return repositorio.get(id);
}
@POST
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response criarPagamento(Transacao transacao, @Context UriInfo uriInfo) throws URISyntaxException {
Pagamento pagamento = new Pagamento();
pagamento.setId(idPagamento++);
pagamento.setValor(transacao.getValor());
pagamento.comStatusCriado();
repositorio.put(pagamento.getId(), pagamento);
System.out.println("PAGAMENTO CRIADO " + pagamento);
Link[] links = getTransitions(pagamento);
return Response.created(new URI("/pagamentos/" + pagamento.getId())).links(links).entity(pagamento)
.type(MediaType.APPLICATION_JSON).build();
}
@PUT
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON) // cuidado javax.ws.rs
public Response confirmarPagamento(@PathParam("id") Integer pagamentoId, @Context UriInfo uriInfo) {
Pagamento pagamento = repositorio.get(pagamentoId);
pagamento.comStatusConfirmado();
System.out.println("Pagamento confirmado: " + pagamento);
Link[] links = getTransitions(pagamento);
return Response.ok().entity(pagamento).links(links).build();
}
@DELETE
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON) // cuidado javax.ws.rs
public Response cancelarPagamento(@PathParam("id") Integer pagamentoId, @Context UriInfo uriInfo) {
Pagamento pagamento = repositorio.get(pagamentoId);
pagamento.comStatusCancelado();
System.out.println("Pagamento cancelado: " + pagamento);
Link[] links = getTransitions(pagamento);
return Response.ok().entity(pagamento).links(links).build();
}
private Link[] getTransitions(Pagamento p) {
String baseUri = "/pagamentos/";
String pagamentoUri = baseUri + p.getId();
Link self = Link.fromUri(baseUri).rel("self").uri(pagamentoUri).type("GET").build();
if (p.ehCriado()) {
Link confirmar = Link.fromUri(baseUri).rel("confirmar").uri(pagamentoUri).type("PUT").build();
Link cancelar = Link.fromUri(baseUri).rel("cancelar").uri(pagamentoUri).type("DELETE").build();
return new Link[] { self, confirmar, cancelar };
} else if (p.ehConfirmado()) {
return new Link[] { self };
} else if (p.ehCancelado()) {
return new Link[] { self };
} else {
throw new IllegalStateException("status de pagamento inválido");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment