Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Spring MVC to iOS and the REST

19.500 Aufrufe

Veröffentlicht am

Presented at DevNexus 2013

Veröffentlicht in: Technologie

Spring MVC to iOS and the REST

  1. Spring MVC to iOS and the RESTRoy Clarkson, Senior Engineer, VMwareTwitter/GitHub: @royclarksonJosh Long, Spring Developer AdvocateTwitter: @starbuxman GitHub: @joshlong© 2013 SpringSource, by VMware
  2. About Roy Clarkson• Georgia Tech Alum• SpringSource Engineer at VMware• Lead on Spring for Android and Spring Mobile• Twitter/GitHub: @royclarkson• rclarkson@vmware.com• http://www.slideshare.net/royclarkson2
  3. About Josh Long (⻰龙之春)Spring Developer Advocatetwitter: @starbuxmanweibo: @springsourcejosh.long@springsource.com 3
  4. About Josh LongSpring Developer Advocatetwitter: @starbuxmanjosh.long@springsource.comContributor To:•Spring Integration•Spring Batch•Spring Hadoop•Activiti Workflow Engine4
  5. Agenda• REST• Spring MVC• iOS• Demos5
  6. The term Representational State Transfer was introduced and defined in 2000 by Roy Fielding in his doctoral dissertation.6
  7. What is REST?• REpresentational State Transfer• An architectural style for designing distributed systems• Not a standard, but rather a set of constraints – Client/Server, Stateless, Uniform Interface, etc.• Not tied to HTTP, but associated most commonly with it7
  8. The Principles of REST• Resources – Expose directory structure-like URIs – URI’s should be easily understood• Representations – Transfer XML, JavaScript Object Notation (JSON), or both – Use XML or JSON to represent data objects or attributes• Messages – Use HTTP methods explicitly (i.e. POST, GET, PUT, DELETE) – CRUD operations can be mapped to these existing methods• Stateless – State dependencies limit or restrict scalability8
  9. What is HATEOAS?• Hypermedia As The Engine Of Application State• The client doesn’t have a built in knowledge of how to navigate and manipulate the model• Instead server provides that information dynamically to the user• Implemented by using media types and link relations9
  10. HTTP GET• Retrieve information – Must be safe and idempotent• Can have side effects, but since the user doesn’t expect them, they shouldn’t be critical to the operation of the system• GET can be conditional or partial – If-Modified-Since – Range GET /pizzas/110
  11. HTTP DELETE• Request that a resource be removed• The resource doesn’t have to be removed immediately – Removal may be a long running task DELETE /pizzas/111
  12. HTTP PUT• Requests that the entity passed be stored at the URI• Can be used to create a new entity or modify an existing one – Creation of new entities is uncommon as it allows the client to select the id of the new entity PUT /toppings/1 { “name” : “Cheese” }12
  13. HTTP POST• Requests that the resource at a URI do something with the enclosed entity• The major difference between POST and PUT are what resource the request URI identifies• For example, use PUT to create and POST to modify POST /toppings/1 { “name” : “Cheddar Cheese” }13
  14. HTTP Status Codes• Status codes are an indicator the result of the server’s attempt to satisfy the request• Broadly divided in categories – 1XX: Informational – 2XX: Success – 3XX: Redirection – 4XX: Client Error – 5XX: Server Error14
  15. Success Status Codes• 200 OK – Everything worked• 201 Created – The server has successfully created a new resource – Newly created resource’s location returned in the Location header• 202 Accepted – The server has accepted the request, but it is not yet complete – A location to determine the request’s current status can be returned in the Location header15
  16. Client Error Status Codes• 400 Bad Request – Malformed Syntax – Should not be repeated without modification• 401 Unauthorized – Authentication is required – Includes a WWW-Authenticate header• 403 Forbidden – Server has understood, but refuses to honor the request – Should not be repeated without modification16
  17. Client Error Status Codes• 404 Not Found – The server cannot find a resource matching a URI• 406 Not Acceptable – The server can only return response entities that do not match the client’s Accept header• 409 Conflict – The resource is in a state that is in conflict with the request – Client should attempt to rectify the conflict and then resubmit the request17
  18. Media Types• Accept & Content-Type HTTP Headers• Client or server describes the content18
  19. Spring Web MVC DispatcherServlet20
  20. Annotations of Spring MVC• @Controller• @RequestMapping• @RequestParam• @PathVariable• @ResponseBody• @RequestBody• @ResponseStatus21
  21. @Controller@Controllerpublic class PizzaController {...}22
  22. @RequestMapping@Controller@RequestMapping("/pizzas")public class PizzaController { // POST /pizzas/bake @RequestMapping(value = "/bake", method = POST) public void bake() { ... }}23
  23. @RequestParam@Controller@RequestMapping("/pizzas")public class PizzaController { // POST /pizzas/bake?temp=400 @RequestMapping(value = "/bake", method = POST) public void bake(@RequestParam Integer temp) { ... }}24
  24. @PathVariable@Controller@RequestMapping("/pizzas")public class PizzaController { // POST /pizzas/bake/400 @RequestMapping(value = "/bake/{temp}", method = POST) public void bake(@PathVariable Integer temp) { ... }}25
  25. @ResponseBody@Controller@RequestMapping("/pizzas")public class PizzaController { // GET /pizzas @RequestMapping( method = GET, produces = "application/json") public @ResponseBody List<Pizza> list() { ... }}26
  26. @ResponseBody@Controller@RequestMapping("/pizzas")public class PizzaController { // GET /pizzas @RequestMapping(method = GET, produces = MediaType.APPLICATION_JSON_VALUE ) public @ResponseBody List<Pizza> list() { ... }}27
  27. @RequestBody@Controller@RequestMapping("/pizzas")public class PizzaController { // PUT /pizzas @RequestMapping( method = PUT, consumes = "application/json") public void create(@RequestBody Pizza pizza) { ... }}28
  28. @ResponseStatus@Controller@RequestMapping("/pizzas")public class PizzaController { // PUT /pizzas @ResponseStatus(HttpStatus.CREATED) @RequestMapping( method = PUT, consumes = "application/json") public void create(@RequestBody Pizza pizza) { ... }}29
  29. Async MVC Processing: Callable@Controller@RequestMapping("/pizzas")public class PizzaController { @RequestMapping(value = "/orders", method = POST) @ResponseBody public Callable<String> upload(MultipartFile file) { return new Callable<Pizza>() { public Pizza call() throws Exception // ... return pizza; } }}30
  30. Async MVC Processing: DeferredResult @RequestMapping("/quotes") @ResponseBody public DeferredResult quotes() { DeferredResult deferredResult = new DeferredResult(); // Add deferredResult to a Queue or a Map... return deferredResult;}// In some other thread:// Set the return value on the DeferredResultdeferredResult.set(data); - thread managed outside of Spring MVC - JMS or AMQP message listener, another HTTP request, etc. 31
  31. Async MVC Processing: AsyncTask@RequestMapping(name =“/upload”,method=RequestMethod.POST) public AsyncTask<Foo> processUpload(MultipartFile file) { TaskExecutor asyncTaskExecutor = new AsyncTaskExecutor(...); return new AsyncTask<Foo>( 1000L, // timeout asyncTaskExecutor, // thread pool new Callable<Foo>(){ ..} // thread );} - same as Callable, with extra features - override timeout value for async processing - lets you specify a specific AsyncTaskExecutor 32
  32. Message Converters• RSS/ATOM• java.awt.BufferedImage• JSON• JAXB• Write your own! – iCal – GSON• Third Party: • https://github.com/joshlong/spring-advanced-marhshallers-and-service-exporters – supports Google PB, Avro, Thrift, MessagePack, Google Snappy33
  33. Spring MVC Demo
  34. Testing• Testing of web APIs isn’t easy – In container, end-to-end, string comparison, etc. – Out of container, Java objects, bypassing much of Spring’s magic• What we want is out of container, but with as much of Spring as we can get35
  35. Spring MVC Testing• Available in Spring 3.2• Bootstraps most of Spring’s MVC infrastructure so that you unit and integration test your web application end-to- end• Provides APIs for testing interesting parts of requests and responses36
  36. REST on iOS• HTTP Client – NSURLConnection• JSON Processor (iOS 5) – NSJSONSerialization• Data – NSData – NSDictionary – NSArray38
  37. NSURLConnection• Loading Data Synchronously + sendSynchronousRequest:returningResponse:error:• Loading Data Asynchronously + sendAsynchronousRequest:queue:completionHandler:39
  38. Basic HTTP RequestNSURL *url = [NSURL URLWithString:@"http://localhost"];NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];40
  39. Basic HTTP Request... ImprovedNSURL *url = [NSURL URLWithString:@"http://localhost"];NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];NSURLResponse *response;NSError *error;NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];NSInteger status = [(NSHTTPURLResponse *)response statusCode];if (status == 200 && data.length > 0 && error == nil){ // do something with data}41
  40. Asynchronous HTTP RequestNSURL *url = [NSURL URLWithString:@"http://localhost"];NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){ NSInteger status = [(NSHTTPURLResponse *)response statusCode]; if (status == 200 && data.length > 0 && error == nil) { // do something with data }}42
  41. HTTP HeadersNSURL *url = [NSURL URLWithString:@"http://localhost"];NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];[request setHTTPMethod:@"PUT"];[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];[request setValue:contentLength forHTTPHeaderField:@"Content-Length"];[request setHTTPBody:postData];43
  42. JSON Serialization// deserialize JSON dataNSError *error;NSDictionary *d = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];// serialize JSON dataNSError *error;NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error];44
  43. iOS Demo
  44. Conclusion• API Design Matters – URIs represent resources, not actions – HTTP verbs are general, but can be used in ways that make anything possible• Implementation isn’t rocket science – Spring MVC – Spring HATEOAS• Easy testing – Out-of-container, but full Spring stack46
  45. More Information• Roy Fielding’s Dissertation http://www.ics.uci.edu/~fielding/pubs/dissertation/ evaluation.htm#sec_6_1%7C• Spring MVC Reference http://static.springsource.org/spring-framework/docs/ current/spring-framework-reference/html/mvc.html• URL Loading System Programming Guide http://developer.apple.com/library/ios/#documentation/ Cocoa/Conceptual/URLLoadingSystem/ URLLoadingSystem.html47
  46. Related Spring Projects• REST Shell https://github.com/SpringSource/rest-shell• Spring HATEOAS https://github.com/SpringSource/spring-hateoas• Spring MVC Test https://github.com/SpringSource/spring-test-mvc48
  47. Questions?• All Sample Code: https://github.com/royclarkson/rest-demo https://github.com/joshlong/the-spring-tutorial• Presentation: http://www.slideshare.net/royclarkson49