Transações compensatórias usando REST
Bruno Pereira bruno.pereira@concretesolutions.com.br
Luca Bastos
luca.bastos@concretesolutions.com.br
Apresentada no Qcon São Paulo/2011
3. Outro Título
Transação com REST é um oximoro(*)?
(*)
Segundo
a
wikipedia,
figura
de
linguagem
que
harmoniza
dois
conceitos
opostos
numa
só
expressão,
formando
assim
um
terceiro
conceito
que
dependerá
da
interpretação
do
leitor.
4. Life
is
a
distributed
object
system.
However,
communicaGon
among
humans
is
a
distributed
hypermedia
system,
where
the
mind's
intellect,
voice
+gestures,
eyes+ears,
and
imaginaGon
are
all
components.
Roy
T.
Fielding,
1998.
5. Bruno Pereira:
Gerente
de
operações
e
pré-‐venda
na
Concrete
SoluGons,
atual
responsável
pelo
escritório
de
SP.
Trabalhou
em
grandes
projetos
na
Globo.com,
Globosat,
Alcoa,
White
MarGns
e
outros.
Engenheiro
eletrônico
e
de
computação
na
UFRJ.
Experiência
em
muitos
projetos
web,
com
experGse
no
server-‐side
e
client-‐side.
Um
dos
pioneiros
na
adoção
de
REST
no
Brasil.
6. Luca Bastos:
Desenvolvedor
do
tempo
da
Carochinha.
Se
mantém
na
aGva
por
pura
paixão.
Ávido
leitor
sendo
o
hábito
da
leitura
um
dos
seus
3
principais
prazeres
na
vida.
Segue
como
esforçado
e
curioso
aprendiz
na
árdua,
porém
gostosa
tentaGva
de
se
manter
atualizado.
Hoje
exerço
minha
paixão
na
Concrete
SoluGons
7. Onde trabalhamos:
http://www.concretesolutions.com.br/
A Concrete tem mais de10 anos com variado portfólio de
clientes no Brasil e no exterior. No início as maiores
demandas do mercado eram soluções para integração.
Atualmente a diversificação é bem grande tantos nos
projetos como nas tecnologias e nas linguagens utilizadas.
Temos projetos nas áreas de cloud, mobile e web.
Muitos são como alguns de São Paulo para lean startups.
27. Segundo Roy Fielding,
estilo de arquitetura é um conjunto
coordenado de restrições arquiteturais
28. Segundo Roy Fielding,
estilo de arquitetura é um conjunto
coordenado de restrições arquiteturais
que limitam os papéis e habilidades dos
elementos arquiteturais e os relacionamentos
permitidos dentre eles,
29. Segundo Roy Fielding,
estilo de arquitetura é um conjunto
coordenado de restrições arquiteturais
que limitam os papéis e habilidades dos
elementos arquiteturais e os relacionamentos
permitidos dentre eles,
dentro de qualquer arquitetura que esteja em
conformidade com tal estilo.
30. De forma simplista,
podemos dizer que REST
é um conjunto de restrições
ao projeto de um sistema hipermídia.
31. Restrições básicas do estilo de arquitetura
REST:
1. Identificação dos recursos
2. Interface uniforme
3. Mensagens auto descritivas
4. Hipermídia comandando o estado
5. Interações sem estado
32. É possível projetar uma arquitetura
com transações distribuídas
dentro das restrições do REST?
33. É possível projetar uma arquitetura
com transações distribuídas
dentro das restrições do REST?
Ou precisamos relaxar algumas das restrições
do Roy Fielding?
34.
35. Vamos demonstrar como fazer transações
dentro das restrições da arquitetura REST
usando um caso prático:
Reserva de passagens aéreas
36.
37. Problema
de
uma
agência
de
viagens:
Reservar
passagens
em
2
trechos
independentes
ligando
vôos
de
2
empresas
aéreas
Agência
A
B
38. Problema
de
uma
agência
de
viagens:
Reservar
passagens
em
2
trechos
independentes
ligando
vôos
de
2
empresas
aéreas
sem
ônus
se
uma
delas
falhar
Agência
A
B
40. Simplificação:
Supomos
que
as
2
empresas
aéreas
usam
o
mesmo
contrato
de
hipermídia
para
reservas
41. Microformato
que
poderia
ser
usado
div
class=reserva
pendente
div
class=voo
span
class=numero1520/span
span
class=companhiaVerde/span
span
class=origemSAO
PAULO/span
span
class=desGnoBRASILIA/span
span
class=saida01/10/2011
10:00/span
span
class=chegada01/10/2011
11:40/span
/div
/div
42. XML
Tradicional
com
dados
relevantes
reserva
voo
numero=1520
companhia=Verde
origem=SAO
PAULO
desGno=BRASILIA
saida=01/10/2011
10:00
chegada=01/10/2011
11:40”
/voo
/reserva
43. URI
para
checar
disponibilidade
de
um
vôo:
/voo/{voo-‐num}/
A
resposta
de
uma
requisição
GET
a.com/voo/1001/
poderá
ser
um
hyperlink
para
a
idenGficação
do
recurso
vôo
ou
nada
se
o
vôo
está
lotado
(204
sem
conteúdo)
44. Dados
de
um
Vôo
voo
id=123456789
numero=1520
companhia=Verde
origem=SAO
PAULO
desGno=BRASILIA
saida=01/10/2011
10:00
chegada=01/10/2011
11:40”
/voo
45. Reserva
de
um
determinado
vôo:
O
request
POST
/reserva
46. Reserva
de
um
determinado
vôo:
O
request
POST
/reserva
incluindo
no
conteúdo
do
POST
a
referência
ao
vôo:
voo
numero=“xpto”
/
47. Reserva
de
um
determinado
vôo:
O
request
POST
/reserva
incluindo
no
conteúdo
do
POST
a
referência
ao
vôo:
voo
numero=“xpto”
/
cria
um
novo
recurso
reserva
com
seu
id
devolvendo
um
header
locaGon
com
o
caminho
do
recurso
/reserva/{id}/
48. Reserva
de
um
determinado
vôo:
O
request
POST
/reserva
incluindo
no
conteúdo
do
POST
a
referência
ao
vôo:
voo
numero=“xpto”
/
cria
um
novo
recurso
reserva
com
seu
id
devolvendo
um
header
locaGon
com
o
caminho
do
recurso
/reserva/{id}/
A
reserva
pode
ser
atualizada
usando
PUT
/reserva/{id}/
49. reserva
id=“123456”
voo
numero=1520
companhia=Verde
origem=SAO
PAULO
desGno=BRASILIA
saida=01/10/2011
10:00
chegada=01/10/2011
11:40”
/voo
link
rel=“update”
href=“/reserva/123456”
/
/reserva
A
reserva
pode
ser
atualizada
usando
PUT
/reserva/{id}/
50. Composição
das
reservas:
História
1
Como
cliente,
quero
reservar
vôos
em
2
trechos
independentes
ligando
vôos
de
2
empresas
aéreas.
É
responsabilidade
da
agência
compor
os
serviços.
51. Sem
pensar
em
transação,
poderia
ser
assim:
1.
GET
a.com/voo/1001/
2.
GET
b.com/voo/2002/
3.
POST
a.com/reserva
4.
POST
b.com/reserva
52. Sem
pensar
em
transação,
poderia
ser
assim:
1.
GET
a.com/voo/1001/
2.
GET
b.com/voo/2002/
3.
POST
a.com/reserva
4.
POST
b.com/reserva
E
se
a
segunda
empresa
diz
que
não
tem
lugar
no
vôo?
53. Sem
pensar
em
transação,
poderia
ser
assim:
1.
GET
a.com/voo/1001/
2.
GET
b.com/voo/2002/
3.
POST
a.com/reserva
4.
POST
b.com/reserva
E
se
a
segunda
empresa
diz
que
não
tem
lugar
no
vôo?
A
solução
pode
ser
fazer
com
que
os
passos
das
reservas
3
e
4
sejam
tentaGvas
que
podem
ser
confirmadas
depois.
54. Disclaimer:
Quase
tudo
mostrado
aqui
se
baseia
no
capítulo
23
do
livro
REST:
From
Research
to
PracGce
Towards
Distributed
Atomic
TransacGons
over
RESTful
Services
de
Guy
Pardon
(Atomikos)
e
Cesare
Pautasso
55. O
Gpo
de
solução
proposta
serve
a
aplicações
distribuídas
que
precisam
de
atomicidade.
56. O
Gpo
de
solução
proposta
serve
a
aplicações
distribuídas
que
precisam
de
atomicidade.
Se
baseia
no
conceito
TCC,
Try-‐Cancel/Confirm
do
Guy
Pardon,
que
tem
semelhança
com
as
práGcas
de
aplicações
financeiras
que
usam
transações
compensatórias.
57. O
Gpo
de
solução
proposta
serve
a
aplicações
distribuídas
que
precisam
de
atomicidade.
Se
baseia
no
conceito
TCC,
Try-‐Cancel/Confirm
do
Guy
Pardon,
que
tem
semelhança
com
as
práGcas
de
aplicações
financeiras
que
usam
transações
compensatórias.
É
adequado
aos
cenários
que
envolvem
reserva
de
recursos.
58. O
Gpo
de
solução
proposta
serve
a
aplicações
distribuídas
que
precisam
de
atomicidade.
Se
baseia
no
conceito
TCC,
Try-‐Cancel/Confirm
do
Guy
Pardon,
que
tem
semelhança
com
as
práGcas
de
aplicações
financeiras
que
usam
transações
compensatórias.
É
adequado
aos
cenários
que
envolvem
reserva
de
recursos.
O
recurso
no
estado
de
reservado
aparece
para
todos
e
isto
evita
dupla
reserva.
59. Confirmação
das
reservas:
História
2
Como
cliente,
quero
ser
capaz
de
confirmar
as
reservas
no
fim
de
tudo
e
que
as
reservas
não
confirmadas
não
sejam
cobradas.
60. O
Serviço
REST
da
empresa
aérea
retorna
um
hyperlink
de
confirmação.
Exemplo:
GET
/reserva/{id}
recebe
como
resposta
reserva
id={id}
link
rel=“confirma”
href=”/reserva/{id}/pagamento”
/reserva
O
pagamento
pode
ser
confirmado
com:
PUT
/reserva/{id}/pagamento
contendo
VISA
...
61. Workflow
do
caminho
feliz
GET
a.com/voo/1001/
200
POST
a.com/reserva
201
(locaGon
/reserva/A
)
GET
b.com/voo/2002/
200
POST
b.com/reserva
201
(locaGon
/reserva/B
)
GET
a.com/reserva/A
200
(link
para
confirmar:
/reserva/{id}/pagamento/
)
GET
b.com/reserva/B
200
(link
para
confirmar:
/reserva/{id}/pagamento/
)
62. Confirmações
usando
o
hyperlink
de
pagamento
recebido:
reserva
id
link
rel=“confirma”
href=“/reserva/{id}/pagamento/”
/reserva
PUT
a.com/reserva/{id}/pagamento/
200
PUT
b.com/reserva/{id}/pagamento/
200
63. Lembram
dos
passos
1.
GET
a.com/voo/1001/
2.
GET
b.com/voo/2002/
3.
POST
a.com/reserva
4.
POST
b.com/reserva
64. Lembram
dos
passos
1.
GET
a.com/voo/1001/
2.
GET
b.com/voo/2002/
3.
POST
a.com/reserva
4.
POST
b.com/reserva
Mas
e
se
o
passo
4
que
é
a
segunda
reserva
falhar?
65. Cancelamento
das
reservas:
História
3
Como
empresa
aérea
não
quero
esperar
indefinidamente
por
uma
confirmação.
Quero
cancelar
uma
reserva
pendente
após
um
certo
período
de
tempo
(Gmeout).
66. A
empresa
aérea
ao
receber
POST
/reserva/
Retorna
reserva
id={id}
link
rel=“confirma”
href=“/reserva/{id}/pagamento/”
limite=“24h”
/reserva
74. Conceituando
transações
REST
Recursos
publicados
por
Web
services
RESTful
devem
ser
enGdades
independentes.
Segundo
Pautasso
e
Wilde,
uma
solução
de
transação
para
REST
é
desacoplada
se
os
serviços
parGcipantes
não
tem
consciência
de
que
são
parte
de
uma
transação.
75. Conceituando
transações
REST
Recursos
publicados
por
Web
services
RESTful
devem
ser
enGdades
independentes.
Segundo
Pautasso
e
Wilde,
uma
solução
de
transação
para
REST
é
desacoplada
se
os
serviços
parGcipantes
não
tem
consciência
de
que
são
parte
de
uma
transação.
Não
são
todos
os
serviços
RESTful
capazes
de
parGcipar
em
transações
assim.
76. Protocolos
da
solução
proposta
Definição
de
T,
R
e
S:
T
é
uma
transação
baseada
em
REST
composta
de
requests
Ri
para
serviços
Si
que
devem
ser
confirmados
ou
cancelados
juntos.
77. Protocolos
da
solução
proposta
Definição
de
T,
R
e
S:
T
é
uma
transação
baseada
em
REST
composta
de
requests
Ri
para
serviços
Si
que
devem
ser
confirmados
ou
cancelados
juntos.
Exemplo:
T
é
a
transação
de
reserva
dos
vôos,
R
reserva
de
um
vôo
e
S
é
o
serviço
acessado.
78. Protocolos
da
solução
proposta
Definição
de
T,
R
e
S:
T
é
uma
transação
baseada
em
REST
composta
de
requests
Ri
para
serviços
Si
que
devem
ser
confirmados
ou
cancelados
juntos.
Exemplo:
T
é
a
transação
de
reserva
dos
vôos,
R
reserva
de
um
vôo
e
S
é
o
serviço
acessado.
Os
Ri
bem
sucedidos
tem
confirmação
explicita
Ri,confirma
(via
pagamento
da
reserva)
79. Protocolos
da
solução
proposta
Definição
de
T,
R
e
S:
T
é
uma
transação
baseada
em
REST
composta
de
requests
Ri
para
serviços
Si
que
devem
ser
confirmados
ou
cancelados
juntos.
Exemplo:
T
é
a
transação
de
reserva
dos
vôos,
R
reserva
de
um
vôo
e
S
é
o
serviço
acessado.
Os
Ri
bem
sucedidos
tem
confirmação
explicita
Ri,confirma
(via
pagamento
da
reserva)
e
todos
os
Ri
não
confirmados
são
cancelados.
80. Importante:
O
uso
do
protocolo
Try-‐Cancel/Confirm
é
a
única
exigência
que
se
faz
aos
prestadores
dos
serviços
para
esta
solução
funcionar.
Através
de
um
acordo
de
negócios,
é
preciso
garanJr
que
caso
o
prestador
do
serviço
(neste
caso
uma
empresa
aérea)
NÃO
receba
a
confirmação
dentro
do
Gmeout
(PUT
do
pagamento),
DEVE
cancelar
a
transação.
Caso
a
agência
não
receba
resposta
do
PUT
de
uma
empresa
aérea,
cancelará
as
reservas
feitas
com
sucesso
nas
outras.
81. Arquitetura
para
o
caminho
feliz
1.
Um
workflow
transacional
T
envia
requests
a
disGntas
APIs
de
Web
services
RESTful
Si.
2.
Requests
Ri
podem
acarretar
mudanças
de
estado
em
algum
serviço
Si
idenGficado
por
alguma
URI.
83. Arquitetura
para
o
caminho
feliz
1.
Um
workflow
transacional
T
envia
requests
a
disGntas
APIs
de
Web
services
RESTful
Si.
2.
Requests
Ri
podem
acarretar
mudanças
de
estado
em
algum
serviço
Si
idenGficado
por
alguma
URI.
3.
Com
o
workflow
bem
sucedido,
as
URIs
de
confirmação
e
mais
os
conteúdos
são
passados
ao
coordenador.
84. Try
0
1
Cliente
Motor
Workflow
1
2
3
Try
Confirm
Coordenador
de
transações
2
85. Arquitetura
para
o
caminho
feliz
1.
Um
workflow
transacional
T
envia
requests
a
disGntas
APIs
de
Web
services
RESTful
Si.
2.
Requests
Ri
podem
acarretar
mudanças
de
estado
em
algum
serviço
Si
idenGficado
por
alguma
URI.
3.
Com
o
workflow
bem
sucedido,
as
URIs
de
confirmação
e
mais
os
conteúdos
são
passados
ao
coordenador.
4.
O
coordenador
chama
todos
os
Ri,confirma
com
um
PUT
idempotente
às
URIs
passadas
e
inclui
os
conteúdos
86. Try
0
1
Cliente
Motor
Workflow
1
2
3
Confirm
Try
Confirm
Coordenador
de
4
transações
2
4
Confirm
88. Protocolo
de
recuperação
em
caso
de
falha
Recuperação
precisa
ocorrer
quando:
1)
Falha
de
nó
2)
Timeout
89. Protocolo
de
recuperação
em
caso
de
falha
Recuperação
precisa
ocorrer
quando:
1)
Falha
de
nó
2)
Timeout
Um
serviço
Si
só
reage
se
a
falha
ocorre
entre
os
passos
de
reserva
e
de
confirmação
(2
e
4).
Neste
caso
executa
Ri,cancela
automaGcamente.
90. Protocolo
de
recuperação
em
caso
de
falha
Recuperação
precisa
ocorrer
quando:
1)
Falha
de
nó
2)
Timeout
Um
serviço
Si
só
reage
se
a
falha
ocorre
entre
os
passos
de
reserva
e
de
confirmação
(2
e
4).
Neste
caso
executa
Ri,cancela
automaGcamente.
O
coordenador
só
reage
durante
o
passo
das
confirmações
(passo
4.
Se
falta
resposta
de
um
Si,
tenta
de
novo
Ri,confirma.
Ri,confirma
usa
métodos
idempotentes
e
pode
tentar
muitas
vezes.
91. Protocolo
de
recuperação
em
caso
de
falha
Importante:
É
preciso
um
log
no
coordenador
começando
antes
do
passo
4
das
confirmações.
92. Caso
de
exceção
No
passo
4
de
confirmações,
algum
serviço
Si
pode
cancelar
por
Gmeout
enquanto
o
coordenador
segue
tentando
confirmar.
Sem
adotar
nenhuma
aGtude,
isto
quebraria
a
atomicidade.
93. Caso
de
exceção
No
passo
4
de
confirmações,
algum
serviço
Si
pode
cancelar
por
Gmeout
enquanto
o
coordenador
segue
tentando
confirmar.
Sem
adotar
nenhuma
aGtude,
isto
quebraria
a
atomicidade.
Perfeição
NÃO
existe.
O
mesmo
pode
acontecer
com
as
transações
clássicas
no
esGlo
XA,
2PC
ou
usando
WS-‐*.
Esta
é
uma
limitação
que
devemos
conviver.
94. HeurísGca
de
exceção
Quando
um
parGcipante
completa
Ri,
pode
ser
considerado
em
dúvida.
Seu
estado
já
persisGu
e
só
falta
a
confirmação
pendente
Ri,confirma.
Se
opta
por
Gmeout,
a
transação
T
deve
ter
uma
heurísGca
de
rollback
(desfazimento).
95. HeurísGca
de
exceção
Quando
um
parGcipante
completa
Ri,
pode
ser
considerado
em
dúvida.
Seu
estado
já
persisGu
e
só
falta
a
confirmação
pendente
Ri,confirma.
Se
opta
por
Gmeout,
a
transação
T
deve
ter
uma
heurísGca
de
rollback
(desfazimento).
O
modo
de
lidar
com
isto
é
simplesmente
o
coordenador
ter
um
log
para
perceber
que
suas
tentaGvas
de
confirmação
estão
sem
resposta.
96. HeurísGca
de
exceção
Quando
um
parGcipante
completa
Ri,
pode
ser
considerado
em
dúvida.
Seu
estado
já
persisGu
e
só
falta
a
confirmação
pendente
Ri,confirma.
Se
opta
por
Gmeout,
a
transação
T
deve
ter
uma
heurísGca
de
rollback
(desfazimento).
O
modo
de
lidar
com
isto
é
simplesmente
o
coordenador
ter
um
log
para
perceber
que
suas
tentaGvas
de
confirmação
estão
sem
resposta.
E
quando
isto
acontecer
soltar
um
alerta
para
que
uma
ação
manual
da
operação
do
sistema
possa
desfazer
as
confirmações
órfãs
já
respondidas.
97. OGmizações
possíveis
1.
Incluir
na
respostas
dos
serviços
um
link
para
cancelamento.
Vantagem:
evitar
que
o
coordenador
tenha
que
esperar
o
Gmeout
para
liberar
o
recurso.
98. OGmizações
possíveis
1.
Incluir
na
respostas
dos
serviços
um
link
para
cancelamento.
Vantagem:
evitar
que
o
coordenador
tenha
que
esperar
o
Gmeout
para
liberar
o
recurso.
2.
PermiGr
ao
coordenador
gerenciar
o
tempo
de
Gmeout
e
assim
nem
começar
as
tentaGvas
de
confirmação
perto
do
fim.
99. OGmizações
possíveis
1.
Incluir
na
respostas
dos
serviços
um
link
para
cancelamento.
Vantagem:
evitar
que
o
coordenador
tenha
que
esperar
o
Gmeout
para
liberar
o
recurso.
2.
PermiGr
ao
coordenador
gerenciar
o
tempo
de
Gmeout
e
assim
nem
começar
as
tentaGvas
de
confirmação
perto
do
fim.
3.
O
coordenador
ter
um
diálogo
com
os
serviços
para
os
casos
de
exceção.
100. OGmizações
possíveis
1.
Incluir
na
respostas
dos
serviços
um
link
para
cancelamento.
Vantagem:
evitar
que
o
coordenador
tenha
que
esperar
o
Gmeout
para
liberar
o
recurso.
2.
PermiGr
ao
coordenador
gerenciar
o
tempo
de
Gmeout
e
assim
nem
começar
as
tentaGvas
de
confirmação
perto
do
fim.
3.
O
coordenador
ter
um
diálogo
com
os
serviços
para
os
casos
de
exceção.
4.
Enfraquecer
premissas
do
padrão
TCC
em
casos
especiais
(ex.
GET
read
only)
101. O
que
vimos:
Uma
solução
leve
e
atômica
para
transações
via
REST,
baseada
na
aplicação
do
modelo
Try-‐Cancel/Confirm
ao
projeto
de
um
sistema
usando
Web
services
RESTful.
102. O
que
vimos:
Uma
solução
leve
e
atômica
para
transações
via
REST,
baseada
na
aplicação
do
modelo
Try-‐Cancel/Confirm
ao
projeto
de
um
sistema
usando
Web
services
RESTful.
Um
exemplo
de
um
protocolo
simples
que
consegue
atomicidade
e
desacoplamento
entre
recursos
distribuídos
se
eles
forem
compa•veis
com
o
padrão
Try-‐Cancel/Confirm.
103. O
que
vimos:
Uma
solução
leve
e
atômica
para
transações
via
REST,
baseada
na
aplicação
do
modelo
Try-‐Cancel/Confirm
ao
projeto
de
um
sistema
usando
Web
services
RESTful.
Um
exemplo
de
um
protocolo
simples
que
consegue
atomicidade
e
desacoplamento
entre
recursos
distribuídos
se
eles
forem
compa•veis
com
o
padrão
Try-‐Cancel/Confirm.
Que
seu
uso
garante
atomicidade
e
consistência
no
caso
de
falhas
com
as
mesmas
limitações
das
soluções
clássicas.
104. O
que
vimos:
Uma
solução
leve
e
atômica
para
transações
via
REST,
baseada
na
aplicação
do
modelo
Try-‐Cancel/Confirm
ao
projeto
de
um
sistema
usando
Web
services
RESTful.
Um
exemplo
de
um
protocolo
simples
que
consegue
atomicidade
e
desacoplamento
entre
recursos
distribuídos
se
eles
forem
compa•veis
com
o
padrão
Try-‐Cancel/Confirm.
Que
seu
uso
garante
atomicidade
e
consistência
no
caso
de
falhas
com
as
mesmas
limitações
das
soluções
clássicas.
Que
pode
ser
usado
em
todos
os
ambientes
de
desenvolvimento
e
por
qualquer
linguagem
de
programação.
105. Agradecimentos:
Jim
Gray,
Hector
G.
Molina,
Rafael
Alonso,
Kenneth
Selem,
Pat
Helland,
Henry
Korth,
Eliezer
Levy,
Abraham
Silbershatz,
Jim
Webber,
Savas
ParatasGdis,
Ian
Robinson,
Sam
Ruby,
Leonard
Richarson,
Guilherme
Silveira,
Paulo
Silveira,
Subbu
Allamaraju,
Mark
Liƒle,
Boris
Lublinski,
Mercy
Njima,
Thomas
Strandenaes,
Randi
Karlsen,
Robert
Grossman,
Kotagiri
Ramamohanarao,
James
Bailey,
Paolo
Buseƒa,
Eric
Newcomer,
Philip
Bernstein,
Andreas
Reuter,
Stefan
Tilkov,
Erik
Wilde,
Guy
Pardon
e
Cesare
Pautasso
que
foram
fontes
do
conhecimento
aqui
comparGlhado.
106. Agradecimentos:
Jim
Gray,
Hector
G.
Molina,
Rafael
Alonso,
Kenneth
Selem,
Pat
Helland,
Henry
Korth,
Eliezer
Levy,
Abraham
Silbershatz,
Jim
Webber,
Savas
ParatasGdis,
Ian
Robinson,
Sam
Ruby,
Leonard
Richarson,
Guilherme
Silveira,
Paulo
Silveira,
Subbu
Allamaraju,
Mark
Liƒle,
Boris
Lublinski,
Mercy
Njima,
Thomas
Strandenaes,
Randi
Karlsen,
Robert
Grossman,
Kotagiri
Ramamohanarao,
James
Bailey,
Paolo
Buseƒa,
Eric
Newcomer,
Philip
Bernstein,
Andreas
Reuter,
Stefan
Tilkov,
Erik
Wilde,
Guy
Pardon
e
Cesare
Pautasso
que
foram
fontes
do
conhecimento
aqui
comparGlhado.
E
uma
homenagem
especial
ao
Roy
Fielding,
porque
sem
ele
a
Web
seria
outra
ou
nem
seria.
107. Thanks
Roy
REST
rocks
Obrigado
Qcon
SP
2011
Perguntas?
@blpsilva
(visite
o
blog)
@lucabastos