Spring MVC to iOS and the REST

Roy Clarkson, Senior Engineer, VMware
Twitter/GitHub: @royclarkson

Josh Long, Spring Developer Advocate
Twitter: @starbuxman GitHub: @joshlong


© 2013 SpringSource, by VMware
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/royclarkson




2
About Josh Long (⻰龙之春)
Spring Developer Advocate
twitter: @starbuxman
weibo: @springsource
josh.long@springsource.com




                             3
About Josh Long

Spring Developer Advocate
twitter: @starbuxman
josh.long@springsource.com

Contributor To:

•Spring Integration
•Spring Batch
•Spring Hadoop
•Activiti Workflow Engine




4
Agenda


•   REST
•   Spring MVC
•   iOS
•   Demos




5
The term Representational State Transfer was introduced and
      defined in 2000 by Roy Fielding in his doctoral dissertation.




6
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 it




7
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 scalability

8
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 relations




9
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/1


10
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/1


11
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
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
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 Error




14
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 header



15
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 modification




16
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 request




17
Media Types


• Accept & Content-Type HTTP Headers
• Client or server describes the content




18
Spring Web MVC DispatcherServlet




20
Annotations of Spring MVC


•    @Controller
•    @RequestMapping
•    @RequestParam
•    @PathVariable
•    @ResponseBody
•    @RequestBody
•    @ResponseStatus




21
@Controller


@Controller
public class PizzaController {
...
}




22
@RequestMapping


@Controller
@RequestMapping("/pizzas")
public class PizzaController {

     // POST /pizzas/bake
     @RequestMapping(value = "/bake", method = POST)
	    public void bake() {
        ...
	    }
}




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
@PathVariable


@Controller
@RequestMapping("/pizzas")
public class PizzaController {

	    // POST /pizzas/bake/400
	    @RequestMapping(value = "/bake/{temp}", method = POST)
	    public void bake(@PathVariable Integer temp) {
	    	 ...
	    }
}




25
@ResponseBody


@Controller
@RequestMapping("/pizzas")
public class PizzaController {

	    // GET /pizzas
	    @RequestMapping(
	    	 	 	 method = GET, produces = "application/json")
	    public @ResponseBody List<Pizza> list() {
	    	 ...
	    }
}




26
@ResponseBody


@Controller
@RequestMapping("/pizzas")
public class PizzaController {

	    // GET /pizzas
	    @RequestMapping(method = GET,
	    	 	 	 produces = MediaType.APPLICATION_JSON_VALUE )
	    public @ResponseBody List<Pizza> list() {
	    	 ...
	    }
}




27
@RequestBody


@Controller
@RequestMapping("/pizzas")
public class PizzaController {

	    // PUT /pizzas
	    @RequestMapping(
	    	 	 	 method = PUT, consumes = "application/json")
	    public void create(@RequestBody Pizza pizza) {
	    	 ...
	    }
}




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
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
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 DeferredResult
deferredResult.set(data);


     - thread managed outside of Spring MVC
     - JMS or AMQP message listener, another HTTP request, etc.




                                                                  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
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 Snappy


33
Spring MVC Demo
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 get




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
  responses




36
REST on iOS


• HTTP Client
     – NSURLConnection


• JSON Processor (iOS 5)
     – NSJSONSerialization


• Data
     – NSData
     – NSDictionary
     – NSArray




38
NSURLConnection


• Loading Data Synchronously

     + sendSynchronousRequest:returningResponse:error:

• Loading Data Asynchronously

     + sendAsynchronousRequest:queue:completionHandler:




39
Basic HTTP Request


NSURL *url = [NSURL URLWithString:@"http://localhost"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];


NSData *data = [NSURLConnection sendSynchronousRequest:request
                                     returningResponse:nil
                                                 error:nil];




40
Basic HTTP Request... Improved


NSURL *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
Asynchronous HTTP Request


NSURL *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
HTTP Headers


NSURL *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
JSON Serialization


// deserialize JSON data
NSError *error;
NSDictionary *d = [NSJSONSerialization JSONObjectWithData:data
                                                  options:0
                                                    error:&error];

// serialize JSON data
NSError *error;
NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary
                                               options:0
                                                 error:&error];




44
iOS Demo
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 stack




46
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.html


47
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-mvc




48
Questions?


• All Sample Code:
  https://github.com/royclarkson/rest-demo
  https://github.com/joshlong/the-spring-tutorial

• Presentation:
  http://www.slideshare.net/royclarkson




49

