際際滷

際際滷Share a Scribd company logo
WHICH RESTFUL WEB SERVICES
FRAMEWORK IS BETTER?

JAX-RS OR SPRING FRAMEWORK


    Hien Luu
Agenda
 REST Overview
 Spring Framework & JAX-RS (Jersey)

 Resource Identifier & Implementation

 Resource Representation Support

 Content Negotiation

 Caching Support

 Securing RESTful web services APIs

 RESTful Client Library

 Conclusion
REST Overview

             GET /v1/cu
                           stomers/10
            Accept: app              1 HTTP/1.1
                         lication/xm
 Client 1                              l




                                                           www.you.com
                                                .1
                                     /101 HTTP/1
                              rs
                  /v1/c ustome json
            Get            cation/
              cept : appli
            Ac
 Client 2




                  Two different resource representations
RESTful Web Services Framework
   Spring Framework
     も Supports  REST in 3.0
     も Extension to the MVC framework

   JAX-RS
     も Java API for RESTful Web Services  JSR-311
     も Implementations
        Jersey
        RESTEasy    jboss
        Restlet
        Apache    CXF
Resource Identifier & Implementation

 Binding resource identifier to resource method
 Root resource, sub-resource

 Instantiation Model

 Request data

 Matrix parameter

 Response, status code

 Exception Handling
Resource Identifier & Implementation

                            GET /customers/101 HTTP/1.1



             JAX-RS                       Spring Framework

             @Path                        @RequestMapping

