rest java one

62
Then Jesus said, "Come to me, all of you who are weary and carry heavy burdens, and I will give you REST." Matthew 11:28

Upload: dextra

Post on 29-Jun-2015

953 views

Category:

Technology


1 download

DESCRIPTION

por Eder Ignatowicz - Senior Architect na Dextra Sistemas

TRANSCRIPT

Then Jesus said, "Come to me, all of you who are weary and carry heavy burdens,

and I will give you REST."Matthew 11:28

Approaching Pure REST in Java:

HATEOAS and HTTP TuningEder Ignatowicz

Senior Architect, Dextra

JavaOne LATAM 2012

Software Craftsman @ Dextra(Arquitetura, NoSQL, Devops, QA)

Doutorando na Unicamp (Polyglot Persistence em Cidades Digitais)

Professor na Faccamp e Unisal

Editor líder no InfoQ Brasil

@ederign

DextraGalera Ponta Firme e que Manda bem

Ambiente de Melhoria ContínuaProjet

os De

safia

dores

Quali

dade

de Vi

da

DextraGalera Ponta Firme e que Manda bem

Ambiente de Melhoria ContínuaProjet

os De

safia

dores

Quali

dade

de Vi

da

WE’RE HIRING!!!

O mundo, antes de REST

TEMPOS DIFÍCEIS...

MUITOS “PADRÕES”RMI, Corba, DCOM

MUITOS FORNECEDORESSun, Microsoft, OASIS, OMG

MUITAS LÁGRIMASNão existia interoperabilidade

Reinvenção da rodaVendor “lock-in”

SOAP WEB SERVICES

Então surgiu o REST!!!

RESTREpresentational State Transfer

Roy F

ieldin

g Diss

erta

tion

ESTILO DE ARQUITETURA DE SOFTWARE PARA SISTEMASDISTRIBUÍDOS HYPERMEDIA SEMELHANTES A WORLDWIDE WEB

PRINCÍPIOS E RESTRIÇÕES REST

CLIENTE-SERVIDORSERVIDOR STATELESS

CACHEINTERFACE UNIFORME

IDENTIFICAÇÃO DE RECURSOSMANIPULAÇÃO DESTES RECURSOS ATRAVÉS DE REPRESENTAÇÕES

MENSAGENS AUTO-DESCRITIVASHYPERMEDIA COMO ENGINE DO ESTADO DA APLICAÇÃO

ARQUITETURA EM CAMADASCÓDIGO SOB DEMANDA

(OPCIONAL)

CACH

E

HATEOASHTTP tunning

PUT

Buscar recursos, cache

Criar um novo recurso

Atualizar (todo o) recurso existente

Remover um recurso

Atualizar (parte de) um recurso

DELETE

PATCH

POST

GET

VERBO URI (Substantivo) AçãoPOST /bookmarks/create CriarGET /bookmarks/show/1 Visualizar

POST /bookmarks/update/1 AlterarGET/POST /bookmarks/delete/1 Apagar

NÃO RESTful

VERBO URI (Substantivo) AçãoPOST /bookmarks/ CriarGET /bookmarks/1 VisualizarPUT /bookmarks/1 Alterar

DELETE /bookmarks/1 Apagar

RESTful

NOSSOS SONHOS NA INTEGRAÇÃO DE SISTEMASESCALABILIDADE

SEGURANÇA

BAIXO ACOPLAMENTO

TOLERÂNCIA A FALHAS

Mas extremamente mal compreendida...

“O que precisa ser feito para que entendam que no estilo arquitetural REST o hypertext é um

pré-requisito?Em outras palavras, se a engine do estado da

aplicação (e consequentemente sua API) não é guiada por hypertext, então sua aplicação não

pode ser RESTful e nem ter uma API REST. PONTO. Existe por ai algum manual que necessite ser

consertado?”

”Roy Thomas Fielding

HYPERMEDIA

Richardson’s Maturity Model

Nível 0: O pântano do POX

Nível1: Recursos

Nível 2: Verbos HTTP