Spring MVC to iOS and the REST

  • 1.
    Spring MVC toiOS and the REST Roy Clarkson, Senior Engineer, VMware Twitter/GitHub: @royclarkson Josh Long, Spring Developer Advocate Twitter: @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/royclarkson 2
  • 3.
    About Josh Long(⻰龙之春) Spring Developer Advocate twitter: @starbuxman weibo: @springsource josh.long@springsource.com 3
  • 4.
    About Josh Long SpringDeveloper Advocate twitter: @starbuxman josh.long@springsource.com Contributor To: •Spring Integration •Spring Batch •Spring Hadoop •Activiti Workflow Engine 4
  • 5.
    Agenda • REST • Spring MVC • iOS • Demos 5
  • 6.
    The term RepresentationalState 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 it 7
  • 8.
    The Principles ofREST • 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 scalability 8
  • 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 relations 9
  • 10.
    HTTP GET • Retrieveinformation – 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/1 10
  • 11.
    HTTP DELETE • Requestthat a resource be removed • The resource doesn’t have to be removed immediately – Removal may be a long running task DELETE /pizzas/1 11
  • 12.
    HTTP PUT • Requeststhat 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 • Requeststhat 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 Error 14
  • 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 header 15
  • 16.
    Client Error StatusCodes • 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 modification 16
  • 17.
    Client Error StatusCodes • 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 request 17
  • 18.
    Media Types • Accept& Content-Type HTTP Headers • Client or server describes the content 18
  • 20.
    Spring Web MVCDispatcherServlet 20
  • 21.
    Annotations of SpringMVC • @Controller • @RequestMapping • @RequestParam • @PathVariable • @ResponseBody • @RequestBody • @ResponseStatus 21
  • 22.
  • 23.
    @RequestMapping @Controller @RequestMapping("/pizzas") public class PizzaController{ // POST /pizzas/bake @RequestMapping(value = "/bake", method = POST) public void bake() { ... } } 23
  • 24.
    @RequestParam @Controller @RequestMapping("/pizzas") public class PizzaController{ // POST /pizzas/bake?temp=400 @RequestMapping(value = "/bake", method = POST) public void bake(@RequestParam Integer temp) { ... } } 24
  • 25.
    @PathVariable @Controller @RequestMapping("/pizzas") public class PizzaController{ // POST /pizzas/bake/400 @RequestMapping(value = "/bake/{temp}", method = POST) public void bake(@PathVariable Integer temp) { ... } } 25
  • 26.
    @ResponseBody @Controller @RequestMapping("/pizzas") public class PizzaController{ // GET /pizzas @RequestMapping( method = GET, produces = "application/json") public @ResponseBody List<Pizza> list() { ... } } 26
  • 27.
    @ResponseBody @Controller @RequestMapping("/pizzas") public class PizzaController{ // GET /pizzas @RequestMapping(method = GET, produces = MediaType.APPLICATION_JSON_VALUE ) public @ResponseBody List<Pizza> list() { ... } } 27
  • 28.
    @RequestBody @Controller @RequestMapping("/pizzas") public class PizzaController{ // PUT /pizzas @RequestMapping( method = PUT, consumes = "application/json") public void create(@RequestBody Pizza pizza) { ... } } 28
  • 29.
    @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
  • 30.
    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
  • 31.
    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 DeferredResult deferredResult.set(data); - thread managed outside of Spring MVC - JMS or AMQP message listener, another HTTP request, etc. 31
  • 32.
    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
  • 33.
    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 Snappy 33
  • 34.
  • 35.
    Testing • Testing ofweb 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 get 35
  • 36.
    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 responses 36
  • 38.
    REST on iOS •HTTP Client – NSURLConnection • JSON Processor (iOS 5) – NSJSONSerialization • Data – NSData – NSDictionary – NSArray 38
  • 39.
    NSURLConnection • Loading DataSynchronously + sendSynchronousRequest:returningResponse:error: • Loading Data Asynchronously + sendAsynchronousRequest:queue:completionHandler: 39
  • 40.
    Basic HTTP Request NSURL*url = [NSURL URLWithString:@"http://localhost"]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; 40
  • 41.
    Basic HTTP Request...Improved NSURL *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
  • 42.
    Asynchronous HTTP Request NSURL*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
  • 43.
    HTTP Headers NSURL *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
  • 44.
    JSON Serialization // deserializeJSON data NSError *error; NSDictionary *d = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; // serialize JSON data NSError *error; NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error]; 44
  • 45.
  • 46.
    Conclusion • API DesignMatters – 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 stack 46
  • 47.
    More Information • RoyFielding’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.html 47
  • 48.
    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-mvc 48
  • 49.
    Questions? • All SampleCode: https://github.com/royclarkson/rest-demo https://github.com/joshlong/the-spring-tutorial • Presentation: http://www.slideshare.net/royclarkson 49