Analogia das evoluções WS-* REST Modelo OSI TCP/IP Muitas specs antes das implementações Modelo waterfall/cascata Regras simples Specs acompanham implementações Modelo incremental Scrum anyone??
Motivação
Porque implementar serviços REST?
Protocolos menos complexos
Mais poder e flexibilidade
Arquitetura amplamente disponível
Menos overhead de protocolo
No Silver Bullet!
Des-Motivação
Quando NÃO implementar serviços REST?
Integração com produtos fechados WS-*
Quando WS-Transaction fizer sentido
Quando WS-Security fizer sentido
Quando não houver API HTTP razoável
Arquitetura dos web services REST
Estilo de acesso aos serviços
Estilo declarativo x imperativo GET /usuario/123456 O quê Como Método HTTP URI do recurso <soap:Envelope> <soap:Body> <globo: consultarUsuario > <id>123456</id> </globo: consultarUsuario > </soap:Body> </soap:Envelope> fazerEstaOperacao
Implementação de serviços REST
Problema proposto
Leilão do Mercado Livre
Vendedor anuncia produto
Interessados realizam ofertas
Vendedor aceita melhor oferta
Vendedor e comprador se avaliam
Serviços oferecidos
Anunciar item
Buscar ítens do vendedor
Cadastrar usuário
Realizar oferta
Retirar oferta
Buscar ofertas do item
Buscar melhor oferta
Aceitar melhor oferta
Avaliar usuário
Buscar avaliações do usuário
Modelagem com recursos
Recursos identificados:
Usuário
Item (produto)
Oferta
Avaliação
Como manipular estes recursos? Defina seu protocolo de comunicação REST
Protocolo de comunicação REST
Perguntas importantes:
Quais são os recursos?
Quais são as URIs?
Quais são os formatos manipulados?
Que métodos HTTP são aceitos em cada URI?
Que status HTTP deve ser retornado em cada situação?
Que cabeçalhos HTTP são relevantes em cada situação?
Protocolo de comunicação REST GET, POST, PUT, DELETE SELECT, INSERT, UPDATE, DELETE !=
Quanto mais CRUD, mais fácil definir protocolo
REST é bem mais do que CRUD
REST envolve interações entre Recursos
Como modelar serviço de “Aceitar melhor oferta”?
Trivial com WS-*, não-trivial com REST
Paradigma diferente, modelagem diferente
Protocolo de comunicação REST Não posso usar PUT e DELETE, que posso fazer?? 1. Reclamar 2. POST com x-http-method-override E se eu precisar enviar dados em uma requisição sem corpo (HTTP DELETE)?? Mesma receita!
Protocolo de comunicação REST Com URI + método, você é capaz de deduzir qual é o serviço em questão? POST /avaliacao/de/{id}/para/{id} GET /avaliacao/{id} POST GET /usuario/{id}/itens GET /usuario/{id}/avaliacoes PUT GET /usuario/{id} POST /usuario DELETE PUT GET /oferta/{id} POST GET /item/{id}/ofertas PUT GET /item/{id} Método URI
Fluxo de Processamento
Validar URI
Validar método HTTP
Obter parâmetros da URI
Interpretar corpo da requisição
Processamento do serviço
Gerar resposta
Implementação – Com um certo trabalho Processamento do serviço Gerar resposta Validar URI Validar método HTTP Controle customizado de URIs existentes e métodos aceitos Obter parâmetros da URI Quebra manual da URI para extrair parâmetros Interpretar corpo da requisição Manipulação direta do corpo da requisição. Validações e conversões de formatos são customizadas Manipulação do status e corpo da resposta é feito diretamente.
Implementação – JAX-RS/Jersey Processamento do serviço Gerar resposta Validar URI Validar método HTTP Anotações sobre classes e métodos Obter parâmetros da URI Injeção de dependências Interpretar corpo da requisição Anotações declaram tipos de conteúdo aceitos. Consumo do corpo é automático. API para definir corpo e status da resposta em alto nível. Fácil suporte a diferentes formatos.
JAX-RS/Jersey
URIs mapeadas em classes/métodos
Parâmetros extraídos das URIs
Conversões xml/json/etc -> Java
Conversões Java -> xml/json/etc
Manipulação de status/headers HTTP
Flexibilidade nas respostas Me diga o que queres Seja feita vossa vontade Accept: text/xml, application/json <usuario> <login>blpsilva</login> </usuario> <usuario> <login>teste999</login> </usuario> "usuarios":[ { "login":"blpsilva", }, { "login":"teste999", } ] OU
Uma interface,
múltiplos formatos
Flexibilidade nas requisições Me diga o que estás mandando Content-Type: text/xml; OU
Uma interface,
múltiplos formatos!
charset=UTF-8 Content-Type: application/json; charset=ISO-8859-1 Eu converto e processo
OK, show me the code!!!
Parsing de URIs @Path("usuario") public class UsuarioResource { @GET @Path("{usuarioId}") @ProduceMime("text/xml") public Response buscarUsuario(@PathParam("usuarioId") String usuarioId)
UsuarioResource trata de /usuario
buscarUsuario trata de GET /usuario/{usuarioId}
Parâmetro usuarioId injetado no método
Parsing de URIs @Path("avaliacao") public class AvaliacaoResource { @POST @Path("de/{avaliador}/para/{avaliado}") public Response avaliarUsuario( @Context UriInfo uriInfo, @PathParam("avaliador") String avaliador, @PathParam("avaliado") String avaliado, Avaliacao avaliacao) {}
AvaliacaoResource trata de /avaliacao
avaliarUsuario:
POST /avaliacao/de/{avaliador}/para/{avaliado}
2 parâmetros extraídos da URI
Avaliação consumida do corpo da requisição
Interpretar corpo da requisição @ConsumeMime( { "text/xml", "application/json" }) public class AvaliacaoResource { @POST @Path("de/{avaliador}/para/{avaliado}") public Response avaliarUsuario(@Context UriInfo uriInfo, @PathParam("avaliador") String avaliador, @PathParam("avaliado") String avaliado, Avaliacao avaliacao )
AvaliacaoResource aceita XML e JSON
Avaliação em XML/JSON é injetada no método
Cliente especifica content-type na requisição
Geração da resposta @ProduceMime( { "text/xml", "application/json" }) public class AvaliacaoResource { @GET @Path("{avaliacaoId}") public Response buscar(@PathParam("avaliacaoId") String avaliacaoId){ Avaliacao avaliacao = avaliacaoService.buscar(avaliacaoId); if(avaliacao == null){ return Response.status(404).build(); } return Response.ok(avaliacao).build(); }
AvaliacaoResource gera XML ou JSON
Cliente envia tipo desejado no header Accept
API fácil para definir corpo e status da resposta
Diferentes formatos tratados declarativamente
Mapeamento Java <-> XML
JAXB é a forma padrão, sempre disponível
Anotações mapeiam classes e atributos
Jersey gera JSON a partir do XML gerado
@XmlRootElement(name = "feedback") public class Avaliacao { @XmlElement(name = "feedbackCode") private String codAvaliacao; @XmlElement(name = "rater") private Usuario avaliador; @XmlElement(name = "positive") private boolean positiva; @XmlElement(name = "comment") private String comentario; } JAXB é muito flexível nos mapeamentos
Parsing do corpo da requisição
Recurso declara formatos esperados
JAX-RS faz conversões Java <-> diferentes formatos
E se o corpo da requisição veio inválido?
Status HTTP 400 – Bad Request
Como indicar o erro? <erro> <codigo> 2319 </codigo> <mensagem> Atributo XPTO é obrigatório </mensagem> </erro> <erros> <erro> <codigo> 2319 </codigo> <mensagem> Atributo XPTO é obrigatório </mensagem> </erro> ... </erros> OU
Clientes Java
Requisições HTTP com commons-http-client
Mapeamento Java/XML e XML/Java com XStream ou JAXB
Status HTTP é o mais importante
Alguns headers são importantes também
Exemplo: Avaliação de usuário
Obter usuário avaliador e o avaliado
Obter dados da avaliação
Montar URI da avaliação
Gerar corpo da requisição
Conferir resposta
Cliente:
Exemplo: Avaliação de usuário
Validar URI + método HTTP
Parsing da URI para obtenção dos usuários
Parsing do corpo da requisição
Chamada ao Service Layer
Geração da resposta
Servidor:
Status HTTP da resposta
Header Location
RESTFul DSL
Principais Status HTTP Sucesso na solicitação. Resposta sem corpo. 204 Tipo de conteúdo não suportado 415 Erro interno no servidor 500 Método HTTP não permitido para a URI 405 Recurso inexistente 404 Requisição inválida 400 Recurso criado com sucesso 201 Solicitação realizada com sucesso 200 Utilização Status
Dúvidas comuns
Como tratar a paginação de resultados?
Como implementar links entre recursos?
Como lidar com acessos concorrentes?
Como autenticar/autorizar operações?
Atom + AtomPub + Apache Abdera
Blueprint de implementação REST
Excelente para conteúdo web
Google, Microsoft e Globo.com já usam
Descritores de serviços REST WADL Enorme debate. Não existe padrão. Você decide! Combinação estranha. Faz algum sentido? Coleções disponíveis e tipos de conteúdo aceitos. Precisamos de um WSDL RESTful? WSDL 2.0 permite descrever REST Documento de serviços AtomPub Lista URIs, métodos HTTP e tipos de conteúdo aceitos. Gerado automaticamente pelo Jersey.
Conclusão
Web services antigamente:
Troca de performance por interoperabilidade
Web services atualmente:
Alta performance E interoperabilidade
Flexibilidade absoluta
Web services no futuro:
Forma padrão de comunicação?
REST everywhere
Dúvidas??
Quer conhecer mais? JM 56 (REST) – Abril/2008 JM 60 (JAX-RS/Jersey) – Agosto/2008
0 comments
Post a comment