ion Spring MVC and JAX-RS (InfoQ)

10
Article A Comparison of Spring MVC and JAX-RS Posted by Rossen Stoyanchev on Feb 10, 2010 Community Java Topics Web Services , Web Frameworks Tags Spring MVC , JAX-RS Introduction Over the past few years REST has become an important concept influencing the design of web frameworks, web protocols and applications. If you haven't been exposed to it, see this brief introduction among many others you can find. RelatedVendorContent Unix, Linux Uptime & Reliability Increase While Patch Management Woes Plague Windows (Yankee Group) Comparing WebLogic, WebSphere, Oracle, and Open Source Application Servers Regaining control of the data centre The 5 Mandates of Software Development Teams - Presto Manifesto JBoss versus IBM WebSphere: Cost, Performance, Eciency, Innovation (IBM wins) Related Sponsor Dynamic Application Infrastructure delivers the innovation, performance and scalability to build, deploy and manage all types of highly robust applications. The ever growing importance of REST is not surprising considering the need for companies to expose web APIs that should be as simple and as deeply rooted in the architecture of the web as can be. Rich browser clients communicating via Ajax also seek much of the same. And there is no reason why any web application can't benefit from the architectural principles that have helped to scale the world wide web. JAX-RS (JSR 311) is the Java API for RESTful Web Services. JAX-RS was created with the participation of Roy Fielding who defined REST in his thesis . It provides those seeking to build RESTful web services an alternative to JAX-WS (JSR-224). There are currently 4 JAX-RS implementations available, all of which provide support for using Spring. Jersey is the reference implementation and the one used in this article. If you're a developer working with Spring you may be wondering (or you may have been asked) how Spring MVC compares to JAX-RS? Furthermore, if you have an existing Spring MVC application that uses the controller class hierarchy (SimpleFormController and friends), you may not be aware of the comprehensive REST support now available in Spring MVC. This article will walk you through the REST features available in Spring 3 and will relate them to JAX-RS. Hopefully the exercise will help you to understand the similarities and the dierences between the two programming models. Before starting out, it may be helpful to point out that JAX-RS targets the development of web services (as opposed to HTML web applications) while Spring MVC has its roots in web application development. Spring 3 adds comprehensive REST support for both web applications and web services. This article however will focus on features relating to the development of web services. I believe this approach will make it easier to discuss Spring MVC in the context of JAX-RS. A second note to make is that the REST features we'll be discussing are a part of the Spring Framework and are a continuation of the existing the Spring MVC programming model. Hence there is no "Spring REST framework" as you might be tempted to say. It's just Spring and Spring MVC. What this practically means is that if you have an existing Spring application you can expect to be able to use Spring MVC both for creating an HTML web layer and a RESTful web services layer. About The Code Snippets The code snippets shown throughout the article assume a simple domain model with two JPA-annotated entities named Account and Portfolio where an Account has many Portfolios. The persistence layer is configured with Spring and consists of a JPA repository implementation for retrieving and persisting entity instances. Jersey and Spring MVC will be used to build a web services layer for servicing client requests by calling the underlying Spring-managed application. Bootstrap And Wire The Web Layer We will assume the use of Spring for dependency injection in both the Spring MVC and the JAX-RS scenarios. The Spring MVC DispatcherServlet and the Jersey SpringServlet will delegate requests to Spring-managed REST-layer components (controllers or resources) that will in turn be wired with either business or persistence components as follows: Both Jersey and Spring MVC will rely on Spring's ContextLoaderListener to load business and persistence components such as the JpaAccountRepository: <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:META-INF/spring/module-config.xml </param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> The ContextLoaderListener can be used in the context of any web or REST framework. Set Up Spring-Managed JAX-RS Resources In Jersey Jersey provides support for using Spring in the REST layer. It can be enabled in two simple steps (actually three if you include adding the build dependency on the maven artifact com.sun.jersey.contribs:jersey-spring). InfoQ: A Comparison of Spring MVC and JAX-RS http://www.infoq.com/articles/spr... 09.03.10 10:51 1 of 10

Transcript of ion Spring MVC and JAX-RS (InfoQ)

Page 1: ion Spring MVC and JAX-RS (InfoQ)

Article

A Comparison of Spring MVC and JAX-RSPosted by Rossen Stoyanchev on Feb 10, 2010Community Java Topics Web Services , Web Frameworks Tags Spring MVC , JAX-RS

Introduction

Over the past few years REST has become an important concept influencing the design of web frameworks, web protocols and applications. If you haven'tbeen exposed to it, see this brief introduction among many others you can find.

RelatedVendorContent

Unix, Linux Uptime & Reliability Increase While Patch Management Woes Plague Windows (Yankee Group)

Comparing WebLogic, WebSphere, Oracle, and Open Source Application Servers

Regaining control of the data centre

The 5 Mandates of Software Development Teams - Presto Manifesto

JBoss versus IBM WebSphere: Cost, Performance, Efficiency, Innovation (IBM wins)

