This document compares the JAX-RS and Spring frameworks for building RESTful web services. It discusses key areas such as resource identifiers, request data binding, response handling, content negotiation, caching, security, and exception handling. Overall, both frameworks provide similar functionality for developing REST APIs but with some differences in their approaches and implementations. JAX-RS focuses solely on REST while Spring integrates REST capabilities into its existing MVC framework.
1 of 50
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();
}
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);
}
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
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
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
}
}
}
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