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();
}
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
Doesn’t 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);
……
}
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
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