Related Sponsor

Dynamic Application Infrastructure delivers the innovation, performance and scalability to build, deploy and manage all types of highly robustapplications.

The ever growing importance of REST is not surprising considering the need for companies to expose web APIs that should be as simple and asdeeply rooted in the architecture of the web as can be. Rich browser clients communicating via Ajax also seek much of the same. And there is noreason why any web application can't benefit from the architectural principles that have helped to scale the world wide web.

JAX-RS (JSR 311) is the Java API for RESTful Web Services. JAX-RS was created with the participation of Roy Fielding who defined REST in his thesis. It provides those seeking tobuild RESTful web services an alternative to JAX-WS (JSR-224). There are currently 4 JAX-RS implementations available, all of which provide support for using Spring. Jersey isthe reference implementation and the one used in this article.

If you're a developer working with Spring you may be wondering (or you may have been asked) how Spring MVC compares to JAX-RS? Furthermore, if you have an existingSpring MVC application that uses the controller class hierarchy (SimpleFormController and friends), you may not be aware of the comprehensive REST support now available inSpring MVC.

This article will walk you through the REST features available in Spring 3 and will relate them to JAX-RS. Hopefully the exercise will help you to understand the similarities andthe differences between the two programming models.

Before starting out, it may be helpful to point out that JAX-RS targets the development of web services (as opposed to HTML web applications) while Spring MVC has its roots inweb application development. Spring 3 adds comprehensive REST support for both web applications and web services. This article however will focus on features relating to thedevelopment of web services. I believe this approach will make it easier to discuss Spring MVC in the context of JAX-RS.

A second note to make is that the REST features we'll be discussing are a part of the Spring Framework and are a continuation of the existing the Spring MVC programmingmodel. Hence there is no "Spring REST framework" as you might be tempted to say. It's just Spring and Spring MVC. What this practically means is that if you have an existingSpring application you can expect to be able to use Spring MVC both for creating an HTML web layer and a RESTful web services layer.

About The Code Snippets

The code snippets shown throughout the article assume a simple domain model with two JPA-annotated entities named Account and Portfolio where an Account has manyPortfolios. The persistence layer is configured with Spring and consists of a JPA repository implementation for retrieving and persisting entity instances. Jersey and Spring MVCwill be used to build a web services layer for servicing client requests by calling the underlying Spring-managed application.

Bootstrap And Wire The Web Layer

We will assume the use of Spring for dependency injection in both the Spring MVC and the JAX-RS scenarios. The Spring MVC DispatcherServlet and the Jersey SpringServlet willdelegate requests to Spring-managed REST-layer components (controllers or resources) that will in turn be wired with either business or persistence components as follows:

Both Jersey and Spring MVC will rely on Spring's ContextLoaderListener to load business and persistence components such as the JpaAccountRepository:

<context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:META-INF/spring/module-config.xml </param-value></context-param>

<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class></listener>

The ContextLoaderListener can be used in the context of any web or REST framework.

Set Up Spring-Managed JAX-RS Resources In Jersey

Jersey provides support for using Spring in the REST layer. It can be enabled in two simple steps (actually three if you include adding the build dependency on the maven artifactcom.sun.jersey.contribs:jersey-spring).

InfoQ: A Comparison of Spring MVC and JAX-RS

http://www.infoq.com/articles/spr... 09.03.10 10:51 1 of 10

Page 2: ion Spring MVC and JAX-RS (InfoQ)

Step one: add the following to your web.xml to ensure JAX-RS root resources can be created with Spring:

<servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class> com.sun.jersey.spi.spring.container.servlet.SpringServlet </servlet-class></servlet>