Nível 3: Controles Hypermedia

REST Sagrado

Nível 0: O pântano do POX

Uma URI, um método HTTPXML-RPC / SOAP / POX

HTTP usado como transporte

POST /agendamentoService HTTP/1.1[headers...]

<appointmentRequest> <slot doctor = "rcmito" start = "1400" end = "1450"/> <patient id = "ederi"/></appointmentRequest>

Nível 1: RecursosCada recurso tem uma única URI

URI tunnelingUm único verbo HTTP (POST ou GET)

HTTP usado como transporte

POST /slots/1234 HTTP/1.1[headers...]

<appointmentRequest> <patient id = "ederi" /></appointmentRequest>

Level 2: HTTP VerbsMuitas URIs, utilizando corretamente

os verbos HTTPUso correto dos códigos de respostaExpõe estado e não comportamento

CRUDGET /doctors/rcmito/slots?date=20121010?status=open HTTP/1.1[headers...]HTTP/1.1 200 OK

<openSlotList> <slot id = “1234” start=”1400” end=”1450” /> <slot id = “1234” start=”1600” end=”1650”/></openSlotList>

Níveis 0,1 e 2 não são RESTful

(e nem REST)

Nível 3: Controles Hypermedia

Hypermedia As The Engine of Application State (HATEOAS)

Recursos auto descritivos

Clientes só precisam saber a URI root (home page) de uma API e os media types utilizados

O resto é HTTP e links

O nome Representational State Transfer foi escolhido com a intenção de criar uma imagem de

como uma aplicação Web bem desenvolvida se comporta: uma rede de páginas web (máquina de

estados), onde o usuário navega selecionando links (transições de estados), resultando na

próxima página (próximo estado da aplicação).

”Roy Thomas Fielding

ESTADO

ESTADOESTADO

ESTADOESTADO

http://uri

Transição

Transição

Transição

Transição

HTTP/1.1 201 CreatedLocation: http://jogano10.com/slots/1234/appointment[various headers]

<appointment> <slot id = "1234" doctor = "rcmito" start = "1400" end = "1450"/> <patient id = "ederi"/> <link rel = "/linkrels/appointment/cancel" uri = "/slots/1234/appointment"/> <link rel = "/linkrels/appointment/addTest" uri = "/slots/1234/appointment/tests"/> <link rel = "self" uri = "/slots/1234/appointment"/> <link rel = "/linkrels/appointment/updateContactInfo" uri = "/patients/ederi/contactInfo"/></appointment>

Isto é

RESTFUL

As três grandes invenções da nossa

história são:

HYPERLINK !!!

JAX-RS API

@Path("/cartao/{cardId}")public class Cartao {

@GET @Path("/saldo") @Produces("text/plain") public Saldo saldo(@PathParam("cardId") String card) { return getSaldo(card); }...}

HTTP Method Binding Serialização

automática

Recursos

Injeção dos parâmetros

JAX-RS API

JAX-RS APISUPORTE A HATEOAS

// Server APIResponse res = Response.ok(order) .link("http://.../orders/1/ship", "ship") .build(); // Client APIResponse order = client.target(…) .request("application/xml").get();

if (order.getLink(“ship”) != null) { Response shippedOrder = client .target(order.getLink("ship")) .request("application/xml").post(null); }

HypermediaSuporte a HATEOAS

REST sem HATEOAS não é REST

Não devem existir verbos na sua URI

Mas, eu preciso mais do que a semântica

GET/POST/PUTDELETE/PATCH "But my model is different!".

You are not a special or unique snowflake.- should I build another protocol? - should I add a new HTTP method?- answer 1: tough shit. you're wrong, it can be modeled with the uniform interface, it's sufficiently general.

Concorrência?If you do two PUTs at once, one wins. The solution depends on what you need. For a lot of applications, "last update wins" is a fine strategy. If not, Etags are the solution.

Transações... ?!?I want to debit one guy's account at the same time, and only if, I can credit another guy's account. I could do two PUTs in a row, but that's begging for inconsistencies to creep into the system.answer 1: YAGNI. Answer 2: what you probably want is a new resource to encapsulate

