Friday, 26 September 2014

A Comparison of Spring MVC and 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 briefintroduction among many others you can find.
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 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 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).
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 requests for "/accounts/{username}/portfolios/{portfolioName}", the AccountResource, as identified by the leading portion of the path ("/accounts"), will create an instance of a sub-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:
Keep in mind resource classes are web service layer components and should remain focused on web service related processing such as translating input, preparing the response, setting the response code, etc. It's also worth pointing out that the practicalities of separating web services logic from business logic often necessitate wrapping business 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 to find @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 relative to 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 that this 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-specific data (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 are instantiated 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 also be 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 extensive data 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 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 @Path
public 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). Form parameters 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 request parameter 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 code isn'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 the following 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 data binding 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 the request.

Processing Request Body Data

Both Spring MVC and JAX-RS automate the processing of request body data:
@POST
public 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 JAXB MessageBodyReader. 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 as was 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 box. It enables use of JAXB, Castor, JiBX, XMLBeans, or XStream. There is also a JacksonHttpMessageConverter 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 JAXB MessageBodyWriter. 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 response of 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 is required.

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:
@POST
public 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 current request.
Spring MVC provides an annotation for setting the response code:
@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 JPA NoResultException 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 class method.
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 with exceptions 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 client interactions. 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 building URLs from URL templates, a servlet filter for simulating form submissions based on HTTP PUT and DELETE, a ContentTypeNegotiatingViewResolver for automating view selection based 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 web application, amongst others. Within SpringSource Stoyanchev focuses on web technologies including consulting, training, and content development of the "Rich-Web Development With Spring" course, which enables attendees to become certified Spring web application developers.

Tell us what you think

Community commentsWatch Thread
Nice articleFeb 10, 2010 06:56 by Lars Tackmann
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.
Re: Nice articleFeb 10, 2010 07:30 by Rossen Stoyanchev
Thanks Lars, good to know!
What about content-negotiation?Feb 10, 2010 09:03 by Ralph Winzinger
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, but actually 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.
Re: What about content-negotiation?Feb 10, 2010 10:04 by Rossen Stoyanchev
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, Spring MVC 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.
Re: What about content-negotiation?Feb 11, 2010 12:38 by Solomon Duskis
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 like SpringSource can pump out; a JSR committee can't have as quick feature turn around.
hypermedia media aware resourcesFeb 11, 2010 02:20 by pradeep partha
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.
JSR 311Feb 11, 2010 02:32 by Alexis Moussine-Pouchkine
Small correction : JAX-RS is 311, not 313.
Re: hypermedia media aware resourcesFeb 11, 2010 06:35 by Rossen Stoyanchev

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


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 do with 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 for example.

That said you can certainly expect to see incremental improvements in the ability to work with links both client and server side.
Spring MVC and exceptionsFeb 11, 2010 06:40 by Peter Coppens
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. The only way I could get this going was through a view, but that seems overkill in the context of a webservices client.


Peter
Re: JSR 311Feb 11, 2010 08:48 by Ryan Slobojan
Hi Alexis,

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

Ryan Slobojan
Chief Editor, InfoQ.com
Re: Spring MVC and exceptionsFeb 11, 2010 10:02 by Rossen Stoyanchev

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.
Re: Spring MVC and exceptionsFeb 11, 2010 10:15 by Peter Coppens
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
Re: Spring MVC and exceptionsFeb 11, 2010 10:22 by Rossen Stoyanchev
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.
Re: hypermedia media aware resourcesFeb 12, 2010 03:13 by Solomon Duskis
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 on Jim Webber'sHow 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 through some 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's the "domain" of the framework...
Seemless EE6 integrationFeb 12, 2010 03:19 by Bill Burke
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 write an 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.
Re: What about content-negotiation?Feb 12, 2010 03:25 by Bill Burke
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 like SpringSource 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 share and 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.
JAX-RS Exception HandlingFeb 12, 2010 04:50 by Greg Beams
For exception mapping, it's possible to use something similar to the following code in JAX-RS.
@Provider
public class NoResultExceptionMapper implements ExceptionMapper<NoResultException> {
    public Response toResponse(NoResultException e) {
        Response.status(Response.Status.NOT_FOUND).build();
    }
}

</noresultexception>
Re: Seemless EE6 integrationFeb 12, 2010 05:02 by Greg Beams
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?
Re: What about content-negotiation?Feb 12, 2010 05:25 by Bill de hÓra
"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.
Re: hypermedia media aware resourcesFeb 12, 2010 05:32 by Rossen Stoyanchev
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, like the 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 combine knowledge of domain objects with a non-intrusive approach to adding the needed behavior.
Re: JAX-RS Exception HandlingFeb 12, 2010 06:26 by Rossen Stoyanchev
@Greg, thanks for pointing that out.
Re: What about content-negotiation?Feb 12, 2010 10:55 by Bill Burke
Yeah, RESTEasy supports same kinda stuff, but additionally asynchronous HTTP, client and server caching, interceptors, and an annotation-driven client framework. I'm know a 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 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.
Interesting and ImpressiveFeb 17, 2010 10:57 by george naing
Spring site shows an impressiev array of products and services. I doubt markitecture is at play???

george
ethicminds.blogspot.com
Re: What about content-negotiation?Feb 17, 2010 03:17 by Jon Hill
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 full BeanAwareBindingResult 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 little more configuration, but worked quite well.

Jon
Spring MVC feature showcaseAug 07, 2010 07:14 by Keith Donald
The following blog compliments Rossen's article by providing a showcase sample application that demonstrates the REST capabilities of Spring MVC, among other features:

blog.springsource.com/2010/07/22/spring-mvc-3-s...
Re: Spring MVC feature showcaseMar 13, 2011 07:23 by krishna srinivasan
Good article on Spring REST implementation:
www.javabeat.net/articles/256-introduction-to-s...
Why do you think JAX-RS impl should not be used for building web appsAug 16, 2011 04:22 by Srivatsa Katta
<quote>
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.
</quote>

Hi Rossen,

Could you please eloborate the above statement, JAX-RS targets development of web services as opposed to HTML web applications.

With the features JAX-RS (impl) provides am sure one can build a rich web applications (for that matter isn't it what spring is also doing with the new annotation based controllers). 

Am keen to know what are the key aspects that you think are not well supported by any JAX-RS but a typical web framework provides. yes there are few things like interceptors, security based url routing etc. But how hard to build one on top of JAX-RS implementation ??
Re: Why do you think JAX-RS impl should not be used for building web appsAug 16, 2011 04:23 by Srivatsa Katta
However really appreciate the way you have explained the comparision between JAX-RS and Spring way of buildin restful services.
Quick toughts on both frameworksAug 12, 2014 07:34 by Snehal Masne
Jersey:

Pros: Standard API (JAX-RS)
Cons: MVC support is less richer than Spring MVC.

Spring:

Pros: Many features, many documents, active community.
Cons: Many rules to learn.


Regards,
Snehal Masne
www.techproceed.com
Love itAug 22, 2014 05:08 by Srikanth Reddy
Thanks. very nice
JAX-RS is straightAug 22, 2014 05:17 by Srikanth Reddy
No notion of controllers of using JAX_RS Jersey implementation but in spring I feel a service is a notion of both controller and a service that I'm not liking

No comments:

Post a Comment

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...