Arquitetura: chega de mesmice

1,358 views

Published on

Apresentação de Guilherme Silveira sobre a arquitetura de sistemas distribuídos de hoje em dia e como a pseudo-integração que fazemos está longe

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,358
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
9
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide













































































  • 1 uri. 1 http verb
  • implementing a specific response






























































































  • Arquitetura: chega de mesmice

    1. 1. Arquitetura: chega de mesmice Guilherme Silveira
    2. 2. Guilherme Silveira guilherme.silveira@caelum.com.br
    3. 3. são paulo
    4. 4. são paulo
    5. 5. são paulo
    6. 6. são paulo
    7. 7. são paulo
    8. 8. Guilherme Silveira guilherme.silveira@caelum.com.br 2002 guj.com.br 2003 vraptor 2004 caelum.com.br xp, xstream 2006 scrum 2009 restfulie, lean 2010 tectura.com.br
    9. 9. bank.com calendar.com travel.com company.com
    10. 10. CORBA heaven?
    11. 11. EJB heaven?
    12. 12. SOAP heaven?
    13. 13. what is REST?
    14. 14. what is the future of integration over the web?
    15. 15. what was REST?
    16. 16. Restful Web Services
    17. 17. Restful Web create a saas account Services
    18. 18. Restful Web create a saas account freeze account Services
    19. 19. Restful Web create a saas account freeze account Services reactivate account
    20. 20. Web Restful Services
    21. 21. Web http Restful Services
    22. 22. Web http port 80 Restful Services
    23. 23. Web http port 80 firewall heaven Restful Services
    24. 24. Web Services Restful
    25. 25. Web Services xml, json Restful
    26. 26. Web Services xml, json Restful get, post, ...
    27. 27. Restful Web Services as of 2009 But what about Hypermidia? What about consumers?
    28. 28. Restful Web Services as of 2009 But what about Hypermidia? What about consumers? There is much more!
    29. 29. unresttrips.com: flight details <?xml version="1.0" encoding="UTF-8" standalum="yes"?> <flight> <information> <from>sao paulo</from> <to>seoul</to> </information>   <value>900.00</value> </flight>
    30. 30. service locator when integrating: coupling++ unrest pay unresttrips.com guilherme
    31. 31. service locator when integrating: coupling++ unrest pay unresttrips.com guilherme
    32. 32. resttrips.com: flight details <?xml version="1.0" encoding="UTF-8" standalum="yes"?> <flight> <information> <from>sao paulo</from> <to>seoul</to> </information>   <value>900.00</value> <link rel="payment" href="http://resttrips.com/payment/custom"/ </flight>
    33. 33. resttrips.com: flight details <?xml version="1.0" encoding="UTF-8" standalum="yes"?> <flight> <information> <from>sao paulo</from> <to>seoul</to> </information>   <value>900.00</value> <link rel="payment" href="http://resttrips.com/payment/custom"/ </flight>
    34. 34. resttrips.com: making the payment flight = Client.at('http://resttrips.com/f/574XR4').get(); confirmation = flight.getLink("payment"). patch(cardInformation, value);
    35. 35. resttrips.com: making the payment flight = Client.at('http://resttrips.com/f/574XR4').get(); confirmation = flight.getLink("payment"). patch(cardInformation, value);
    36. 36. resttrips.com: changing its payment provider <?xml version="1.0" encoding="UTF-8" standalum="yes"?> <flight> <information> <from>sao paulo</from> <to>seoul</to> </information>   <value>900.00</value> <link rel="payment" href="http://paysite.com/custom"/> </flight>
    37. 37. resttrips.com: changing its payment provider <?xml version="1.0" encoding="UTF-8" standalum="yes"?> <flight> <information> <from>sao paulo</from> <to>seoul</to> </information>   <value>900.00</value> <link rel="payment" href="http://paysite.com/custom"/> </flight>
    38. 38. dependency injection when integrating: coupling-- restrips pay resttrips.com guilherme paysite.com
    39. 39. dependency injection when integrating: coupling-- restrips pay resttrips.com guilherme paysite.com
    40. 40. trip = resource http://kayak.com/f/574XR4 payment = resource any_uri_unknown_at_compile_time
    41. 41. não viajo sozinho
    42. 42. meu amigo @sergio_caelum
    43. 43. meu amigo @sergio_caelum Bilu bilu
    44. 44. resttrips.com: sharing a trip flight = Client.at('http://resttrips.com/f/574XR4').get(); confirmation = flight.getLink("payment"). patch(cardInformation, value/2); // send the payment link to another part of the web flight = Client.at('http://resttrips.com/f/574XR4').get(); confirmation = flight.getLink("payment"). patch(cardInformation, value/2);
    45. 45. resttrips.com: sharing a trip flight = Client.at('http://resttrips.com/f/574XR4').get(); confirmation = flight.getLink("payment"). patch(cardInformation, value/2); // send the payment link to another part of the web flight = Client.at('http://resttrips.com/f/574XR4').get(); confirmation = flight.getLink("payment"). patch(cardInformation, value/2);
    46. 46. resttrips.com: sharing a trip flight = Client.at('http://resttrips.com/f/574XR4').get(); confirmation = flight.getLink("payment"). patch(cardInformation, value/2); // send the payment link to another part of the web flight = Client.at('http://resttrips.com/f/574XR4').get(); confirmation = flight.getLink("payment"). patch(cardInformation, value/2);
    47. 47. resttrips.com: sharing a trip flight = Client.at('http://resttrips.com/f/574XR4').get(); confirmation = flight.getLink("payment"). patch(cardInformation, value/2); // send the payment link to another part of the web flight = Client.at('http://resttrips.com/f/574XR4').get(); confirmation = flight.getLink("payment"). patch(cardInformation, value/2);
    48. 48. calendar: integrating my systems myself = Client.at('http://users.calendar.com') .with(auth).get(); myself.link("calendar").patch(flight.link("self"));
    49. 49. calendar: integrating my systems myself = Client.at('http://users.calendar.com') .with(auth).get(); myself.link("calendar").patch(flight.link("self"));
    50. 50. calendar: more examples me.link("calendar").patch(link_to_birthday_list) me.link("calendar").patch(link_to_hotel_reservation) me.link("calendar").patch(link_to_trip_details)
    51. 51. so what?
    52. 52. so what? Any update on the flight ==> reflects here Any update on the hotel ==> reflects here Any update on the meeting ==> reflects here
    53. 53. so what? r at e! i nt eg us e, ju st o n ’t d Any update on the flight ==> reflects here Any update on the hotel ==> reflects here Any update on the meeting ==> reflects here
    54. 54. so what? that was just keeping an URI.
    55. 55. so what? that was just keeping an URI. Remove ==> Cancels the flight Remove ==> Cancels the reservation Remove ==> Emails your coworkers
    56. 56. so what? that was just keeping an URI. ro l! co nt a li ze en tr no tc do Remove ==> Cancels the flight Remove ==> Cancels the reservation Remove ==> Emails your coworkers
    57. 57. integration over the web INTEGRATION is DECENTRALIZING the CONTROL delegating to multiple agents distributed systems
    58. 58. does our ‘rest’ sites in 2010 work this way?
    59. 59. so what? that was just keeping an URI. Remove ==> Cancels the flight Remove ==> Cancels the reservation Remove ==> Emails your coworkers
    60. 60. so what? that was just keeping an URI. a t? fo rm hi ch bu tw Remove ==> Cancels the flight Remove ==> Cancels the reservation Remove ==> Emails your coworkers
    61. 61. mas qual o formato do pagamento ou calendário?
    62. 62. #json, #xml, #soap #etc?
    63. 63. qual #json, #xml #etc?
    64. 64. exercise
    65. 65. who is that guy?
    66. 66. quem é essa?
    67. 67. fácil? e ela?
    68. 68. fácil? e ela? lh a! fi in ha é m n ão
    69. 69. conteúdo sem semântica não tem valor!
    70. 70. so what?
    71. 71. so what? micro formats, media types, rdf etc
    72. 72. so what? nk s! er li hyp w ith ats fo rm ic ro m micro formats, media types, rdf etc
    73. 73. integration over the web
    74. 74. #json, @sergio_caelum
    75. 75. #?
    76. 76. de onde veio o # e o @?
    77. 77. “watching @guilhermecaelum #qconsp *10 great talk” Atenção: esse tweet é só uma sugestão!
    78. 78. controlled vocabulary
    79. 79. emergiu no twitter, por exemplo
    80. 80. inventar antes o controlled vocabulary?
    81. 81. top down? Big Design Up Front O monstro do lago SOAP, longa de 2001
    82. 82. economizando # busca um voo def voos_de(site)   base = Restfulie.at(site).get   voos = base.link("opensearch").get.fill("flight").with(:from => "GRU", :to => "JFK").get end voos = voos_de("kayak") voos << voos_de("tam") voos << voos_de("gol") voos << voos_de("cvc") voo_mais_barato(voos).link("payment").post(inferno_do_cartao)
    83. 83. banco voo = voo_mais_barato(voos) banco = Restfulie.at("meubanco").auth(eu).get auth = banco.cartoes["lisa"] .authorization(1.min, voo.preco) voo.link("payment").post(auth) mais_barato(voos).link("payment")...
    84. 84. email
    85. 85. email guilherme super viagem
    86. 86. email guilherme super viagem
    87. 87. email guilherme super viagem caelum
    88. 88. email guilherme super viagem caelum
    89. 89. email guilherme super viagem caelum kayak
    90. 90. email guilherme super viagem caelum kayak
    91. 91. email guilherme super viagem caelum kayak
    92. 92. Put your server to REST leonard richardsons model
    93. 93. Server Maturity 1 uri, 1 http verb /services.do?action=install&...
    94. 94. Server Maturity 1 uri, 1 http verb /services.do?action=install&... @Path("/services") public class Services {   @GET   public Response services(     @QueryParam("action") String action) {     ServiceFactory factory = new ServiceFactory();     Service service = factory.getServiceFor(action);     return service.execute();   } }
    95. 95. Server Maturity 1 uri, 1 http verb public class InstallService {   public Response execute() {     return Response.ok()              .type("application/xml")              .entity("<service>...</service>")              .build();   } }
    96. 96. But?
    97. 97. 1 uri, 1 http verb /services.do?action=install&... I know them all beforehand.
    98. 98. 1 uri, 1 http verb /services.do?action=install&... Any change will break all our clients!
    99. 99. a priori knowledge
    100. 100. a priori knowledge =
    101. 101. a priori knowledge = coupling++
    102. 102. Server Maturity Multiple uris, 1 http verb /install?...
    103. 103. Server Maturity Multiple uris, 1 http verb /install?... @Path("/services") public class Services {   @GET @Path("install")   public Response install() {     return new InstallService().execute();   }   @GET @Path("uninstall")   public Response uninstall() {     return new UninstallService().execute();   }
    104. 104. but...
    105. 105. GET hell GET should not imply in undesireable effects
    106. 106. POST hell GET could help us with cache!
    107. 107. Server Maturity Multiple uris, multiple verbs POST /cloud GET /cloud/1547437/software POST /cloud/1547437/software
    108. 108. rails + restfulie rubyonrails.org
    109. 109. rails + restfulie rubyonrails.org class SoftwaresController < ApplicationController      acts_as_restfulie   respond_to :xml, :json      def create     @item = Item.create(params[:item])     respond_with @item, :status => :created   end      def show     @item = Item.find(params[:id])     respond_with @item   end end
    110. 110. Vraptor vraptor.org/en
    111. 111. Vraptor vraptor.org/en @Resource public class SoftwareResource {   public void install() {     Software software = SoftwareRepository.register (software);     response.created(software);   }   public void uninstall() {     response.deleted(software);   } }
    112. 112. JAX-RS @Path("/softwares") public class SoftwareResource {   @POST @Consumes("application/xml")   public Response install(Software software) {     software = SoftwareRepository.register(software);     long id = software.getId();     URI uri = UriBuilder.fromPath("/softwares/" + id)                                        .build();     software.install();     return Response.created(uri).build();   }
    113. 113. JAX-RS   @DELETE @Path("{id}")   public Response uninstall(@PathParam("id") Long id) {     Software software = SoftwareRepository.retrieve(id);     software.uninstall();     return Response.ok().build();   }
    114. 114. Uniform Interface++ Resources++
    115. 115. Http verbs example POST creates PUT replaces PATCH updates DELETE removes GET retrieves OPTIONS tells me what i can do ...
    116. 116. Is a Restful service a cute CRUD?
    117. 117. yes
    118. 118. but there is more!
    119. 119. hypermedia enter amazon.com
    120. 120. hypermedia enter amazon.com search (GET)
    121. 121. hypermedia enter amazon.com search (GET) create a payment (POST)
    122. 122. hypermedia enter amazon.com search (GET) search (GET) create a payment (POST)
    123. 123. hypermedia enter amazon.com search (GET) search (GET) create a basket (POST) create a payment (POST)
    124. 124. hypermedia enter amazon.com follow links search (GET) search (GET) create a basket (POST) create a payment (POST)
    125. 125. hypermedia enter amazon.com follow links search (GET) search (GET) fill forms create a basket (POST) create a payment (POST)
    126. 126. Cloud API GET /user/15 retrieves an user
    127. 127. Cloud API GET /user/15 retrieves an user follow GET machines accesses its machines
    128. 128. Cloud API GET /user/15 retrieves an user follow GET machines accesses its machines follow POST self installs a new machine
    129. 129. Cloud API GET /user/15 retrieves an user follow GET machines accesses its machines follow POST self installs a new machine follow POST payment pay for it
    130. 130. retrieves an user $ curl http://localhost:9998/user/574 -i HTTP/1.1 200 OK ...
    131. 131. user <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <user>     <link rel="machines" href="/user/574/machines"/>     <name>guilherme silveira</name>     <website>www.caelum.com.br</site>    <link rel="payment" href="/payment/custom"/>     ... </user>
    132. 132. user <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <user>     <link rel="machines" href="/user/574/machines"/>     <name>guilherme silveira</name>     <website>www.caelum.com.br</site>    <link rel="payment" href="/payment/custom"/>     ... </user>
    133. 133. maschine maschine maschine $ curl http://localhost:9998/user/574/machines -i HTTP/1.1 200 OK Content-Type: application/xml
    134. 134. maschine <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <machines xmlns:ns2="http://www.w3.org/2005/Atom">   <machine>     <ns2:link rel="self" href="/user/574/machines/1"/>     <ns2:link rel="software" href="/machines1/softwares"/>     <id>1</id>     <host>www.caelum.com.br</host>     <softwares>       <software>         <id>1234</id>         <ns2:link rel="self" href="/softwares/1234"/>       </software>     </softwares>   </machine> </machines>
    135. 135. maschine <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <machines xmlns:ns2="http://www.w3.org/2005/Atom">   <machine>     <ns2:link rel="self" href="/user/574/machines/1"/>     <ns2:link rel="software" href="/machines1/softwares"/>     <id>1</id>     <host>www.caelum.com.br</host>     <softwares>       <software>         <id>1234</id>         <ns2:link rel="self" href="/softwares/1234"/>       </software>     </softwares>   </machine> </machines>
    136. 136. payment <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <user>     <link rel="machines" href="/user/574/machines"/>     <name>guilherme silveira</name>     <website>www.caelum.com.br</site>    <link rel="payment" href="/payment/custom"/>     ... </user>
    137. 137. payment <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <user>     <link rel="machines" href="/user/574/machines"/>     <name>guilherme silveira</name>     <website>www.caelum.com.br</site>    <link rel="payment" href="/payment/custom"/>     ... </user>
    138. 138. #buthow?
    139. 139. @XmlRootElement @XmlType(propOrder= {"id", "host", "softwares", "links"}) public class Machine {   private final all variables here;   @XmlElement(name="link", namespace="http://www.w3.org/2005/Atom")   public List<Link> getLinks() {     return Arrays.asList(       Link.to("/machines/" + getId(), "self"),       Link.to("/machines/" + getId() + "/softwares", "softwares")     );   }   @XmlElementWrapper(name="softwares")   @XmlElement(name="software")   public List<Software> getSoftwares() {     return softwares;   }   public void install(Software software) {     getSoftwares().add(software);   }   public void uninstall(Software software) {     getSoftwares().remove(software);   } } Machine.java
    140. 140. @XmlRootElement @XmlType(propOrder= {"id", "host", "softwares", "links"}) public class Machine {   private final all variables here;   @XmlElement(name="link", namespace="http://www.w3.org/2005/Atom")   public List<Link> getLinks() {     return Arrays.asList(       Link.to("/machines/" + getId(), "self"),       Link.to("/machines/" + getId() + "/softwares", "softwares")     );   }   @XmlElementWrapper(name="softwares")   @XmlElement(name="software")   public List<Software> getSoftwares() {     return softwares;   }   public void install(Software software) {     getSoftwares().add(software);   }   public void uninstall(Software software) {     getSoftwares().remove(software);   } } Machine.java
    141. 141. @Path("/machines") public class MachineResource { MachineResource @Path("{id}/softwares") public SoftwareResource softwares(@PathParam("id") Long id) { Machine machine = new MachineRepository().retrieve(id); if (machine != null) { SoftwareResource softwareResource = new SoftwareResource(); softwareResource.setMachine(machine); return softwareResource; } throw new WebApplicationException(404); } @POST @Consumes("application/xml") public Response create(Machine machine) { Long id = new MachineRepository().save(machine); return Response.created(UriBuilder.fromPath("/" + id).build()).build(); } @GET @Path("{id}") @Produces("application/xml") public Machine show(@PathParam("id") Long id) { return new MachineRepository().retrieve(id); } @GET @Produces("application/xml") public Machines list() { Machines machines = new Machines(); machines.setMachine(new MachineRepository().list()); return machines;
    142. 142. @Path("/machines") public class MachineResource { MachineResource @Path("{id}/softwares") public SoftwareResource softwares(@PathParam("id") Long id) { Machine machine = new MachineRepository().retrieve(id); if (machine != null) { SoftwareResource softwareResource = new SoftwareResource(); softwareResource.setMachine(machine); return softwareResource; } throw new WebApplicationException(404); } @POST @Consumes("application/xml") public Response create(Machine machine) { Long id = new MachineRepository().save(machine); return Response.created(UriBuilder.fromPath("/" + id).build()).build(); } @GET @Path("{id}") @Produces("application/xml") public Machine show(@PathParam("id") Long id) { return new MachineRepository().retrieve(id); } @GET @Produces("application/xml") public Machines list() { Machines machines = new Machines(); machines.setMachine(new MachineRepository().list()); return machines;
    143. 143. Server Model according to Leonard Richardson, 2008 one uri + one verb
    144. 144. Server Model according to Leonard Richardson, 2008 Ugly one uri + one verb
    145. 145. Server Model according to Leonard Richardson, 2008 multiple uris one uri + one verb
    146. 146. Server Model according to Leonard Richardson, 2008 Less ugly multiple uris one uri + one verb
    147. 147. Server Model according to Leonard Richardson, 2008 multiple verbs multiple uris one uri + one verb
    148. 148. Server Model according to Leonard Richardson, 2008 cute CRUD multiple verbs multiple uris one uri + one verb
    149. 149. Server Model rest according to Leonard Richardson, 2008 hypermedia multiple verbs multiple uris one uri + one verb
    150. 150. JAX-RS wishlist VRaptor and Restfulie
    151. 151. examples vraptor.org/en
    152. 152. 1. conventions? @Path("/services") public class Services {   @GET   public Response services(     @QueryParam("action") String action) {     ServiceFactory factory = new ServiceFactory();     Service service = factory.getServiceFor(action);     return service.execute();   } }
    153. 153. Convention over Configuration @Resource public class Services { private final ServiceFactory factory; public Services(ServiceFactory factory) { this.factory = factory; } public void services(String action) { factory.getServiceFor(action).execute(); } }
    154. 154. do you want to avoid copy+paste?
    155. 155. yes!
    156. 156. yes!
    157. 157. 2. TDD: hard to test @Path("/products") public class Products { coupled to the   @GET implementation   public Response create(     @QueryParam("what") String what) {     // persists     return Response.ok()              .type("application/xml")              .entity("<product>...</product>")              .build();   } }
    158. 158. TDD: mock it coupled to the interface couple-- @Resource public class Services { private final Response response; public Services(Response response) { this.response = response; } public void services(String action) { response.getServiceFor(action).execute(); } }
    159. 159. TDD: mock it coupled to the interface couple-- @Resource public class Services { private final Response response; public Services(Response response) { this.response = response; } public void services(String action) { response.getServiceFor(action).execute(); } }
    160. 160. 3. Content negotiation by hand @Path("/softwares") public class SoftwareResource {   @POST @Consumes("application/xml")   public Response install(Software software) {     software = SoftwareRepository.register(software);     long id = software.getId();     URI uri = UriBuilder.fromPath("/softwares/" + id)                                        .build(); software.install();     return Response.created(uri).build();   }
    161. 161. Let us do it for you. @Resource public class SoftwareResource { @Post @Consumes   public void install(Software software) {     software = SoftwareRepository.register(software);     response.created(software);   } }
    162. 162. Let us do it for you. @Resource public class SoftwareResource { @Post @Consumes   public void install(Software software) {     software = SoftwareRepository.register(software);     response.created(software);   } }
    163. 163. 4. URI coupling writing the URI once ...   @GET @Path("/softwares/{id}")   public Response install(@QueryParam("id") Software software) { // ...   }
    164. 164. 4. URI coupling writing the URI again several times @Path("/softwares") public class SoftwareResource {   @POST @Consumes("application/xml")   public Response install(Software software) {     software = SoftwareRepository.register(software);     long id = software.getId();     URI uri = UriBuilder.fromPath("/softwares/" + id)                                        .build(); software.install();     return Response.created(uri).build();   }
    165. 165. 4. URI coupling code @Path("/softwares") public class SoftwareResource {   @POST @Consumes("application/xml")   public Response install(Software software) {     software = SoftwareRepository.register(software);     long id = software.getId();     URI uri = UriBuilder.fromPath("/softwares/" + id)                                        .build(); software.install();     return Response.created(uri).build();   }
    166. 166. ZERO uri replication @Resource public class SoftwareResource { @Post @Consumes   public void install(Software software) {     // ...     response.use(SoftwareResource.class).show(software);   } }
    167. 167. ZERO uri replication @Resource public class SoftwareResource { @Post @Consumes   public void install(Software software) {     // ...     response.use(SoftwareResource.class).show(software);   } }
    168. 168. 5. Parameter list @Path("/machines") public class MachineResource { @Path("{id}/softwares") public SoftwareResource softwares(@PathParam("id") Long id) { Machine machine = new MachineRepository().retrieve(id); if (machine == null) { throw new WebApplicationException(404); } // ... } }
    169. 169. Yes, we can do it. @Resource public class MachineResource { @Post ("{m.id}/softwares") public SoftwareResource softwares(Machine m) { Machine machine = new MachineRepository().retrieve(m // ... } } parameter converter chain of responsability
    170. 170. Yes, we can do it. @Resource public class MachineResource { @Post ("{m.id}/softwares") public SoftwareResource softwares(Machine m) { Machine machine = new MachineRepository().retrieve(m // ... } } parameter converter chain of responsability
    171. 171. example restfulie.caelumobjects.com
    172. 172. Response response = client.at ("http://localhost:9998/user/574").get(); 6. Client internal DSLs
    173. 173. Response response = client.at ("http://localhost:9998/user/574").get(); User user = response.getResource(); System.out.println("user: " + user.getName()); 6. Client internal DSLs
    174. 174. User user = response.getResource(); System.out.println("user: " + user.getName()); Link link = resource(user).getLink("machine"); response = link.follow().post(new Machine());
    175. 175. Link link = resource(user).getLink("machine"); response = link.follow().post(new Machine()); double amount = resource(user).refresh(). getAmountDue();
    176. 176. double amount = resource(user).refresh(). getAmountDue(); link = resource(user).getLink("payment"); Payment payment = new Payment(amount); response = link.follow().post(payment);
    177. 177. link = resource(user).getLink("payment"); Payment payment = new Payment(amount); response = link.follow().post(payment); System.out.println("payment completed");
    178. 178. link = resource(user).getLink("payment"); Payment payment = new Payment(amount); response = link.follow().post(payment); System.out.println("payment completed"); i was looking for a DSL and i did not know it!
    179. 179. bottom up design by committe mime type? microformato controlled vocabulary
    180. 180. hypermídia viabilizando a integração através da web
    181. 181. obrigado
    182. 182. code samples Lucas Cavalcanti (java server) @lucascs Anderson Leite (ruby) @anderson_leite
    183. 183. Further reading
    184. 184. Further reading Roy Fielding dissertation
    185. 185. Further reading Roy Fielding dissertation Rest in Practice, Jim Webber and others
    186. 186. Further reading Roy Fielding dissertation Rest in Practice, Jim Webber and others Restful Webservices Cookbook, Subbu Allamaraju
    187. 187. Further reading Roy Fielding dissertation Rest in Practice, Jim Webber and others Restful Webservices Cookbook, Subbu Allamaraju Restful Web Services, Richardson and Ruby
    188. 188. Further reading Roy Fielding dissertation Rest in Practice, Jim Webber and others Restful Webservices Cookbook, Subbu Allamaraju Restful Web Services, Richardson and Ruby JAX-RS specification
    189. 189. Further reading Roy Fielding dissertation Rest in Practice, Jim Webber and others Restful Webservices Cookbook, Subbu Allamaraju Restful Web Services, Richardson and Ruby JAX-RS specification Infoq articles on REST
    190. 190. Further reading Roy Fielding dissertation Rest in Practice, Jim Webber and others Restful Webservices Cookbook, Subbu Allamaraju Restful Web Services, Richardson and Ruby JAX-RS specification Infoq articles on REST Restfulie guide
    191. 191. Interviews and Presentations
    192. 192. Interviews and Presentations Stefan Tilkov interview on InfoQ
    193. 193. Interviews and Presentations Stefan Tilkov interview on InfoQ http://bit.ly/9RUXKL
    194. 194. Interviews and Presentations Stefan Tilkov interview on InfoQ http://bit.ly/9RUXKL Leonard Richardson’s presentation at QCon
    195. 195. Interviews and Presentations Stefan Tilkov interview on InfoQ http://bit.ly/9RUXKL Leonard Richardson’s presentation at QCon http://bit.ly/dj2W66
    196. 196. Interviews and Presentations Stefan Tilkov interview on InfoQ http://bit.ly/9RUXKL Leonard Richardson’s presentation at QCon http://bit.ly/dj2W66 Martin Fowler on REST
    197. 197. Interviews and Presentations Stefan Tilkov interview on InfoQ http://bit.ly/9RUXKL Leonard Richardson’s presentation at QCon http://bit.ly/dj2W66 Martin Fowler on REST http://bit.ly/bx61ci
    198. 198. Interviews and Presentations
    199. 199. Interviews and Presentations Ian Robinson and Jim Webber interview
    200. 200. Interviews and Presentations Ian Robinson and Jim Webber interview http://bit.ly/aEuzj3
    201. 201. Interviews and Presentations Ian Robinson and Jim Webber interview http://bit.ly/aEuzj3 Jan Algermissen classification
    202. 202. Interviews and Presentations Ian Robinson and Jim Webber interview http://bit.ly/aEuzj3 Jan Algermissen classification http://bit.ly/cycFBF
    203. 203. Interviews and Presentations Ian Robinson and Jim Webber interview http://bit.ly/aEuzj3 Jan Algermissen classification http://bit.ly/cycFBF Guilherme Silveira on REST clients
    204. 204. Interviews and Presentations Ian Robinson and Jim Webber interview http://bit.ly/aEuzj3 Jan Algermissen classification http://bit.ly/cycFBF Guilherme Silveira on REST clients http://bit.ly/aHCglv
    205. 205. code samples
    206. 206. code samples JAX-RS
    207. 207. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311
    208. 208. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311 Rails
    209. 209. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311 Rails http://rubyonrails.org
    210. 210. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311 Rails http://rubyonrails.org Restfulie
    211. 211. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311 Rails http://rubyonrails.org Restfulie http://restfulie.caelumobjects.com
    212. 212. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311 Rails http://rubyonrails.org Restfulie http://restfulie.caelumobjects.com VRaptor
    213. 213. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311 Rails http://rubyonrails.org Restfulie http://restfulie.caelumobjects.com VRaptor http://vraptor.org/en

    ×