Não existe a necessidade de API nem de

versionamento de APIs!!!- So Iʼll wrap up where we started. Youʼll find that the closer you move to REST, the less of a distinct API youʼll have at all. The “regular” application and its API will become one.- The rub, and itʼs a big rub, is not a technical one but a social one. Building on a API requires trust of stability, and “traditional” websites donʼt provide for

http://2.bp.blogspot.com/-JmDsZ1ESAWg/TyiHY8MMdzI/AAAAAAAAEDs/lFZxR0z5fGk/s1600/escalada1.jpg

Escalabilidade HTTP + JAX-RS

HTTP Cach

ing

Local Cache “The Proxies”

Translation Proxy

Reverse Proxy

Web Server

HTTPCaching features

allowed (or not)expiration

intermediary caches allowed (or not)

validationstorable(or not)

HTTP Quando “cachear”?

Expires headerExpires: Sun, 04 Aug 2012 16:00 GMT

Cache-control headerCache-Control: no-cache

Cache-Control: public, max-age=3000

Validation HeaderLast-Modified: Mon, 29 Jun 2012 02:28:12 GMT

ETag: "3e86-410-3596fbbc"

JAX-RS e Cache Control

@Path("/doutores")public class DoutoresService { @Path("/{id}") @GET @Produces("application/xml") public Response getDoutores(@PathParam("id") int id) { List<Doutor> doutores = //getDoutores CacheControl cc = new CacheControl(); cc.setMaxAge(3000); return Response.ok(doutores).cacheControl(cc).build(); }}

JAX-RS e Gets Condicionais

Last-Modified: Mon, 29 Jun 2012 02:28:12 GMTETag: "3e86-410-3596fbbc"

O cache está valido?304 “Not Modified”

Não está?200 “OK” + recurso válido

@Path("/doutores")public class DoutoresService { @Path("/{id}") @GET @Produces("application/xml") public Response getDoutores(@PathParam("id") int id, @Context Request request) { EntityTag tag = // get tag mais atualizada ResponseBuilder builder = null;

builder = request.evaluatePreconditions(tag); if (builder != null){ return builder.cacheControl(cc).build(); } Object doutores = // getDoutores return Response.ok(doutores).cacheControl(cc).build(); }}

JAX-RS e Cache-Control

@Path("/doutores")public class DoutoresService { @Path("/{id}") @GET @Produces("application/xml") public Response getDoutores(@PathParam("id") int id) { List<Doutor> doutores = //getDoutores CacheControl cc = new CacheControl(); cc.setMaxAge(3000); return Response.ok(doutores).cacheControl(cc).build(); }}

O mesmo princípio se aplica para PUTs e POSTs

condicionais(updates concorrentes)

JSR 339: JAX-RS 2.0

Public Review Ballot 24/11/2012

Adopt a JSR

Client API @Before public void setUp() throws Exception { // start the server server = Main.startServer(); // create the client Client c = ClientFactory.newClient(); target = c.target(Main.BASE_URI); }

@After public void tearDown() throws Exception { server.stop(); }

@Test public void testExtratoSemHATEOAS() { String responseMsg = target.path("cartao/1/saldo").request() .get(String.class); assertEquals(value, responseMsg); }

Interceptors/Handlers

Pontos de extensão: Logging, Compression, Security, etc.

@Providerclass LoggingFilter implements RequestFilter, ResponseFilter {

@Override public FilterAction preFilter(FilterContext ctx) throws IOException { logRequest(ctx.getRequest()); return FilterAction.NEXT; } @Override public FilterAction postFilter(FilterContext ctx) throws IOException { logResponse(ctx.getResponse()); return FilterAction.NEXT; }

Async

Suporte na API Client

// Acesso URITarget target = client.target("http://.../atm/balance")… // Chamada async e callbackFuture<?> handle = target.request().async().get( new InvocationCallback<String>() { public void complete(String balance) { … } public void failed(InvocationException e) { … } });

Java <3

@ederign