<servlet-mapping> <servlet-name>Jersey Web Application</servlet-name> <url-pattern>/resources/*</url-pattern></servlet-mapping>

Step two: declare root JAX-RS resource classes with some Spring and some JAX-RS annotations:

@Path("/accounts/")@Component@Scope("prototype")public class AccountResource {

@Context UriInfo uriInfo;

@Autowired private AccountRepository accountRepository;

}

The following is a description of the annotations:@Component declares AccountResource as a Spring bean.@Scope makes it a prototype Spring bean that's instantiated every time it is used (i.e. on each request).@Autowired requests a reference to an AccountRepository, which Spring will provide.@Path is a JAX-RS annotation that declares AccountResource as a "root" JAX-RS resource.@Context is also a JAX-RS annotation requesting the injection of the request-specific UriInfo object.

JAX-RS has the notion of "root" resources (marked with @Path) and sub-resources. In the example above AccountResource is a root resource that handles paths starting with"/accounts/". Methods within AccountResource like getAccount() need only declare paths relative to the type-level path:

@Path("/accounts/")@Component@Scope("prototype")public class AccountResource {

@GET @Path("{username}") public Account getAccount(@PathParam("username") String username) {

}

}

The path to "/accounts/{username}" where username is a path parameter and can take the value of any user name for a given account, will be handed to the getAccount()method.

Root resources are instantiated by the JAX-RS runtime (Spring in this case). Sub-resources on the other hand are instantiated by the application. For example to handle requestsfor "/accounts/{username}/portfolios/{portfolioName}", the AccountResource, as identified by the leading portion of the path ("/accounts"), will create an instance of asub-resource to which the request will be delegated:

@Path("/accounts/")@Component@Scope("prototype")public class AccountResource {

@Path("{username}/portfolios/") public PortfolioResource getPortfolioResource(@PathParam("username") String username) { return new PortfolioResource(accountRepository, username, uriInfo); }

}

PortfolioResource itself is declared without annotations and will have all its dependencies passed down by the parent resource:

public class PortfolioResource {

private AccountRepository accountRepository; private String username; private UriInfo uriInfo;

public PortfolioResource(AccountRepository accountRepository, String username, UriInfo uriInfo) { this.accountRepository = accountRepository; this.username = username; this.uriInfo = uriInfo; }

}

Root and sub-resources in JAX-RS set up a processing chain that involves multiple resources:

InfoQ: A Comparison of Spring MVC and JAX-RS

http://www.infoq.com/articles/spr... 09.03.10 10:51 2 of 10

Page 3: ion Spring MVC and JAX-RS (InfoQ)

Keep in mind resource classes are web service layer components and should remain focused on web service related processing such as translating input, preparing theresponse, setting the response code, etc. It's also worth pointing out that the practicalities of separating web services logic from business logic often necessitate wrappingbusiness logic into a single method that serves as a transaction boundary.

Setting Up Spring MVC @Controller Classes

For Spring MVC we'll set up the DispatcherServlet with a contextConfigLocation parameter that points to Spring MVC configuration:

<servlet> <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring/*.xml </param-value> </init-param></servlet>

To start off the annotation based programming model in Spring MVC (@MVC) requires only a small amount of configuration. This component-scan element tells Spring where tofi nd @Controller-annotated classes.

<context:component-scan base-package="org.springframework.samples.stocks" />

After that we can declare an AccountController as follows:

@Controller@RequestMapping("/accounts")public class AccountController {

@Autowired private AccountRepository accountRepository;

}

The @RequestMapping annotation maps this controller to all requests starting with "/accounts". Methods in AccountController like getAccount() need only declare paths relativeto that:

@RequestMapping(value = "/{username}", method = GET)public Account getAccount(@PathVariable String username) {

}

Spring MVC does not have the notion of root resources and sub-resources. Hence every controller is managed by Spring and not by the application:

@Controller@RequestMapping("/accounts/{username}/portfolios")public class PortfolioController {

@Autowired private AccountRepository accountRepository;

}

Requests for "/accounts/{username}/portfolios" are delegated directly to the PortfolioController without any involvement from the AccountController. It's worth pointing out thatthis request could also be handled directly in the AccountController thereby removing the need for a PortfolioController.

Web Layer Component Scope

In JAX-RS, AccountResource was declared with per-request semantics. This is the default recommendation of JAX-RS. It enables the injection and storing of request-specificdata (request headers, query parameters, cookie values) in the resource class itself. This applies to root-level resources, which are managed by JAX-RS. Sub-resources areinstantiated by the application and do not benefit directly from this.

In Spring MVC controllers are always created as singletons. They accept request-specific data as method arguments, which is also an option in JAX-RS where resources can alsobe created as singletons.

Mapping Requests To Methods

Next we'll take a look at how Spring MVC and JAX-RS map requests to methods. Both @Path and @RequestMapping support extracting path variables from the URL:

@Path("/accounts/{username}")@RequestMapping("/accounts/{username}")

Both frameworks also support the use of regular expressions for extracting path variables:

@Path("/accounts/{username:.*}")@RequestMapping("/accounts/{username:.*}"

Spring MVC's @RequestMapping allows matching requests based on the presence or absence of query parameters:

@RequestMapping(parameters="foo")@RequestMapping(parameters="!foo")

or based on the value of a query parameter:

@RequestMapping(parameters="foo=123")

@RequestMapping also allows matching requests based on presence (or absence) of headers:

@RequestMapping(headers="Foo-Header")@RequestMapping(headers="!Foo-Header")

or based on the value of a header:

@RequestMapping(headers="content-type=text/*")

Working With Request Data

HTTP requests contain data that applications need to extract and work with. That includes HTTP headers, cookies, query string parameters, form parameters, or more extensivedata sent in the body of the request (XML, JSON, etc.) In RESTful applications the URL itself can also carry valuable information such as which resource is being accessed via path

InfoQ: A Comparison of Spring MVC and JAX-RS

http://www.infoq.com/articles/spr... 09.03.10 10:51 3 of 10

Page 4: ion Spring MVC and JAX-RS (InfoQ)

parameters or what content type is needed via file extensions (.html, .pdf) The HttpServletRequest provides low level access to all that but doing so can be quite verbose.

Request Parameters, Cookies, and HTTP Headers

Spring MVC and JAX-RS have annotations for extracting such HTTP request values:

@GET @Pathpublic void foo(@QueryParam("q") String q, @FormParam("f") String f, @CookieParam("c") String c, @HeaderParam("h") String h, @MatrixParam("m") m) { // JAX-RS}

@RequestMapping(method=GET)public void foo(@RequestParam("q") String q, @CookieValue("c") String c, @RequestHeader("h") String h) { // Spring MVC}

The above annotations are very similar except that JAX-RS supports the extraction of matrix parameters and has separate annotations for query string and form parameters.Matrix parameters are not commonly seen. They're similar to query string parameters but applied to specific path segments (e.g. GET /images;name=foo;type=gif). Formparameters will be discussed shortly.

JAX-RS allows placing the above annotations on fields and setters assuming a resource is declared with per-request scope.

Spring MVC has a space-saving feature that allows omitting names from the above annotations as long as the names match to the Java argument names. For example a requestparameter called "q" requires the method argument to be called "q" as well:

public void foo(@RequestParam String q, @CookieValue c, @RequestHeader h) {

}

This is rather handy in method signatures that are already stretched long due to the use of annotations on every argument. Also bear in mind this feature requires that codeisn't compiled without debugging symbols.

Type Conversion And Formatting Of HTTP Request Values

HTTP request values (headers, cookies, parameters) are invariably String-based and that requires parsing.

JAX-RS handles parsing of request data by looking for a valueOf() method or a constructor accepting a String in the custom target type. To be precise JAX-RS supports thefollowing types of annotated method arguments including path variables, request parameters, HTTP header values, and cookies:

Primitive types.Types that have a constructor that accepts a single String argument.Types that have a static method named valueOf with a single String argument.List<T>, Set<T>, or SortedSet<T>, where T satisfies 2 or 3 above.

In Spring 3 all of the above is supported as well. In addition, Spring 3 provides a new type conversion and formatting mechanism that can be annotation-driven.

Form Data

As mentioned above JAX-RS makes a distinction between query string parameters and form parameters. While Spring MVC has just one @RequestParam, it also provides a databinding mechanism for dealing with form input that Spring MVC users will be familiar with.

For example one option to process a form submitting 3 pieces of data is to declare a method with 3 arguments:

@RequestMapping(method=POST)public void foo(@RequestParam String name, @RequestParam creditCardNumber, @RequestParam expirationDate) { Credit card = new CreditCard(); card.setName(name); card.setCreditCardNumber(creditCardNumber); card.setExpirationDate(expirationDate);

}

However as the size of the form grows this approach becomes impractical. With data binding, a form object of an arbitrary structure including nested data (billing address,mailing address, etc.) can be created, populated and passed in by Spring MVC:

@RequestMapping(method=POST)public void foo(CreditCard creditCard) { // POST /creditcard/1 // name=Bond // creditCardNumber=1234123412341234 // expiration=12-12-2012}

Form processing is important for working with web browsers. Web service clients on the other hand are more likely to submit XML or JSON-formatted data in the body of therequest.

Processing Request Body Data

Both Spring MVC and JAX-RS automate the processing of request body data:

@POSTpublic Response createAccount(Account account) { // JAX_RS}

@RequestMapping(method=POST)public void createAccount(@RequestBody Account account) { // Spring MVC}

Request Body Data In JAX-RS

In JAX-RS, entity providers of type MessageBodyReader are responsible for converting request body data. JAX-RS implementations are required to have a JAXBMessageBodyReader. Custom MessageBodyReader implementations annotated with @Provider may also be provided.

Request Body Data in Spring MVC

In Spring MVC you add @RequestBody to a method argument if you want it to be initialized from request body data. This is in contrast to initialization from form parameters aswas shown earlier.

In Spring MVC, classes of type HttpMessageConverter are responsible for converting request body data. A marshalling Spring OXM HttpMessageConverter is provided out of the

InfoQ: A Comparison of Spring MVC and JAX-RS

http://www.infoq.com/articles/spr... 09.03.10 10:51 4 of 10

Page 5: ion Spring MVC and JAX-RS (InfoQ)

box. It enables use of JAXB, Castor, JiBX, XMLBeans, or XStream. There is also a Jackson HttpMessageConverter for use with JSON.

HttpMessageConverter types are registered with the AnnotationMethodHandlerAdapter, which adapts incoming requests to Spring MVC @Controllers. Here is the configuration:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" > <property name="messageConverters" ref="marshallingConverter"/></bean>

<bean id="marshallingConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"> <constructor-arg ref="jaxb2Marshaller"/> <property name="supportedMediaTypes" value="application/vnd.stocks+xml"/></bean>

<oxm:jaxb2-marshaller id="jaxb2Marshaller"/>

The following diagram illustrates this configuration:

The new mvc custom namespace in Spring 3 automates the above configuration. All you need to do is add:

<mvc:annotation-driven />

That will register a converter for reading and writing XML if JAXB is on the classpath and a converter for reading and writing JSON if Jackson is on the classpath.

Preparing The Response

A typical response may involve selecting the response code, setting HTTP response headers, adding data to the body of the response, as well as dealing with exceptions.

Setting Response Body Data With JAX-RS

To add data to the body of the response in JAX-RS, you simply return the object from the resource method:

@GET@Path("{username}")public Account getAccount(@PathParam("username") String username) { return accountRepository.findAccountByUsername(username);}

JAX-RS will find an entity provider of type MessageBodyWriter that can convert the object to the required content type. JAX-RS implementations are required to have a JAXBMessageBodyWriter. Custom MessageBodyWriter implementations annotated with @Provider may also be provided.

Setting Response Body Data With Spring MVC

In Spring MVC a response is prepared through a view resolution process. This allows selecting from a range of view technologies. When working with web service clients,however, it may be more natural to bypass the view resolution process and use the object returned from the method :

@RequestMapping(value="/{username}", method=GET)public @ResponseBody Account getAccount(@PathVariable String username) { return accountRepository.findAccountByUsername(username);}

When a controller method or (its return type) is annotated with @ResponseBody, its return value is processed with an HttpMessageConverter and then used to set the responseof the body. The same set of HttpMessageConverter types used for request body arguments is also used for the body of the response. Hence no further configuration isrequired.

Status Codes & Response Headers

JAX-RS provides a chained API for building a response:

@PUT @Path("{username}")public Response updateAccount(Account account) { // ... return Response.noContent().build(); // 204 (No Content)}

This can be used in conjunction with a UriBuilder to create links to entities for the Location response header:

@POSTpublic Response createAccount(Account account) { // ... URI accountLocation = uriInfo.getAbsolutePathBuilder().path(account.getUsername()).build(); return Response.created(accountLocation).build();}

The uriInfo used above is either injected into a root resources (with @Context) or passed down from parent to sub-resource. It allows appending to the path of the currentrequest.

Spring MVC provides an annotation for setting the response code:

InfoQ: A Comparison of Spring MVC and JAX-RS

http://www.infoq.com/articles/spr... 09.03.10 10:51 5 of 10

Page 6: ion Spring MVC and JAX-RS (InfoQ)

@RequestMapping(method=PUT)@ResponseStatus(HttpStatus.NO_CONTENT)public void updateAccount(@RequestBody Account account) { // ...}

To set a location header you work directly with the HttpServletResponse objects:

@RequestMapping(method=POST)@ResponseStatus(CREATED)public void createAccount(@RequestBody Account account, HttpServletRequest request,

HttpServletResponse response) { // ... String requestUrl = request.getRequestURL().toString(); URI uri = new UriTemplate("{requestUrl}/{username}").expand(requestUrl, account.getUsername()); response.setHeader("Location", uri.toASCIIString());}

Exception Handling

JAX-RS allows resource methods to throw exceptions of type WebApplicationException, which contain a Response. The following example code translates a JPANoResultException to the Jersey-specific NotFoundException, which causes the return of a 404 error:

@GET@Path("{username}")public Account getAccount(@PathParam("username") String username) { try { return accountRepository.findAccountByUsername(username); } catch (NoResultException e) { throw new NotFoundException(); }}

Instances of WebApplicationException encapsulate the logic necessary to produce a specific response but the exceptions must be caught in each individual resource classmethod.

Spring MVC allows defining controller-level methods for dealing with exceptions:

@Controller@RequestMapping("/accounts")public class AccountController {

@ResponseStatus(NOT_FOUND) @ExceptionHandler({NoResultException.class}) public void handle() { // ... }}

If any controller methods throw JPA's NoResultException, the above handler method will be invoked to handle it and return a 404 error. That allows each controller to deal withexceptions as it sees fit from a single place.

Summary

Hopefully this article has helped you to see how Spring MVC can be used for building RESTful web services and how that compares to the JAX-RS programming model.

If you're a Spring MVC user you're probably developing HTML web applications. REST concepts apply to web services and to web applications alike especially in rich clientinteractions. In addition to the features discussed in this article, Spring 3 also adds support for RESTful web applications. Here is a partial list: a new JSP custom tag for buildingURLs from URL templates, a servlet filter for simulating form submissions based on HTTP PUT and DELETE, a ContentTypeNegotiatingViewResolver for automating view selectionbased on content type, new view implementations, and more. Last but not least is the updated and much improved Spring documentation.

About the Author

Rossen Stoyanchev is a senior consultant at SpringSource. In his career he has worked on a trading application, an investment accounting system and an e-commerce webapplication, amongst others. Within SpringSource Stoyanchev focuses on web technologies including consulting, training, and content development of the "Rich-WebDevelopment With Spring" course, which enables attendees to become certified Spring web application developers.

Bookmark digg+, reddit+, del.icio.us+, dzone+, facebook+ slashdot+

Watch Thread Reply24 comments

Nice article by Lars Tackmann Posted Feb 10, 2010 7:26 AMRe: Nice article by Rossen Stoyanchev Posted Feb 10, 2010 8:00 AM

What about content-negotiation? by Ralph Winzinger Posted Feb 10, 2010 9:33 AMRe: What about content-negotiation? by Rossen Stoyanchev Posted Feb 10, 2010 10:34 AM

Re: What about content-negotiation? by Solomon Duskis Posted Feb 10, 2010 1:08 PMRe: What about content-negotiation? by Bill Burke Posted Feb 11, 2010 3:55 PM

Re: What about content-negotiation? by Bill de hÓra Posted Feb 11, 2010 5:55 PMRe: What about content-negotiation? by Bill Burke Posted Feb 12, 2010 11:25 AM

hypermedia media aware resources by pradeep partha Posted Feb 10, 2010 2:50 PMRe: hypermedia media aware resources by Rossen Stoyanchev Posted Feb 11, 2010 7:05 AM

Re: hypermedia media aware resources by Solomon Duskis Posted Feb 11, 2010 3:43 PMRe: hypermedia media aware resources by Rossen Stoyanchev Posted Feb 12, 2010 6:02 AM

Re: What about content-negotiation? by Jon Hill Posted Feb 17, 2010 3:47 AMJSR 311 by Alexis Moussine-Pouchkine Posted Feb 11, 2010 3:02 AM

Re: JSR 311 by Ryan Slobojan Posted Feb 11, 2010 9:18 AMSpring MVC and exceptions by Peter Coppens Posted Feb 11, 2010 7:10 AM

Re: Spring MVC and exceptions by Rossen Stoyanchev Posted Feb 11, 2010 10:32 AMRe: Spring MVC and exceptions by Peter Coppens Posted Feb 11, 2010 10:45 AM

Re: Spring MVC and exceptions by Rossen Stoyanchev Posted Feb 11, 2010 10:52 AMSeemless EE6 integration by Bill Burke Posted Feb 11, 2010 3:49 PM

Re: Seemless EE6 integration by Greg Beams Posted Feb 11, 2010 5:32 PMJAX-RS Exception Handling by Greg Beams Posted Feb 11, 2010 5:20 PM

Re: JAX-RS Exception Handling by Rossen Stoyanchev Posted Feb 12, 2010 6:56 AMInteresting and Impressive by george naing Posted Feb 16, 2010 11:27 PM

InfoQ: A Comparison of Spring MVC and JAX-RS

http://www.infoq.com/articles/spr... 09.03.10 10:51 6 of 10

Page 7: ion Spring MVC and JAX-RS (InfoQ)

Sort by date descending

Great article and a fair comparison. However note that the following statement is really a design choice:

"PortfolioResource itself is declared without annotations and will have all its dependencies passed down by the parent resource"

You can also have JAX-RS inject/proxy child resources (and thus gain full access to Spring DI in these) by using a ResourceContext E.g. the code:

@Path("{username}/portfolios/")public PortfolioResource getPortfolioResource(@PathParam("username") String username) {return new PortfolioResource(accountRepository, username, uriInfo);}

becomes

@Path("{username}/portfolios/")public PortfolioResource getPortfolioResource(@PathParam("username") String username) {PortfolioResource portfolioResource = resourceContext.getResource(PortfolioResource.class);portfolioResource.setUsername(username);return portfolioResource;}

this way portfolioResource is still proxied and thus can take full advantage of the Spring DI/Aspect hoopla.

Reply

Thanks Lars, good to know!

Reply

With JAX-RS it's very easy to do content-negotiation based on the 'produces'-annotation. When I tried an early version of Spring's REST-support, this was not impossible, butactually quite difficult to achieve. If that is still the case, you should point it out, since this is an important part of the REST paradigm.

Reply

Ralph, good point! I think you'll find content-negotiation quite straight-forward in Spring MVC. Much like in JAX-RS, if you don't specify a content type for a resource, SpringMVC will try to locate a matching HttpConverter. This means the code samples above don't need to change. You just need to have the necessary HttpConverters configured.Furthermore, since configuration is Spring-based you can match to application mime types (e.g. "application/vnd.stocks+xml") like in the sample code above.

JAX-RS has @Produces and @Consumes that allow you to limit the content types you can support. You can also do this in Spring MVC by matching on headers in your@RequestMapping annotation.

Reply

Great stuff Rossen. This post definitely filled in some knowledge gaps that I had with Spring MVC REST.

Spring MVC REST annotations caught up, and may have surpassed the JAX-RS annotations. I'm looking forward to new and exciting features that a single entity likeSpringSource can pump out; a JSR committee can't have as quick feature turn around.

Reply

Nice article and it touched key annotations for REST support in Spring MVC.

Is there any plan for supporting hypermedia resources(HATEOAS) similar to Restfulie as explained in www.infoq.com/news/2009/11/restfulie-hypermedia...

Since Spring support for REST is not implementing jax-rs it gives the benefit of adding more features than what current jax-rs spec supports.

Reply

Small correction : JAX-RS is 311, not 313.

Reply

Is there any plan for supporting hypermedia resources(HATEOAS) similar to Restfulie as explained in www.infoq.com/news/2009/11/restfulie-hypermedia...

Nice article

Feb 10, 2010 7:26 AM by Lars Tackmann

Re: Nice article

Feb 10, 2010 8:00 AM by Rossen Stoyanchev

What about content-negotiation?

Feb 10, 2010 9:33 AM by Ralph Winzinger

Re: What about content-negotiation?

Feb 10, 2010 10:34 AM by Rossen Stoyanchev

Re: What about content-negotiation?

Feb 10, 2010 1:08 PM by Solomon Duskis

hypermedia media aware resources

Feb 10, 2010 2:50 PM by pradeep partha

JSR 311

Feb 11, 2010 3:02 AM by Alexis Moussine-Pouchkine

Re: hypermedia media aware resources

Feb 11, 2010 7:05 AM by Rossen Stoyanchev

InfoQ: A Comparison of Spring MVC and JAX-RS

http://www.infoq.com/articles/spr... 09.03.10 10:51 7 of 10

Page 8: ion Spring MVC and JAX-RS (InfoQ)

Hi Pradeep, thanks for the pointer to that article. The creation of links is not simple and is not deemed simple. There are multiple ways to do links and to describe what to dowith them, which it makes it difficult for a framework to generalize. Also required links are often not necessarily based on the URI of the current resource. See this forexample.

That said you can certainly expect to see incremental improvements in the ability to work with links both client and server side.

Reply

A few weeks ago I went through converting a prototype Jersey app to spring mvc. If just this article would have been available then :). If one has Spring in the stack anyway,that seemed like the logical thing to do and in general it turned out very well.

One thing I found difficult to deal with is exception handing in Spring MVC. I was not able to get a message converter invoked on the return of the exception method. Theonly way I could get this going was through a view, but that seems overkill in the context of a webservices client.

Peter

Reply

Hi Alexis,

Thanks for the catch - this has been updated in the article above.

Ryan SlobojanChief Editor, InfoQ.com

Reply

One thing I found difficult to deal with is exception handing in Spring MVC. I was not able to get a message converter invoked on the return of the exception method.The only way I could get this going was through a view, but that seems overkill in the context of a webservices client.

Hi Peter, I think this JIRA ticket is referring to the same issue. You could vote on it. It appears the developer who reported it has already tracked it provided a patch.

Reply

The JIRA ticket link seems to point to your blog. Would you happen to have some id or actual jira link? I would happily go and vote for it

Reply

The JIRA ticket link seems to point to your blog. Would you happen to have some id or actual jira link? I would happily go and vote for it

Sorry, I didn't mean to link to that (may be Ryan can edit my comment and correct the link)? This is the actual link to SPR-693.

Reply

There are quite a few components to getting HATEOAS to work. From a framework standpoint:

1) the first step, IMHO, is to be allow the user to easily construct/manage the generation of URLs based on some domain object.

2) The next step is using that ease of URL generation as part of the marshalling process.

n) Sometime after that, adding semantic markup to provide a "meaning" of that URL

n+1) generating URLs based on a notion of workflow/"action" (payment/cancellation) there's generating URLs Adding semantics to those URLs (as Restfullie does based onJim Webber's How to GET a cup of cofee)

I'd like to illustrate #1 and #2:

For example, let's say you have an Artist & Soundtrack domain. Artists and soundtracks have a relationship to each other. Those relationships should be expressed throughsome kind of linking mechanism. If you access /artist/1234, you should get links to all of their soundtracks. How can you easily convert a Soundtrack object to a URL? That'sthe "domain" of the framework...

Reply

Spring MVC and exceptions

Feb 11, 2010 7:10 AM by Peter Coppens

Re: JSR 311

Feb 11, 2010 9:18 AM by Ryan Slobojan

Re: Spring MVC and exceptions

Feb 11, 2010 10:32 AM by Rossen Stoyanchev

Re: Spring MVC and exceptions

Feb 11, 2010 10:45 AM by Peter Coppens

Re: Spring MVC and exceptions

Feb 11, 2010 10:52 AM by Rossen Stoyanchev

Re: hypermedia media aware resources

Feb 11, 2010 3:43 PM by Solomon Duskis

Seemless EE6 integration

Feb 11, 2010 3:49 PM by Bill Burke

InfoQ: A Comparison of Spring MVC and JAX-RS

http://www.infoq.com/articles/spr... 09.03.10 10:51 8 of 10

Page 9: ion Spring MVC and JAX-RS (InfoQ)

It should be pointed ou that JAX-RS requires seemless integration with EE6. This means you don't need any of the bootstrap/initialization code in web.xml. You can just writean EJB, managed bean, CDI bean, or pojo, put the classes within your WAR and it just works. JAX-RS classes are automatically scanned and deployed.

Reply

Great stuff Rossen. This post definitely filled in some knowledge gaps that I had with Spring MVC REST.

Spring MVC REST annotations caught up, and may have surpassed the JAX-RS annotations. I'm looking forward to new and exciting features that a single entity likeSpringSource can pump out; a JSR committee can't have as quick feature turn around.

I think that's a bit unfair. JAX-RS is a specification not a product. I'm sure JAX-RS implementations like Jersey, RESTEasy, and CXF can innovate just as fast, probably faster,than anything SpringSource comes up with. The difference is of course, that these projects will bring back their innovations to a future JAX-RS revision so that all can shareand so that such an important API isn't controlled by one commercial company.

IMO, its just sad that SpringSource has the inherent need to do their own thing for as something as trivial as JAX-RS.

Reply

For exception mapping, it's possible to use something similar to the following code in JAX-RS.

@Providerpublic class NoResultExceptionMapper implements ExceptionMapper<NoResultException> { public Response toResponse(NoResultException e) { Response.status(Response.Status.NOT_FOUND).build(); }}

</noresultexception>

Reply

I just tried this with my JAX-RS webapp in glassfish v3. Didn't work. Is there some catch that I need to be aware of?

Reply

"I'm sure JAX-RS implementations like Jersey, RESTEasy, and CXF can innovate just as fast, probably faster, than anything SpringSource comes up with."

Right. For example, Jersey provides a Form object, implicit views, and a client.

In general, I think JAX-RS does a better job of conneg, media type, and exception mapping handling than SpringMVC3. It will be interesting to see how SpringMVC3 evolves.And if all you want to do is define a REST interface onto some service code, then Jersey+Guice is light and fast way to do that.

Reply

Hi Solomon, thanks for your comments first of all.

I agree the generation of links needs to be encapsulated as much as possible. A good part of that is based on the capabilities of the underlying marshalling technology, likethe JAXB XmlAdapter you've pointed out previously. I do think a general purpose chained API for building up URI's would be helpful here.

As for the payment example in Restfulie, there are suggestions like SPR-6261 although my sense is that this is a more natural fit for Grails and Roo both of which combineknowledge of domain objects with a non-intrusive approach to adding the needed behavior.

Reply

@Greg, thanks for pointing that out.

Reply

Yeah, RESTEasy supports same kinda stuff, but additionally asynchronous HTTP, client and server caching, interceptors, and an annotation-driven client framework. I'm knowa lot of the stuff in Jersey, RESTEasy etc. will be in the next revision of the spec. IMO, specs aren't for innovation, they are for consolidation.

"I'm sure JAX-RS implementations like Jersey, RESTEasy, and CXF can innovate just as fast, probably faster, than anything SpringSource comes up with."

Right. For example, Jersey provides a Form object, implicit views, and a client.

In general, I think JAX-RS does a better job of conneg, media type, and exception mapping handling than SpringMVC3. It will be interesting to see how SpringMVC3evolves. And if all you want to do is define a REST interface onto some service code, then Jersey+Guice is light and fast way to do that.

Re: What about content-negotiation?

Feb 11, 2010 3:55 PM by Bill Burke

JAX-RS Exception Handling

Feb 11, 2010 5:20 PM by Greg Beams

Re: Seemless EE6 integration

Feb 11, 2010 5:32 PM by Greg Beams

Re: What about content-negotiation?

Feb 11, 2010 5:55 PM by Bill de hÓra

Re: hypermedia media aware resources

Feb 12, 2010 6:02 AM by Rossen Stoyanchev

Re: JAX-RS Exception Handling

Feb 12, 2010 6:56 AM by Rossen Stoyanchev

Re: What about content-negotiation?

Feb 12, 2010 11:25 AM by Bill Burke

InfoQ: A Comparison of Spring MVC and JAX-RS

http://www.infoq.com/articles/spr... 09.03.10 10:51 9 of 10

Page 10: ion Spring MVC and JAX-RS (InfoQ)

Reply

Spring site shows an impressiev array of products and services. I doubt markitecture is at play???

georgeethicminds.blogspot.com

Reply

I've recently completed a RESTful Spring MVC project. I had XML, JSON and JSP views and it wasn't entirely straight-forward as I had to avoid marshalling a fullBeanAwareBindingResult or Exception object for the JSON and XML views. I ended up using named model attributes for the JSON, XML, and Error views, which meant a littlemore configuration, but worked quite well.

Jon

Reply

InfoQ.com and all content copyright © 2006-2009 C4Media Inc. InfoQ.com hosted at Contegix, the best ISP we've ever worked with. Privacy policy

Interesting and Impressive

Feb 16, 2010 11:27 PM by george naing

Re: What about content-negotiation?

Feb 17, 2010 3:47 AM by Jon Hill

InfoQ: A Comparison of Spring MVC and JAX-RS

http://www.infoq.com/articles/spr... 09.03.10 10:51 10 of 10