@Path("/customers")                       @Controller
public class CustomerResource {           @RequestMapping("/customers")
                                          public class CustomerResource {
    @GET
    @Path("{id})                             @RequestMapping("{id},
    public Customer getCustomer(                     method=RequestMethod.GET)
          @PathParam("id") int id) {}         public Customer getCustomer(
                                                    @PathVariable("id") int id) {}

}                                         }
Resource Identifier & Implementation

   JAX-RS: Binding URI Regular Expression
     @Path("/customers")
     public class CustomerResource {

         @GET
         @Path("{id: d+})
         public Customer getCustomer(
               @PathParam("id") int id) {}
     }




   Spring Framework: Ant-style expression
     @RequestMapping("/customers")
     public class CustomerResource {

         @RequestMapping(/*/customer/{id})
         public Customer getCustomer(@PathVariable int id) {
         }
     }
Resource Identifier & Implementation
       JAX-RS

@Path("/customers")
public class CustomerResource {

    @POST
    @Consumes("application/xml")
    public Response createCustomer(Customer customer) {}

    @GET
    @Path("{id}")
    @Produces("application/xml")
    public Customer getCustomer(@PathParam("id") int id) {}


    @PUT
    @Path("{id}")
    @Consumes("application/xml")
    public Customer updateCustomer(@PathParam("id") int id,
             Customer customer) {}
}
Resource Identifier & Implementation
        Spring
@Controller
@RequestMapping("/customers")
public class CustomerResource {

    @RequestMapping(method=Request.POST,
                    headers="Content-Type=application/xml")
    public String createCustomer(Customer customer) {}

    @RequestMapping(value=/{id}, method=Request.GET,
                    headers=Accept=application/xml)
    public Customer getCustomer(@PathVariable int id) {}


    @RequestMapping(value=/{id}, method=Request.PUT,
                    headers="Content-Type=application/xml")
    public Customer updateCustomer(@PathParam("id") int id,
                           Customer customer) {}

}
Resource Identifier & Implementation

   JAX-RS Sub Resource Locator
     も Dynamically dispatch requests
     も Absent of request method designator: GET, POST, etc.

     も Return an object to handle HTTP request

 @Path("widgets")
 public class SubResourceLocatorResource {

     @Path("{region}")
     public SubResource dispatcher(@PathParam("region") String region) {
        return new SubResource(region);
     }
 }



   Spring Framework - no sub resource locator
Resource Identifier & Implementation

   Instantiation Model
     も JAX-RS
        New  resource instance per request (default)
        Singleton (up to implementation)

     も Spring   Framework
        Singleton   (default)
Resource Identifier & Implementation

                               Request Data

                   JAX-RS                     Spring Framework
       @QueryParam*                     @RequestParam*
       @FormParam*                      @RequestParam*
       @PathParam*                      @PathVariable*
       @CookieParam*                    @CookieValue*
       @HeaderParam*                    @RequestHeader*
       @MatrixParam*                    Not supported
       @Context
       ≒Can specify default value      ≒Can specify require or not
       @DefaultValue                    ≒Can specify default value

JAX-RS allows above annotations on fields and setters with per-request scope resource
Resource Identifier & Implementation
      JAX-RS
@GET
@Path(/foo/{id})
public Response bar(@PathParm(id) int id,
        @QueryParam(a) @DefaultValue(JavaOne) String a,
        @FormParam(b) int b,
        @MatrixParam(m),
        @CookieParam(token) String token,
        @HeaderParam(User-Agent) String userAgent {}



      Spring
@RequestMapping(value=/foo/{id}, method=Request.GET)
public void bar(@PathVariable int id,
        @RequestParam(value=a, defaultValue=JavaOne) String a,
        @RequestParam(b, required=false) int b,
        @CookieValue(token) String token,
        @RequestHeader(User-Agent) String userAgent {}
Resource Identifier & Implementation
   Context information - @Context
     も UriInfo  static and dynamic, per-request information
     も Application  resources
     も HttpHeaders  request header information
     も Request - precondition evaluation, representation variant
     も SecurityContext  security context of current request
     も Providers  look up provider instances


     @GET
     @Path("/{info: .+}")
     public Response getContextInfo(@Context Application app,
                            @Context UriInfo uriInfo,
                            @Context HttpHeaders headers,
                            @Context Request request,
                            @Context SecurityContext securityContext) {
       return Response.ok().build();
     }
Resource Identifier & Implementation

   Spring Framework
     も HttpServletRequest
          Header

     も HttpServletResponse
          Response

     も ApplicationContext


     @RequestMapping(/info")
     public void getContextInfo(HttpServletRequest request,
           HttpServletResponse response) {

         //
     }
Resource Identifier & Implementation

                    Resource Method Response

               JAX-RS                     Spring Framework
   void*                          void*
   Response*                      Any Java type
   GenericEntity*                 ResponseEntity<?>
   Any Java type*




   *null return status code 204   * Handle response itself
Resource Identifier & Implementation

   JAX-RS
     も ResponseBuilder, Response, UriBuilder
     も Convenient for status code, setting headers

 @GET
 @Path(/foo/{id})
 public Response bar(@PathParm(id) int id) {
   StringBuffer buf = new StringBuffer();

     ResponseBuilder responseBuilder =
           Response.ok(buf.toString(), MediaType.TEXT_HTML_TYPE).
           location(URI.create("/foo).
           lastModified(new Date());

     return responseBuilder.build();
 }
Resource Identifier & Implementation

   Spring Framework
     も ResponseEntity<?>,     HttpHeaders
 @ReuestMapping(value={id}, method=RequestMethod=GET)
 public ResponseEntity<Customer> bar(@PathVariable int id) {

     Customer customer = ;

     HttpHeaders responseHeaders = new HttpHeaders();
     responseHeaders.setLocation(URI.create("/customers/" + id));
     responseHeaders.setContentType(MediaType.APPLICATION_XML);

      return new ResponseEntity(customer,
          responseHeaders, HttpStatus.OK);
 }
Exception Handling - JAX-RS
      Resource method
        も Canthrow checked or unchecked exception
        も WebApplicationException
           Response  use directly if available
           Can specify response code

        も Exception    mapping interface
           Mapping   of an exception to specific Response
@Provider  Total control the response
public class ExceptionMappingProvider implements ExceptionMapper<MyException>{
  public Response toResponse(MyException exception) {
     return Response.status(Response.Status.FORBIDDEN).
            entity(exception.getMessage()).build();
  }
}
Exception Handling - JAX-RS
 @GET
 @Path({id})
 public Customer (@PathParm(id) int id) {
      Customer customer = getCustomer(id);
      if (customer == null) {
        throw new WebApplicationException(Response.Status.NOT_FOUND);
      } else {
        return customer;
      }
 }


@GET
@Path("/uncheckedException")
public Response uncheckedException() {
       throw new MyException("just for fun");
}
                        @Provider
                        public class ExMappingProvider implements
                                           ExceptionMapper<MyException> {
                             public Response toResponse(MyException exc) {
                           
                             }
                        }
Exception Handling  Spring
   Resource method
     も Canthrow checked or unchecked exception
     も @ResponseStatus  annotation on exception class
        to   control status code
     も Exception    handler at resource class level (not global)
        Can control status code and returned message
        @ResponseBody
        @ResponseStatus
        Doesnt support ResponseEntity

     も Default    is 500 status code
Exception Handling  Spring
@ResponseStatus(value=HttpStatus.FORBIDDEN)
public class ForbiddenException extends RuntimeException {
    public ForbiddenException(String msg) {
      super(msg);
    }
}


@Controller
@RequestMapping("/exceptions")
public class ExceptionResource {

    @ResponseStatus(value=HttpStatus.NOT_FOUND)
    @ExceptionHandler(ResourceNotFoundException.class)
    public @ResponseBody String exceptionHandler1(
              ResourceNotFoundException ex1) {
        return ex1.getMessage();
    }
    @RequestMapping("/resourceNotFoundException")
    public void resourceNotFoundException() {
      throw new ResourceNotFoundException("resource not found");
    }
}
Score Card

                         Scores


       Feature           JAX-RS   Spring
 Resource URI              5.0     4.5
 Sub resource              5.0     4.0
 Request Data              5.0     4.8
 Response, status code     5.0     4.5
 Exception Handling        5.0     5.0
Resource Representation Support

                       JAX-RS              Spring
                                                          erter
        Message                                    ageConv
XML            BodyRea
                         der              HttpMess                  XML

                                                        erter
          Message
                  BodyWr                 HttpMessageConv
                         iter
                                  Java
                                 POJO
                         der
               eB odyRea                  HttpMe
                                                ssageC
         Messag                                          onverte
                                                                r
                          iter           HttpMe
JSON
              sageB odyWr                      ssageCo
                                                      nverter
                                                                    JSON
           Mes
Resource Representation Support
                          Out-of-the-box Support

                 JAX-RS                          Spring Framework
byte[] (*/*)                          byte[]
String (*/*)                          String
InputStream (*/*)                     MultiValueMap
Reader (*/*)                          Source
File (*/*)                            Class<T>
Source (*/xml)
JAXBElement (*/xml)                   Registered by default
MultivalueMap (application/x-www-
form-urlencoded)
StreamingOutput (*/*)
Class<T>
Resource Representation Support
                            Content Negotiation


GET http://<host>:<port>/customers/1
Accept: application/xml;q=0.8, application/json;q=0.6


                                        HTTP/1.1 200 OK
                                        Content-type: application/xml
                                        <customer id=1>.</customer>


                                       HTTP/1.1 200 OK
                                       Content-type: application/json
                                       {customer : { id : 1 }}

                                        HTTP/1.1 406 Not Acceptable
Resource Representation Support
                                                         JAX-RS
 Content-Type: application/xml      @PUT
                                    @Path(id}")
                                    @Consumes(application/xml)
                                    @Produces("application/xml)
                                    public Customer updateCustomer(..) {
                                         ..
 Accept: application/xml            }




                                                         Spring

@RequestMapping(value={id}, method=RequetMethod.PUT,
   headers="Content-Type=application/xml)
public ResponseEntity<Customer> updateCustomer(..) {
     ..
}
Resource Representation Support
      JAX-RS
@GET
@Path("{id}")
@Produces({"application/xml", "application/json"})
public Customer getCustomer(@PathParam("id") int id) {
   Customer customer = lookUpCustomer(id);
   return customer;
}




      Spring

@RequestMapping(value = "/{id}", method = RequestMethod.GET,
    headers=Accept=application/xml,application/json)
public ResponseEntity<Customer> getCustomer(@PathVariable int id) {
   Customer customer = lookUpCustomer(id);
   return ResponseEntiry<Customer>(customer, HttpStatus.OK);
}
Resource Representation Support
                                     JAX-RS

public interface MessageBodyReader<T> {       public interface MessageBodyWriter<T> {
  boolean isReadable(Class<?> type, .);
                                               boolean isWriteable(Class<?> type, );
    T readFrom(Class<?>,   );                 long getSize(T t, Class<?> type,);
}                                              void writeTo(T t, Class<?> type,)
                                              }




@Provider                                     @Provider
public class MyMBR implements                 public class MyMBW implements
     MessageBodyReader<MyCustomerClass> {          MessageBodyWriter<MyCustomerClass>
                                              {
                                                
}                                             }
Resource Representation Support
                                    Spring

public interface HttpMessageConverter<T> {
  boolean canRead(Class<?> clazz, MediaType mediaType);
  boolean canWrite(Class<?> clazz, MediaType mediaType);
  List<MediaType> getSupportedMediaTypes();
  T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
  void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
}




public class MyHttpMessageConverter<MyCustomerClass> implements
     MessageBodyReader<MyCustomerClass> {

    
}
Resource Representation Support
                      Spring - Content Negotiation Through URI Pattern


 GET http://<host>:<port>/customers/1.xml              Request
                                                                            Resource

 GET http://<host>:<port>/customers/1.json




                                    ContentNegotiatingViewResolver



application/json
                   MappingJacksonJsonView
                                              JSON                   JSON - application/json
                                                                     XML - application/xml
application/xml
                       MarshallingView
                                               XML
Resource Representation Support
                        Advanced Content Negotiation

GET http://<host>:<port>/customers/1

Accept: application/xml;q=0.8, application/json;q=0.6
Accept-Language: fr;q=1.0, en;p=0.5
Accept-Encoding: gzip, deflate


public class Variant {
    public Variant(MediaType mediaType, Locale locale,
        String encoding) {
    }
}
                                                            JAX-RS
public interface Request {
    public Variant selectVariant(List<Variant> variants);
    
}
Resource Representation Support
                           Advanced Content Negotiation
 @GET
 @Path("{id})
 public Response getCustomer(@PathParam("id") int id, @Context Request request){

    Variant.VariantBuilder vb = Variant.VariantBuilder.newInstance();
    vb.mediaTypes(MediaType.APPLICATION_ATOM_XML_TYPE,
         MediaType.APPLICATION_XML_TYPE, MediaType.APPLICATION_JSON_TYPE);
    vb.languages(Locale.CHINESE, Locale.FRANCE, Locale.ENGLISH);
    vb.encodings("deflate", "gzip");
    List<Variant> variants = vb.add().build();

    Variant matchedVariant = request.selectVariant(variants);
    Customer customer = lookUpCustomer(id);
    ResponseBuilder responseBuilder = Response.ok(customer);
    responseBuilder.type(matchedVariant.getMediaType())
       .language(matchedVariant.getLanguage())
       .header("Content-Encoding", matchedVariant.getEncoding());

    return responseBuilder.build();
}
Resource Representation Support

                             Scores


         Feature                JAX-RS      Spring
 Request mapping                      5.0    4.9
 Resource representation              5.0    5.0
 Custom data serialization            5.0    5.0
 Content negotiation                  5.0    5.0
Caching & Concurrency

                   Caching & Concurrency Control HTTP Headers


 Cache               Request Header            Response Header
Validation                              Cache-Control


              If-Modified-Since         Last-Modified
              If-None-Match             ETag


              If-Unmodified-Since       Last-Modified
              If-Match                  Etag
Concurrency
  Control
Caching & Concurrency
                                 Caching With Date

GET /customers/1
Accept: application/xml
                                  HTTP/1.1 200 OK
                                  Content-type: application/xml
                                  Cache-Control: private, no-store, max-age=600
                                  Last-Modified: Sun, 22 August 2010 05:21 GMT
                                  <customer id=1>.</customer>


GET /customers/1
Accept: application/xml
If-Modified-Since: Sun, 22 August 2010 05:21 EST


                                   HTTP/1.1 304 Not Modified
Caching & Concurrency
                             Caching With ETag

GET /customers/1
Accept: application/xml
                             HTTP/1.1 200 OK
                             Content-type: application/xml
                             Cache-Control: private, no-store, max-age=600
                             Etag: 123456789
                             <customer id=1>.</customer>


GET /customers/1
Accept: application/xml
If-None-Match: 123456789


                              HTTP/1.1 304 Not Modified
Caching & Concurrency
                             Conditional Updates

GET /customers/1
Accept: application/xml
                             HTTP/1.1 200 OK
                             Content-type: application/xml
                             Cache-Control: private, no-store, max-age=600
                             Etag: 123456789
                             <customer id=1>.</customer>


PUT /customers/1
Accept: application/xml
If-None-Match: 123456788


                               HTTP/1.1 412 Precondition Failed
Caching & Concurrency
                                JAX-RS

   CacheControl
     も Abstraction   for Cache-Control header
   EntityTag
     も Abstraction   for entity tag
   Request
     も evaluatePreconditions(EntityTagtag)
     も evaluatePreconditions(Date date)

     も Return non-null builder
Caching & Concurrency
                             Spring

   Servlet Filter
     も ShallowEtagHeaderFilter

     も Generate   MD5 hash of the response
     も Automatically add Etag header

     も Detect If-None-Match and take action

     も Not flexible
Resource Representation Support

                       Scores


           Feature        JAX-RS      Spring
 Caching                        5.0    4.5
 Concurrency Control            5.0    4.5
Securing RESTful web services APIs
   Authentication
     も Basicauthentication  password is in Base64
     も Digest authentication  secure MD5 hashes

   Authorization
     も Assign   roles to users
   API interact with servlet & J2EE
     も Setup    in web.xml
Securing RESTful web services APIs

                         JAX-RS Annotation Security
@Path("/customers")
@RolesAllowed(ADMIN, CUSTOMER_REP})
public class CustomerResource {

    @RolesAllowed(ADMIN)
    @POST
    @Consumes("application/xml")
    public Response createCustomer(InputStream is) {}

    @PermitALL
    @GET
    @Path("{id}")
    @Produces("application/xml")
    public StreamingOutput getCustomer(@PathParam("id") int id) {}


}
Securing RESTful web services APIs

                       JAX-RS Programmatic Security
@Path("/customers")
public class CustomerResource {

    @POST
    @Consumes("application/xml")
    public Response createCustomer(Customer customer,
        @Context SecurityContext sc) {

        System.out.println(User:  + sc.getUserPrincipal().getName());
        if (!sc.isUserInRole(ADMIN)) {
           // return 401
        }
    }
}




                    Thin wrapper on HTTPServletRequest Security
Securing RESTful web services APIs

                         Spring Programmatic Security
@RequestMapping("/customers")
public class CustomerResource {


    @RequestMapping(method = RequestMethod.POST,
          headers="Content-Type=application/xml)
    public ResponseEntity<Customer> createCustomer(Customer customer,
        HttpServletRequest request) {

        if (!request.isUserInRole(ADMIN)) {
            // return 401
         }
    }
}
Resource Representation Support

                      Scores


            Feature      JAX-RS      Spring
 Security                      5.0    5.0
RESTful Client Library
   Goals
     も Make it easy to work with Restful web services
     も Work at Java object level

   Jersey Client
     も Notpart of JAX-RS
     も HTTPURLConnection, HTTPClient
     も Work with MessageBodyReader and MessageBodyWriter

   Part of SpringFramework  RestTemplate
     も HTTPURLConnection,HTTPClient
     も Work with HttpMessageConverter
RESTful Client Library

                              Scores


          Feature                   JAX-RS                 Spring
 RESTful Client Library                 0                   5.0



           Each JAX-RS implementation provides their own
                           client library
Summary


    JAX-RS   ~
             =   Spring
Q &A

More Related Content

Javaone 2010

  • 1. WHICH RESTFUL WEB SERVICES FRAMEWORK IS BETTER? JAX-RS OR SPRING FRAMEWORK Hien Luu
  • 2. Agenda REST Overview Spring Framework & JAX-RS (Jersey) Resource Identifier & Implementation Resource Representation Support Content Negotiation Caching Support Securing RESTful web services APIs RESTful Client Library Conclusion
  • 3. REST Overview GET /v1/cu stomers/10 Accept: app 1 HTTP/1.1 lication/xm Client 1 l www.you.com .1 /101 HTTP/1 rs /v1/c ustome json Get cation/ cept : appli Ac Client 2 Two different resource representations
  • 4. RESTful Web Services Framework Spring Framework も Supports REST in 3.0 も Extension to the MVC framework JAX-RS も Java API for RESTful Web Services JSR-311 も Implementations Jersey RESTEasy jboss Restlet Apache CXF
  • 5. Resource Identifier & Implementation Binding resource identifier to resource method Root resource, sub-resource Instantiation Model Request data Matrix parameter Response, status code Exception Handling
  • 6. Resource Identifier & Implementation GET /customers/101 HTTP/1.1 JAX-RS Spring Framework @Path @RequestMapping @Path("/customers") @Controller public class CustomerResource { @RequestMapping("/customers") public class CustomerResource { @GET @Path("{id}) @RequestMapping("{id}, public Customer getCustomer( method=RequestMethod.GET) @PathParam("id") int id) {} public Customer getCustomer( @PathVariable("id") int id) {} } }
  • 7. Resource Identifier & Implementation JAX-RS: Binding URI Regular Expression @Path("/customers") public class CustomerResource { @GET @Path("{id: d+}) public Customer getCustomer( @PathParam("id") int id) {} } Spring Framework: Ant-style expression @RequestMapping("/customers") public class CustomerResource { @RequestMapping(/*/customer/{id}) public Customer getCustomer(@PathVariable int id) { } }
  • 8. Resource Identifier & Implementation JAX-RS @Path("/customers") public class CustomerResource { @POST @Consumes("application/xml") public Response createCustomer(Customer customer) {} @GET @Path("{id}") @Produces("application/xml") public Customer getCustomer(@PathParam("id") int id) {} @PUT @Path("{id}") @Consumes("application/xml") public Customer updateCustomer(@PathParam("id") int id, Customer customer) {} }
  • 9. Resource Identifier & Implementation Spring @Controller @RequestMapping("/customers") public class CustomerResource { @RequestMapping(method=Request.POST, headers="Content-Type=application/xml") public String createCustomer(Customer customer) {} @RequestMapping(value=/{id}, method=Request.GET, headers=Accept=application/xml) public Customer getCustomer(@PathVariable int id) {} @RequestMapping(value=/{id}, method=Request.PUT, headers="Content-Type=application/xml") public Customer updateCustomer(@PathParam("id") int id, Customer customer) {} }
  • 10. Resource Identifier & Implementation JAX-RS Sub Resource Locator も Dynamically dispatch requests も Absent of request method designator: GET, POST, etc. も Return an object to handle HTTP request @Path("widgets") public class SubResourceLocatorResource { @Path("{region}") public SubResource dispatcher(@PathParam("region") String region) { return new SubResource(region); } } Spring Framework - no sub resource locator
  • 11. Resource Identifier & Implementation Instantiation Model も JAX-RS New resource instance per request (default) Singleton (up to implementation) も Spring Framework Singleton (default)
  • 12. Resource Identifier & Implementation Request Data JAX-RS Spring Framework @QueryParam* @RequestParam* @FormParam* @RequestParam* @PathParam* @PathVariable* @CookieParam* @CookieValue* @HeaderParam* @RequestHeader* @MatrixParam* Not supported @Context ≒Can specify default value ≒Can specify require or not @DefaultValue ≒Can specify default value JAX-RS allows above annotations on fields and setters with per-request scope resource
  • 13. Resource Identifier & Implementation JAX-RS @GET @Path(/foo/{id}) public Response bar(@PathParm(id) int id, @QueryParam(a) @DefaultValue(JavaOne) String a, @FormParam(b) int b, @MatrixParam(m), @CookieParam(token) String token, @HeaderParam(User-Agent) String userAgent {} Spring @RequestMapping(value=/foo/{id}, method=Request.GET) public void bar(@PathVariable int id, @RequestParam(value=a, defaultValue=JavaOne) String a, @RequestParam(b, required=false) int b, @CookieValue(token) String token, @RequestHeader(User-Agent) String userAgent {}
  • 14. Resource Identifier & Implementation Context information - @Context も UriInfo static and dynamic, per-request information も Application resources も HttpHeaders request header information も Request - precondition evaluation, representation variant も SecurityContext security context of current request も Providers look up provider instances @GET @Path("/{info: .+}") public Response getContextInfo(@Context Application app, @Context UriInfo uriInfo, @Context HttpHeaders headers, @Context Request request, @Context SecurityContext securityContext) { return Response.ok().build(); }
  • 15. Resource Identifier & Implementation Spring Framework も HttpServletRequest Header も HttpServletResponse Response も ApplicationContext @RequestMapping(/info") public void getContextInfo(HttpServletRequest request, HttpServletResponse response) { // }
  • 16. Resource Identifier & Implementation Resource Method Response JAX-RS Spring Framework void* void* Response* Any Java type GenericEntity* ResponseEntity<?> Any Java type* *null return status code 204 * Handle response itself
  • 17. Resource Identifier & Implementation JAX-RS も ResponseBuilder, Response, UriBuilder も Convenient for status code, setting headers @GET @Path(/foo/{id}) public Response bar(@PathParm(id) int id) { StringBuffer buf = new StringBuffer(); ResponseBuilder responseBuilder = Response.ok(buf.toString(), MediaType.TEXT_HTML_TYPE). location(URI.create("/foo). lastModified(new Date()); return responseBuilder.build(); }
  • 18. Resource Identifier & Implementation Spring Framework も ResponseEntity<?>, HttpHeaders @ReuestMapping(value={id}, method=RequestMethod=GET) public ResponseEntity<Customer> bar(@PathVariable int id) { Customer customer = ; HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setLocation(URI.create("/customers/" + id)); responseHeaders.setContentType(MediaType.APPLICATION_XML); return new ResponseEntity(customer, responseHeaders, HttpStatus.OK); }
  • 19. Exception Handling - JAX-RS Resource method も Canthrow checked or unchecked exception も WebApplicationException Response use directly if available Can specify response code も Exception mapping interface Mapping of an exception to specific Response @Provider Total control the response public class ExceptionMappingProvider implements ExceptionMapper<MyException>{ public Response toResponse(MyException exception) { return Response.status(Response.Status.FORBIDDEN). entity(exception.getMessage()).build(); } }
  • 20. Exception Handling - JAX-RS @GET @Path({id}) public Customer (@PathParm(id) int id) { Customer customer = getCustomer(id); if (customer == null) { throw new WebApplicationException(Response.Status.NOT_FOUND); } else { return customer; } } @GET @Path("/uncheckedException") public Response uncheckedException() { throw new MyException("just for fun"); } @Provider public class ExMappingProvider implements ExceptionMapper<MyException> { public Response toResponse(MyException exc) { } }
  • 21. Exception Handling Spring Resource method も Canthrow checked or unchecked exception も @ResponseStatus annotation on exception class to control status code も Exception handler at resource class level (not global) Can control status code and returned message @ResponseBody @ResponseStatus Doesnt support ResponseEntity も Default is 500 status code
  • 22. Exception Handling Spring @ResponseStatus(value=HttpStatus.FORBIDDEN) public class ForbiddenException extends RuntimeException { public ForbiddenException(String msg) { super(msg); } } @Controller @RequestMapping("/exceptions") public class ExceptionResource { @ResponseStatus(value=HttpStatus.NOT_FOUND) @ExceptionHandler(ResourceNotFoundException.class) public @ResponseBody String exceptionHandler1( ResourceNotFoundException ex1) { return ex1.getMessage(); } @RequestMapping("/resourceNotFoundException") public void resourceNotFoundException() { throw new ResourceNotFoundException("resource not found"); } }
  • 23. Score Card Scores Feature JAX-RS Spring Resource URI 5.0 4.5 Sub resource 5.0 4.0 Request Data 5.0 4.8 Response, status code 5.0 4.5 Exception Handling 5.0 5.0
  • 24. Resource Representation Support JAX-RS Spring erter Message ageConv XML BodyRea der HttpMess XML erter Message BodyWr HttpMessageConv iter Java POJO der eB odyRea HttpMe ssageC Messag onverte r iter HttpMe JSON sageB odyWr ssageCo nverter JSON Mes
  • 25. Resource Representation Support Out-of-the-box Support JAX-RS Spring Framework byte[] (*/*) byte[] String (*/*) String InputStream (*/*) MultiValueMap Reader (*/*) Source File (*/*) Class<T> Source (*/xml) JAXBElement (*/xml) Registered by default MultivalueMap (application/x-www- form-urlencoded) StreamingOutput (*/*) Class<T>
  • 26. Resource Representation Support Content Negotiation GET http://<host>:<port>/customers/1 Accept: application/xml;q=0.8, application/json;q=0.6 HTTP/1.1 200 OK Content-type: application/xml <customer id=1>.</customer> HTTP/1.1 200 OK Content-type: application/json {customer : { id : 1 }} HTTP/1.1 406 Not Acceptable
  • 27. Resource Representation Support JAX-RS Content-Type: application/xml @PUT @Path(id}") @Consumes(application/xml) @Produces("application/xml) public Customer updateCustomer(..) { .. Accept: application/xml } Spring @RequestMapping(value={id}, method=RequetMethod.PUT, headers="Content-Type=application/xml) public ResponseEntity<Customer> updateCustomer(..) { .. }
  • 28. Resource Representation Support JAX-RS @GET @Path("{id}") @Produces({"application/xml", "application/json"}) public Customer getCustomer(@PathParam("id") int id) { Customer customer = lookUpCustomer(id); return customer; } Spring @RequestMapping(value = "/{id}", method = RequestMethod.GET, headers=Accept=application/xml,application/json) public ResponseEntity<Customer> getCustomer(@PathVariable int id) { Customer customer = lookUpCustomer(id); return ResponseEntiry<Customer>(customer, HttpStatus.OK); }
  • 29. Resource Representation Support JAX-RS public interface MessageBodyReader<T> { public interface MessageBodyWriter<T> { boolean isReadable(Class<?> type, .); boolean isWriteable(Class<?> type, ); T readFrom(Class<?>, ); long getSize(T t, Class<?> type,); } void writeTo(T t, Class<?> type,) } @Provider @Provider public class MyMBR implements public class MyMBW implements MessageBodyReader<MyCustomerClass> { MessageBodyWriter<MyCustomerClass> { } }
  • 30. Resource Representation Support Spring public interface HttpMessageConverter<T> { boolean canRead(Class<?> clazz, MediaType mediaType); boolean canWrite(Class<?> clazz, MediaType mediaType); List<MediaType> getSupportedMediaTypes(); T read(Class<? extends T> clazz, HttpInputMessage inputMessage) void write(T t, MediaType contentType, HttpOutputMessage outputMessage) } public class MyHttpMessageConverter<MyCustomerClass> implements MessageBodyReader<MyCustomerClass> { }
  • 31. Resource Representation Support Spring - Content Negotiation Through URI Pattern GET http://<host>:<port>/customers/1.xml Request Resource GET http://<host>:<port>/customers/1.json ContentNegotiatingViewResolver application/json MappingJacksonJsonView JSON JSON - application/json XML - application/xml application/xml MarshallingView XML
  • 32. Resource Representation Support Advanced Content Negotiation GET http://<host>:<port>/customers/1 Accept: application/xml;q=0.8, application/json;q=0.6 Accept-Language: fr;q=1.0, en;p=0.5 Accept-Encoding: gzip, deflate public class Variant { public Variant(MediaType mediaType, Locale locale, String encoding) { } } JAX-RS public interface Request { public Variant selectVariant(List<Variant> variants); }
  • 33. Resource Representation Support Advanced Content Negotiation @GET @Path("{id}) public Response getCustomer(@PathParam("id") int id, @Context Request request){ Variant.VariantBuilder vb = Variant.VariantBuilder.newInstance(); vb.mediaTypes(MediaType.APPLICATION_ATOM_XML_TYPE, MediaType.APPLICATION_XML_TYPE, MediaType.APPLICATION_JSON_TYPE); vb.languages(Locale.CHINESE, Locale.FRANCE, Locale.ENGLISH); vb.encodings("deflate", "gzip"); List<Variant> variants = vb.add().build(); Variant matchedVariant = request.selectVariant(variants); Customer customer = lookUpCustomer(id); ResponseBuilder responseBuilder = Response.ok(customer); responseBuilder.type(matchedVariant.getMediaType()) .language(matchedVariant.getLanguage()) .header("Content-Encoding", matchedVariant.getEncoding()); return responseBuilder.build(); }
  • 34. Resource Representation Support Scores Feature JAX-RS Spring Request mapping 5.0 4.9 Resource representation 5.0 5.0 Custom data serialization 5.0 5.0 Content negotiation 5.0 5.0
  • 35. Caching & Concurrency Caching & Concurrency Control HTTP Headers Cache Request Header Response Header Validation Cache-Control If-Modified-Since Last-Modified If-None-Match ETag If-Unmodified-Since Last-Modified If-Match Etag Concurrency Control
  • 36. Caching & Concurrency Caching With Date GET /customers/1 Accept: application/xml HTTP/1.1 200 OK Content-type: application/xml Cache-Control: private, no-store, max-age=600 Last-Modified: Sun, 22 August 2010 05:21 GMT <customer id=1>.</customer> GET /customers/1 Accept: application/xml If-Modified-Since: Sun, 22 August 2010 05:21 EST HTTP/1.1 304 Not Modified
  • 37. Caching & Concurrency Caching With ETag GET /customers/1 Accept: application/xml HTTP/1.1 200 OK Content-type: application/xml Cache-Control: private, no-store, max-age=600 Etag: 123456789 <customer id=1>.</customer> GET /customers/1 Accept: application/xml If-None-Match: 123456789 HTTP/1.1 304 Not Modified
  • 38. Caching & Concurrency Conditional Updates GET /customers/1 Accept: application/xml HTTP/1.1 200 OK Content-type: application/xml Cache-Control: private, no-store, max-age=600 Etag: 123456789 <customer id=1>.</customer> PUT /customers/1 Accept: application/xml If-None-Match: 123456788 HTTP/1.1 412 Precondition Failed
  • 39. Caching & Concurrency JAX-RS CacheControl も Abstraction for Cache-Control header EntityTag も Abstraction for entity tag Request も evaluatePreconditions(EntityTagtag) も evaluatePreconditions(Date date) も Return non-null builder
  • 40. Caching & Concurrency Spring Servlet Filter も ShallowEtagHeaderFilter も Generate MD5 hash of the response も Automatically add Etag header も Detect If-None-Match and take action も Not flexible
  • 41. Resource Representation Support Scores Feature JAX-RS Spring Caching 5.0 4.5 Concurrency Control 5.0 4.5
  • 42. Securing RESTful web services APIs Authentication も Basicauthentication password is in Base64 も Digest authentication secure MD5 hashes Authorization も Assign roles to users API interact with servlet & J2EE も Setup in web.xml
  • 43. Securing RESTful web services APIs JAX-RS Annotation Security @Path("/customers") @RolesAllowed(ADMIN, CUSTOMER_REP}) public class CustomerResource { @RolesAllowed(ADMIN) @POST @Consumes("application/xml") public Response createCustomer(InputStream is) {} @PermitALL @GET @Path("{id}") @Produces("application/xml") public StreamingOutput getCustomer(@PathParam("id") int id) {} }
  • 44. Securing RESTful web services APIs JAX-RS Programmatic Security @Path("/customers") public class CustomerResource { @POST @Consumes("application/xml") public Response createCustomer(Customer customer, @Context SecurityContext sc) { System.out.println(User: + sc.getUserPrincipal().getName()); if (!sc.isUserInRole(ADMIN)) { // return 401 } } } Thin wrapper on HTTPServletRequest Security
  • 45. Securing RESTful web services APIs Spring Programmatic Security @RequestMapping("/customers") public class CustomerResource { @RequestMapping(method = RequestMethod.POST, headers="Content-Type=application/xml) public ResponseEntity<Customer> createCustomer(Customer customer, HttpServletRequest request) { if (!request.isUserInRole(ADMIN)) { // return 401 } } }
  • 46. Resource Representation Support Scores Feature JAX-RS Spring Security 5.0 5.0
  • 47. RESTful Client Library Goals も Make it easy to work with Restful web services も Work at Java object level Jersey Client も Notpart of JAX-RS も HTTPURLConnection, HTTPClient も Work with MessageBodyReader and MessageBodyWriter Part of SpringFramework RestTemplate も HTTPURLConnection,HTTPClient も Work with HttpMessageConverter
  • 48. RESTful Client Library Scores Feature JAX-RS Spring RESTful Client Library 0 5.0 Each JAX-RS implementation provides their own client library
  • 49. Summary JAX-RS ~ = Spring
  • 50. Q &A