Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Put your client and server to rest - Javaone

1,653 views

Published on

This is the talk Guilherme Silveira and Jan Algermissen presented during Javaone 2010. More info on blog.caelumobjects.com and nordsc.com/blog

Published in: Technology
  • Be the first to comment

Put your client and server to rest - Javaone

  1. 1. Put your client and server to REST with JAX-RS Guilherme Silveira and Jan Algermissen
  2. 2. Guilherme Silveira Technical leader, Instructor @guilhermecaelum guilherme.silveira@caelum.com.br
  3. 3. Guilherme Silveira Technical leader, Instructor @guilhermecaelum guilherme.silveira@caelum.com.br
  4. 4. 2002 guj.com.br 2003 vraptor 2004 caelumobjects.com xp, xstream Guilherme Silveira 2006 scrum Technical leader, Instructor @guilhermecaelum 2009 restfulie, lean guilherme.silveira@caelum.com.br
  5. 5. Guilherme Silveira Technical leader, Instructor @guilhermecaelum guilherme.silveira@caelum.com.br
  6. 6. Guilherme Silveira Technical leader, Instructor @guilhermecaelum guilherme.silveira@caelum.com.br
  7. 7. Training and Consulting Guilherme Silveira Technical leader, Instructor @guilhermecaelum guilherme.silveira@caelum.com.br
  8. 8. a ge o Im y -N rr So 2002 Discovered REST 2005 1st pure REST project 2008 REST gaining momentum Jan Algermissen algermissen@acm.org 2009 NORD SC @algermissen
  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 guilherme
  31. 31. service locator when integrating: coupling++ unrest pay unresttrips 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. 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);
  42. 42. 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);
  43. 43. 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);
  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. calendar: integrating my systems myself = Client.at('http://users.calendar.com') .with(auth).get(); myself.link("calendar").patch(flight.link("self"));
  46. 46. calendar: integrating my systems myself = Client.at('http://users.calendar.com') .with(auth).get(); myself.link("calendar").patch(flight.link("self"));
  47. 47. 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)
  48. 48. so what?
  49. 49. so what? Any update on the flight ==> reflects here Any update on the hotel ==> reflects here Any update on the meeting ==> reflects here
  50. 50. 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
  51. 51. so what? that was just keeping an URI.
  52. 52. so what? that was just keeping an URI. Remove ==> Cancels the flight Remove ==> Cancels the reservation Remove ==> Emails your coworkers
  53. 53. 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
  54. 54. integration over the web INTEGRATION is DECENTRALIZING the CONTROL delegating to multiple agents distributed systems
  55. 55. does our ‘rest’ sites in 2010 work this way?
  56. 56. so what? that was just keeping an URI. Remove ==> Cancels the flight Remove ==> Cancels the reservation Remove ==> Emails your coworkers
  57. 57. 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
  58. 58. exercise
  59. 59. who is that guy?
  60. 60. who is that girl?
  61. 61. too easy, right? who is that little girl?
  62. 62. too easy, right? who is that little girl? ht er da ug y notm is s he
  63. 63. content without semantic has no value!
  64. 64. so what?
  65. 65. so what? micro formats, media types, rdf etc
  66. 66. so what? nk s! er li hyp w ith ats fo rm ic ro m micro formats, media types, rdf etc
  67. 67. integration over the web
  68. 68. Put your server to REST leonard richardsons model
  69. 69. Server Maturity 1 uri, 1 http verb /services.do?action=install&...
  70. 70. 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();   } }
  71. 71. Server Maturity 1 uri, 1 http verb public class InstallService {   public Response execute() {     return Response.ok()              .type("application/xml")              .entity("<service>...</service>")              .build();   } }
  72. 72. But?
  73. 73. 1 uri, 1 http verb /services.do?action=install&... I know them all beforehand.
  74. 74. 1 uri, 1 http verb /services.do?action=install&... Any change will break all our clients!
  75. 75. a priori knowledge
  76. 76. a priori knowledge =
  77. 77. a priori knowledge = coupling++
  78. 78. Server Maturity Multiple uris, 1 http verb /install?...
  79. 79. 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();   }
  80. 80. but...
  81. 81. GET hell GET should not imply in undesireable effects
  82. 82. POST hell GET could help us with cache!
  83. 83. Server Maturity Multiple uris, multiple verbs POST /cloud GET /cloud/1547437/software POST /cloud/1547437/software
  84. 84. rails + restfulie rubyonrails.org
  85. 85. 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
  86. 86. Vraptor vraptor.org/en
  87. 87. 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);   } }
  88. 88. 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();   }
  89. 89. JAX-RS   @DELETE @Path("{id}")   public Response uninstall(@PathParam("id") Long id) {     Software software = SoftwareRepository.retrieve(id);     software.uninstall();     return Response.ok().build();   }
  90. 90. Uniform Interface++ Resources++
  91. 91. Http verbs example POST creates PUT replaces PATCH updates DELETE removes GET retrieves OPTIONS tells me what i can do ...
  92. 92. Is a Restful service a cute CRUD?
  93. 93. yes
  94. 94. but there is more!
  95. 95. hypermedia enter amazon.com
  96. 96. hypermedia enter amazon.com search (GET)
  97. 97. hypermedia enter amazon.com search (GET) create a payment (POST)
  98. 98. hypermedia enter amazon.com search (GET) search (GET) create a payment (POST)
  99. 99. hypermedia enter amazon.com search (GET) search (GET) create a basket (POST) create a payment (POST)
  100. 100. hypermedia enter amazon.com follow links search (GET) search (GET) create a basket (POST) create a payment (POST)
  101. 101. hypermedia enter amazon.com follow links search (GET) search (GET) fill forms create a basket (POST) create a payment (POST)
  102. 102. Cloud API GET /user/15 retrieves an user
  103. 103. Cloud API GET /user/15 retrieves an user follow GET machines accesses its machines
  104. 104. Cloud API GET /user/15 retrieves an user follow GET machines accesses its machines follow POST self installs a new machine
  105. 105. 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
  106. 106. retrieves an user $ curl http://localhost:9998/user/574 -i HTTP/1.1 200 OK ...
  107. 107. 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>
  108. 108. 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>
  109. 109. maschine maschine maschine $ curl http://localhost:9998/user/574/machines -i HTTP/1.1 200 OK Content-Type: application/xml
  110. 110. 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>
  111. 111. 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>
  112. 112. 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>
  113. 113. 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>
  114. 114. #buthow?
  115. 115. @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
  116. 116. @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
  117. 117. @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;
  118. 118. @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;
  119. 119. Server Model according to Leonard Richardson, 2008 one uri + one verb
  120. 120. Server Model according to Leonard Richardson, 2008 Ugly one uri + one verb
  121. 121. Server Model according to Leonard Richardson, 2008 multiple uris one uri + one verb
  122. 122. Server Model according to Leonard Richardson, 2008 Less ugly multiple uris one uri + one verb
  123. 123. Server Model according to Leonard Richardson, 2008 multiple verbs multiple uris one uri + one verb
  124. 124. Server Model according to Leonard Richardson, 2008 cute CRUD multiple verbs multiple uris one uri + one verb
  125. 125. Server Model rest according to Leonard Richardson, 2008 hypermedia multiple verbs multiple uris one uri + one verb
  126. 126. JAX-RS wishlist VRaptor and Restfulie
  127. 127. examples vraptor.org/en
  128. 128. 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();   } }
  129. 129. 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(); } }
  130. 130. do you want to avoid copy+paste?
  131. 131. yes!
  132. 132. yes!
  133. 133. 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();   } }
  134. 134. 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(); } }
  135. 135. 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(); } }
  136. 136. 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();   }
  137. 137. Let us do it for you. @Resource public class SoftwareResource { @Post @Consumes   public void install(Software software) {     software = SoftwareRepository.register(software);     response.created(software);   } }
  138. 138. Let us do it for you. @Resource public class SoftwareResource { @Post @Consumes   public void install(Software software) {     software = SoftwareRepository.register(software);     response.created(software);   } }
  139. 139. 4. URI coupling writing the URI once ...   @GET @Path("/softwares/{id}")   public Response install(@QueryParam("id") Software software) { // ...   }
  140. 140. 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();   }
  141. 141. 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();   }
  142. 142. ZERO uri replication @Resource public class SoftwareResource { @Post @Consumes   public void install(Software software) {     // ...     response.use(SoftwareResource.class).show(software);   } }
  143. 143. ZERO uri replication @Resource public class SoftwareResource { @Post @Consumes   public void install(Software software) {     // ...     response.use(SoftwareResource.class).show(software);   } }
  144. 144. 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); } // ... } }
  145. 145. 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
  146. 146. 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
  147. 147. example restfulie.caelumobjects.com
  148. 148. Response response = client.at ("http://localhost:9998/user/574").get(); 6. Client internal DSLs
  149. 149. Response response = client.at ("http://localhost:9998/user/574").get(); User user = response.getResource(); System.out.println("user: " + user.getName()); 6. Client internal DSLs
  150. 150. User user = response.getResource(); System.out.println("user: " + user.getName()); Link link = resource(user).getLink("machine"); response = link.follow().post(new Machine());
  151. 151. Link link = resource(user).getLink("machine"); response = link.follow().post(new Machine()); double amount = resource(user).refresh(). getAmountDue();
  152. 152. double amount = resource(user).refresh(). getAmountDue(); link = resource(user).getLink("payment"); Payment payment = new Payment(amount); response = link.follow().post(payment);
  153. 153. link = resource(user).getLink("payment"); Payment payment = new Payment(amount); response = link.follow().post(payment); System.out.println("payment completed");
  154. 154. 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!
  155. 155. Putting JAX-RS Clients to REST
  156. 156. “Jersey View Client” • Developed early 2010 • w/ Paul Sandoz (@paulsandoz) • To-be Jersey RESTful client API • Feedback welcome!
  157. 157. Goals • Encourage RESTful client side programming • Natural coding model • Resemble JAX-RS annotation style
  158. 158. LEARN FROM WEB BROWSER
  159. 159. HTTP Request
  160. 160. Web Browser Tasks
  161. 161. Web Browser Tasks • GET resource after user enters URL
  162. 162. Web Browser Tasks • GET resource after user enters URL • Build up Web page
  163. 163. Web Browser Tasks • GET resource after user enters URL • Build up Web page • Show informatin (title, content)
  164. 164. Web Browser Tasks • GET resource after user enters URL • Build up Web page • Show informatin (title, content) • Expose links and forms
  165. 165. Web Browser Tasks • GET resource after user enters URL • Build up Web page • Show informatin (title, content) • Expose links and forms • Act upon link activation or form submission
  166. 166. A Web Page
  167. 167. A Web Page • Has a location
  168. 168. A Web Page • Has a location • Build from response(s)
  169. 169. A Web Page • Has a location • Build from response(s) • Holds application state
  170. 170. A Web Page • Has a location • Build from response(s) • Holds application state • Exposes application state
  171. 171. A Web Page • Has a location • Build from response(s) • Holds application state • Exposes application state • Exposes links and forms
  172. 172. A Web Page • Has a location • Build from response(s) • Holds application state • Exposes application state • Exposes links and forms • Assumptions
  173. 173. GENERALIZE FROM HERE
  174. 174. User Agent
  175. 175. User Agent • Use entry URI to start application
  176. 176. User Agent • Use entry URI to start application • Build up application state from response(s)
  177. 177. User Agent • Use entry URI to start application • Build up application state from response(s) • Make state available
  178. 178. User Agent • Use entry URI to start application • Build up application state from response(s) • Make state available • Make hypermedia controls activatable
  179. 179. User Agent • Use entry URI to start application • Build up application state from response(s) • Make state available • Make hypermedia controls activatable • Construct request upon control activation
  180. 180. A View
  181. 181. A View • Bound to resource
  182. 182. A View • Bound to resource • Build from response(s)
  183. 183. A View • Bound to resource • Build from response(s) • Holds application state
  184. 184. A View • Bound to resource • Build from response(s) • Holds application state • Exposes application state
  185. 185. A View • Bound to resource • Build from response(s) • Holds application state • Exposes application state • Enables activation of controls
  186. 186. A View • Bound to resource • Build from response(s) • Holds application state • Exposes application state • Enables activation of controls • Bundles Assumptions
  187. 187. View: Combination of state and assumptions, bound to a URI
  188. 188. So where is the difference?
  189. 189. Browser: A single kind of view!
  190. 190. That’s ok in Browser-land
  191. 191. Can’t do machine REST with a single kind of view
  192. 192. Not just one kind of application state
  193. 193. Atom Pub • Service view • Feed view • Entry View
  194. 194. Our Example • User account view • Machine View • Invoice View
  195. 195. Client Side API?
  196. 196. Use classes to represent kinds of views
  197. 197. A view class for a Web Page View WebPageView pageView = client.view( “https://twitter.com/signup”,WebPageView.class); Form form = page.getFormsByIndex(0); form.name = “John”; form.submit();
  198. 198. View Classes
  199. 199. View Classes • Relate instance to resource
  200. 200. View Classes • Relate instance to resource • Handle response
  201. 201. View Classes • Relate instance to resource • Handle response • Build up application state
  202. 202. View Classes • Relate instance to resource • Handle response • Build up application state • Expose application state
  203. 203. View Classes • Relate instance to resource • Handle response • Build up application state • Expose application state • Expose hypermedia controls
  204. 204. View Classes • Relate instance to resource • Handle response • Build up application state • Expose application state • Expose hypermedia controls • Perform requests upon control activation
  205. 205. View Classes • Relate instance to resource • Handle response • Build up application state • Expose application state • Expose hypermedia controls • Perform requests upon control activation • Bundle assumptions
  206. 206. A class for account views URI ACCOUNT_URI = new URI( “http://example.org/saas/user/john/account”); Client client = new Client(); // Create view instance bound to a URI AccountView av = client.view(ACCOUNT_URI, AccountView.class); // Access application state held by view // Invoke controls exposed by view
  207. 207. A Media Type GET /saas/user/john/account 200 Ok Content-Type: application/saas <account> <machines href=”./machines” accept=”application/saas;type=machine”/> <payments href=”./payments” accept=”application/saas;type=payment”/> <userData> <name>John Doe</name> ... </userData> </account>
  208. 208. public class AccountView { // hold state private ViewResource machineCollection; private ViewResource paymentProcessor; private String userName; @GET @Consumes(“application/saas;type=account”) public void build(Account account) { // build state from response } public String getUserName() { return userName; } // <machines href=””/> control exposed public CreatedMachineView addMachine(Machine machine) { return machineCollection.post(machine, CreatedMachineView.class) } // <payments href=””/> control exposed public void submitPayment(Payment payment) { paymentProcessor.post(payment); } }
  209. 209. public class AccountView { // hold state private ViewResource machineCollection; private ViewResource paymentProcessor; private String userName; @GET @Consumes(“application/saas;type=account”) public void build(Account account) { // build state from response } public String getUserName() { return userName; } // <machines href=””/> control exposed public CreatedMachineView addMachine(Machine machine) { return machineCollection.post(machine, CreatedMachineView.class) } // <payments href=””/> control exposed public void submitPayment(Payment payment) { paymentProcessor.post(payment); } }
  210. 210. public class AccountView { // hold state private ViewResource machineCollection; private ViewResource paymentProcessor; private String userName; @GET @Consumes(“application/saas;type=account”) public void build(Account account) { // build state from response } public String getUserName() { return userName; } // <machines href=””/> control exposed public CreatedMachineView addMachine(Machine machine) { return machineCollection.post(machine, CreatedMachineView.class) } // <payments href=””/> control exposed public void submitPayment(Payment payment) { paymentProcessor.post(payment); } }
  211. 211. public class AccountView { // hold state private ViewResource machineCollection; private ViewResource paymentProcessor; private String userName; @GET @Consumes(“application/saas;type=account”) public void build(Account account) { // build state from response } public String getUserName() { return userName; } // <machines href=””/> control exposed public CreatedMachineView addMachine(Machine machine) { return machineCollection.post(machine, CreatedMachineView.class) } // <payments href=””/> control exposed public void submitPayment(Payment payment) { paymentProcessor.post(payment); } }
  212. 212. public class AccountView { // hold state private ViewResource machineCollection; private ViewResource paymentProcessor; private String userName; @GET @Consumes(“application/saas;type=account”) public void build(Account account) { // build state from response } public String getUserName() { return userName; } // <machines href=””/> control exposed public CreatedMachineView addMachine(Machine machine) { return machineCollection.post(machine, CreatedMachineView.class) } // <payments href=””/> control exposed public void submitPayment(Payment payment) { paymentProcessor.post(payment); } }
  213. 213. public class AccountView { // hold state private ViewResource machineCollection; private ViewResource paymentProcessor; private String userName; @GET @Consumes(“application/saas;type=account”) public void build(Account account) { // build state from response } public String getUserName() { return userName; } // <machines href=””/> control exposed public CreatedMachineView addMachine(Machine machine) { return machineCollection.post(machine, CreatedMachineView.class) } // <payments href=””/> control exposed public void submitPayment(Payment payment) { paymentProcessor.post(payment); } }
  214. 214. Choosing a certain view class to handle a response manifests an assumption!
  215. 215. Using View Classes AccountView accountView = client.view( ACCOUNT_URI,AccountView.class); LOG.info(“Working on account for “ + accountView.getUserName()); Machine machine = newMachine(); CreatedMachineView cmv = accountView.addMachine(machine); LOG.info("New machine is at: " + cmv.getLocation()); InvoiceView invoiceView = cmv.getInvoiceView(); Payment payment = new Payment(invoiceView.getAmount(), myCreditCardData); accountView.makePayment(payment);
  216. 216. Using View Classes AccountView accountView = client.view( ACCOUNT_URI,AccountView.class); LOG.info(“Working on account for “ + accountView.getUserName()); Machine machine = newMachine(); CreatedMachineView cmv = accountView.addMachine(machine); LOG.info("New machine is at: " + cmv.getLocation()); InvoiceView invoiceView = cmv.getInvoiceView(); Payment payment = new Payment(invoiceView.getAmount(), myCreditCardData); accountView.makePayment(payment);
  217. 217. Using View Classes AccountView accountView = client.view( ACCOUNT_URI,AccountView.class); LOG.info(“Working on account for “ + accountView.getUserName()); Machine machine = newMachine(); CreatedMachineView cmv = accountView.addMachine(machine); LOG.info("New machine is at: " + cmv.getLocation()); InvoiceView invoiceView = cmv.getInvoiceView(); Payment payment = new Payment(invoiceView.getAmount(), myCreditCardData); accountView.makePayment(payment);
  218. 218. Using View Classes AccountView accountView = client.view( ACCOUNT_URI,AccountView.class); LOG.info(“Working on account for “ + accountView.getUserName()); Machine machine = newMachine(); CreatedMachineView cmv = accountView.addMachine(machine); LOG.info("New machine is at: " + cmv.getLocation()); InvoiceView invoiceView = cmv.getInvoiceView(); Payment payment = new Payment(invoiceView.getAmount(), myCreditCardData); accountView.makePayment(payment);
  219. 219. Using View Classes AccountView accountView = client.view( ACCOUNT_URI,AccountView.class); LOG.info(“Working on account for “ + accountView.getUserName()); Machine machine = newMachine(); CreatedMachineView cmv = accountView.addMachine(machine); LOG.info("New machine is at: " + cmv.getLocation()); InvoiceView invoiceView = cmv.getInvoiceView(); Payment payment = new Payment(invoiceView.getAmount(), myCreditCardData); accountView.makePayment(payment);
  220. 220. Using View Classes AccountView accountView = client.view( ACCOUNT_URI,AccountView.class); LOG.info(“Working on account for “ + accountView.getUserName()); Machine machine = newMachine(); CreatedMachineView cmv = accountView.addMachine(machine); LOG.info("New machine is at: " + cmv.getLocation()); InvoiceView invoiceView = cmv.getInvoiceView(); Payment payment = new Payment(invoiceView.getAmount(), myCreditCardData); accountView.makePayment(payment);
  221. 221. Using View Classes AccountView accountView = client.view( ACCOUNT_URI,AccountView.class); LOG.info(“Working on account for “ + accountView.getUserName()); Machine machine = newMachine(); CreatedMachineView cmv = accountView.addMachine(machine); LOG.info("New machine is at: " + cmv.getLocation()); InvoiceView invoiceView = cmv.getInvoiceView(); Payment payment = new Payment(invoiceView.getAmount(), myCreditCardData); accountView.makePayment(payment);
  222. 222. Using View Classes AccountView accountView = client.view( ACCOUNT_URI,AccountView.class); LOG.info(“Working on account for “ + accountView.getUserName()); Machine machine = newMachine(); CreatedMachineView cmv = accountView.addMachine(machine); LOG.info("New machine is at: " + cmv.getLocation()); InvoiceView invoiceView = cmv.getInvoiceView(); Payment payment = new Payment(invoiceView.getAmount(), myCreditCardData); accountView.makePayment(payment);
  223. 223. Things to Note
  224. 224. Things to Note • Think of view like of browser window
  225. 225. Things to Note • Think of view like of browser window • Can keep them around, go back, use any time
  226. 226. Things to Note • Think of view like of browser window • Can keep them around, go back, use any time • Handle for application state
  227. 227. Things to Note • Think of view like of browser window • Can keep them around, go back, use any time • Handle for application state • View class is single point of code
  228. 228. Things to Note • Think of view like of browser window • Can keep them around, go back, use any time • Handle for application state • View class is single point of code • Bundles code and expectations
  229. 229. Things to Note • Think of view like of browser window • Can keep them around, go back, use any time • Handle for application state • View class is single point of code • Bundles code and expectations • Views classes used define application
  230. 230. thank you
  231. 231. Presentation Online http://slidesha.re/put_them_to_rest
  232. 232. After-Talk Discussion Come and discuss RESTfulie and Jersey View Client.
  233. 233. The golden rule
  234. 234. In a world with serious issues
  235. 235. In a world with serious issues
  236. 236. In a world with serious issues
  237. 237. In a world with serious issues
  238. 238. What is the magical solution?
  239. 239. sunday in the park “Ah, yes, a similar thing happens all the time when flaying frisbee in the park with my dog. When I throw the frisbee and the dog tries to catch it in his teeth, everyone seems to be happy.”
  240. 240. sunday in the park “However, when the dog tries to throw the frisbee and I try to catch it in my teeth, it just doesn't seem to work well for either of us.” Roy Fielding, REST creator
  241. 241. If JMS does not fit your problem, do not try to fit your solution within JMS.
  242. 242. If SOA does not fit your problem, do not try to fit your solution within SOA.
  243. 243. If REST does not fit your problem, do not try to fit your solution within REST.
  244. 244. finally
  245. 245. The golden rule If * does not fit your problem, do not try to fit your solution within *.
  246. 246. code samples Lucas Cavalcanti (java server) @lucascs Anderson Leite (ruby) @anderson_leite
  247. 247. Further reading
  248. 248. Further reading Roy Fielding dissertation
  249. 249. Further reading Roy Fielding dissertation Rest in Practice, Jim Webber and others
  250. 250. Further reading Roy Fielding dissertation Rest in Practice, Jim Webber and others Restful Webservices Cookbook, Subbu Allamaraju
  251. 251. Further reading Roy Fielding dissertation Rest in Practice, Jim Webber and others Restful Webservices Cookbook, Subbu Allamaraju Restful Web Services, Richardson and Ruby
  252. 252. 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
  253. 253. 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
  254. 254. 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
  255. 255. Jersey related
  256. 256. Jersey related Jersey related posts
  257. 257. Jersey related Jersey related posts http://www.nordsc.com/blog/?cat=28
  258. 258. Jersey related Jersey related posts http://www.nordsc.com/blog/?cat=28 Repository
  259. 259. Jersey related Jersey related posts http://www.nordsc.com/blog/?cat=28 Repository https://jersey.dev.java.net/
  260. 260. Jersey related Jersey related posts http://www.nordsc.com/blog/?cat=28 Repository https://jersey.dev.java.net/ Presentation
  261. 261. Jersey related Jersey related posts http://www.nordsc.com/blog/?cat=28 Repository https://jersey.dev.java.net/ Presentation http://www.nordsc.com/presentations/j1/
  262. 262. Interviews and Presentations
  263. 263. Interviews and Presentations Stefan Tilkov interview on InfoQ
  264. 264. Interviews and Presentations Stefan Tilkov interview on InfoQ http://bit.ly/9RUXKL
  265. 265. Interviews and Presentations Stefan Tilkov interview on InfoQ http://bit.ly/9RUXKL Leonard Richardson’s presentation at QCon
  266. 266. Interviews and Presentations Stefan Tilkov interview on InfoQ http://bit.ly/9RUXKL Leonard Richardson’s presentation at QCon http://bit.ly/dj2W66
  267. 267. 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
  268. 268. 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
  269. 269. Interviews and Presentations
  270. 270. Interviews and Presentations Ian Robinson and Jim Webber interview
  271. 271. Interviews and Presentations Ian Robinson and Jim Webber interview http://bit.ly/aEuzj3
  272. 272. Interviews and Presentations Ian Robinson and Jim Webber interview http://bit.ly/aEuzj3 Jan Algermissen classification
  273. 273. Interviews and Presentations Ian Robinson and Jim Webber interview http://bit.ly/aEuzj3 Jan Algermissen classification http://bit.ly/cycFBF
  274. 274. 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
  275. 275. 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
  276. 276. code samples
  277. 277. code samples JAX-RS
  278. 278. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311
  279. 279. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311 Rails
  280. 280. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311 Rails http://rubyonrails.org
  281. 281. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311 Rails http://rubyonrails.org Restfulie
  282. 282. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311 Rails http://rubyonrails.org Restfulie http://restfulie.caelumobjects.com
  283. 283. code samples JAX-RS http://jcp.org/en/jsr/detail?id=311 Rails http://rubyonrails.org Restfulie http://restfulie.caelumobjects.com VRaptor
  284. 284. 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

×