Blogs

SpringSource Blog

REST in Spring 3: @MVC

Arjen Poutsma

In the last couple of years, REST has emerged as a compelling alternative to SOAP/WSDL/WS-*-based distributed architectures. So when we started to plan our work on the next major release of Spring – version 3.0, it was quite clear to us that we had to focus on making the development of 'RESTful' Web services and applications easier. Now, what is and isn't 'RESTful' could be the topic of a whole new post all together; in this post I'll take a more practical approach, and focus on the features that we added to the @Controller model of Spring MVC.

A Bit of Background

Ok, I lied: there is some background first. If you really want to learn about the new features, feel free to skip to the next section.

For me, work on REST started about two years ago, shortly after reading the highly recommended book RESTful Web Services from O'Reilly, by Leonard Richardson and Sam Ruby. Initially, I was thinking about adding REST support to Spring Web Services, but after working a couple of weeks on a prototype, it became clear to me that this wasn't a very good fit. In particular, I found out that I had to copy most of the logic from the Spring-MVC DispatcherServlet over to Spring-WS. Clearly, this was not the way to go forward.

Around the same time we introduced the annotation-based model of Spring MVC. This model was clearly an improvement to the former, inheritance-based model. Another interesting development at that time was the development of the JAX-RS specification. My next attempt was to try and merge these two models: to try and combine the @MVC annotations with the JAX-RS annotations, and to be able to run JAX-RS applications within the DispatcherServlet. While I did get a working prototype out of this effort, the result was not satisfactory. There were a number of technical issues which I won't bore you with, but most importantly the approach felt 'clunky' and unnatural for a developer who was already used to Spring MVC 2.5.

Finally, we decided to add the RESTful functionality to features to Spring MVC itself. Obviously, that would mean that there would be some overlap with JAX-RS, but at least the programming model would be satisfactory for Spring MVC developers, both existing and new ones. Additionally, there are already three JAX-RS implementations offering Spring support (Jersey, RESTEasy, and Restlet). Adding a fourth to this list did not seem a good use of our valuable time.

RESTful features in Spring MVC 3.0

Now, enough of the background, let's look at the features!

URI Templates

A URI template is a URI-like string, containing one or more variable names. When these variables are substituted for values, the template becomes a URI. For more information, see the proposed RFC.

In Spring 3.0 M1, we introduced the use of URI templates through the @PathVariable annotation. For instance:

@RequestMapping("/hotels/{hotelId}")
public String getHotel(@PathVariable String hotelId, Model model) {
    List<Hotel> hotels = hotelService.getHotels();
    model.addAttribute("hotels", hotels);
    return "hotels";
}

When a request comes in for /hotels/1, that 1 will be bound to the hotelId parameter. You can optionally specify the variable name the parameter is bound to, but when you compile your code with debugging enabled that is not necessary: we infer the path variable name from the parameter name.

You can also have more than one path variable, like so:

@RequestMapping(value="/hotels/{hotel}/bookings/{booking}", method=RequestMethod.GET)
public String getBooking(@PathVariable("hotel") long hotelId, @PathVariable("booking") long bookingId, Model model) {
    Hotel hotel = hotelService.getHotel(hotelId);
    Booking booking = hotel.getBooking(bookingId);
    model.addAttribute("booking", booking);
    return "booking";
}

This would match requests like /hotels/1/bookings/2, for instance.

You can also combine the use of Ant-style paths and path variables, like so:

@RequestMapping(value="/hotels/*/bookings/{booking}", method=RequestMethod.GET)
public String getBooking(@PathVariable("booking") long bookingId, Model model) {
    ...
}

and you can use data binding, too:

@InitBinder
public void initBinder(WebDataBinder binder) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}

@RequestMapping("/hotels/{hotel}/dates/{date}")
public void date(@PathVariable("hotel") String hotel, @PathVariable Date date) {
    ...
}

The above would match /hotels/1/dates/2008-12-18, for instance.

Content Negotiation

In version 2.5, Spring-MVC lets the @Controller decide which view to render for a given request, through its View, view name, and ViewResolver abstractions. In a RESTful scenario, it is common to let the client decide the acceptable representations, via the Accept HTTP header. The server responds with the delivered representation via the Content-Type header. This process is known as content negotiation.

One issue with the Accept header is that is impossible to change it in a web browser, in HTML. For instance, in Firefox, it's fixed to

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

So what if you want to link to a PDF version of a particular resource? Looking at the file extension is a good workaround. For example, http://example.com/hotels.pdf retrieves the PDF view of the hotel list, as does http://example.com/hotels with an Accept header of application/pdf.

This is what the ContentNegotiatingViewResolver does: it wraps one or more other ViewResolvers, looks at the Accept header or file extension, and resolves a view corresponding to these. In an upcoming blog post, Alef Arendsen will show you how to use the ContentNegotiatingViewResolver.

Views

We also added some new Views to Spring MVC, particularly:

  • the AbstractAtomFeedView and AbstractRssFeedView, which can be used to return an Atom and RSS feed,
  • the MarshallingView, which can be used to return an XML representation. This view is based on the Object/XML Mapping module, which has been copied from the Spring Web Services project. This module wraps XML marshalling technologies such as JAXB, Castor, JiBX, and more, and makes it easier to configure these within a Spring application context,
  • the JacksonJsonView, for JSON representations of objects in your model. This view is actually part of the Spring JavaScript project, which we'll talk about more in a future blog post.

Obviously, these work great in combination with the ContentNegotiatingViewResolver!

HTTP Method Conversion

Another key principle of REST is the use of the Uniform Interface. Basically, this means that all resources (URLs) can be manipulated using the same four HTTP method: GET, PUT, POST, and DELETE. For each of methods, the HTTP specification defines exact semantics. For instance, a GET should always be a safe operation, meaning that is has no side effects, and a PUT or DELETE should be idempotent, meaning that you can repeat these operations over and over again, but the end result should be the same.

While HTTP defines these four methods, HTML only supports two: GET and POST. Fortunately, there are two possible workarounds: you can either use JavaScript to do your PUT or DELETE, or simply do a POST with the 'real' method as an additional parameter (modeled as a hidden input field in an HTML form). This latter trick is what the HiddenHttpMethodFilter does. This filter was introduced in Spring 3.0 M1, and is a plain Servlet Filter. As such, it can be used in combination with any web framework (not just Spring MVC). Simply add this filter to your web.xml, and a POST with a hidden _method parameter will be converted into the corresponding HTTP method request.

As an extra bonus, we've also added support for method conversion in the Spring MVC form tags. For example, the following snippet taken from the updated Petclinic sample:

<form:form method="delete">
    <p class="submit"><input type="submit" value="Delete Pet"/></p>
</form:form>

will actually perform an HTTP POST, with the 'real' DELETE method hidden behind a request parameter, to be picked up by the HiddenHttpMethodFilter. The corresponding @Controller method is therefore:

@RequestMapping(method = RequestMethod.DELETE)
public String deletePet(@PathVariable int ownerId, @PathVariable int petId) {
    this.clinic.deletePet(petId);
    return "redirect:/owners/" + ownerId;
}

ETag support

An ETag (entity tag) is an HTTP response header returned by an HTTP/1.1 compliant web server used to determine change in content at a given URL. It can be considered to be the more sophisticated successor to the Last-Modified header. When a server returns a representation with an ETag header, client can use this header in subsequent GETs, in a If-None-Match header. If the content has not changed, the server will return 304: Not Modified.

In Spring 3.0 M1, we introduced the ShallowEtagHeaderFilter. This is a plain Servlet Filter, and thus can be used in combination any web framework. As the name indicates, the filter creates so-called shallow ETags (as opposed to a deep ETags, more about that later). The way it works is quite simple: the filter simply caches the content of the rendered JSP (or other content), generates a MD5 hash over that, and returns that as a ETag header in the response. The next time a client sends a request for the same resource, it use that hash as the If-None-Match value. The filter notices this, renders the view again, and compares the two hashes. If they are equal, a 304 is returned. It is important to note that this filter will not save processing power, as the view is still rendered. The only thing it saves is bandwith, as the rendered response is not sent back over the wire.

Deep ETags are a bit more complicated. In this case, the ETag is based on the underlying domain objects, RDMBS tables, etc. Using this approach, no content is generated unless the underlying data has changed. Unfortunately, implementing this approach in a generic way is much more difficult than shallow ETags. We might add support for deep ETags in a later version of Spring, by relying on JPA's @Version annotation, or an AspectJ aspect for instance.

And more!

In a following post, I will conclude my RESTful journey, and talk about the RestTemplate, which was also introduced in Spring 3.0 M2. This class gives you client-side access to RESTful resources in a fashion similar to the JdbcTemplate, JmsTemplate, etc.

Similar Posts

Share this Post
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • LinkedIn
  • Slashdot
  • Technorati
  • Twitter
 

52 responses


  1. If I would just like to use REST capabilities as a way to expose some of our data(actually we have a desktop client app that is the main app but want to provide a REST API for integration scenarios), can we use Spring REST support. What I am trying to say is that we don't have any web based UI we are just tyring to expose the API via REST. I am tasked to recommend and right now I am ready to go with Jersey and I happen to see this post.


  2. Excellent overview of the new Spring REST capabilities. I look forward to introducing these concepts to our development teams when Spring 3.0 is released. I really like the annotated approach to controllers, of which Spring REST annotations are a natural progression. Excellent work.

    Also, thanks for the "behind the scenes" look at the planning/prototyping of these features. I wish our management would more "officially" support such prototyping efforts.


  3. Informative thanks for sharing.
    regards
    SBL Geomatics


  4. @Philip

    Any ideas when would that be happening (Spring 3.0 release)


  5. Excellent plan. What's even better is that it fits really nicely with the strategies I've already been using … it'll just make it easier to strip out some of my existing boiler-plate code. Typical Spring-yness.

    Looking forward to Spring 3.0 with anticipation.


  6. With respect to the Spring Framework 3.0 release date…

    Our current roadmap looks as follows: We'll do 3.0 M3 at the end of March; then we'll move on to the first release candidate which is expected in late April. Depending on RC feedback, the Spring 3.0 final release will follow soon after.

    Now, in order to get there, you guys playing with our 3.0 milestones ahead of the RC1 release would be of great value :-)


  7. I've been experimenting with the RequestMapping/PathVariable, RestTemplate and OXM and so far it's been a very pleasant experience. One thing which would potentially reduce boiler plate even further would be to have an XML HttpMessageConverter based around the OXM Unmarshaller and Marshaller interfaces.

    Arjen mentions the JacksonJsonView in the post. This doesn't appear to be in the bundle of 3.0M2, so I was wondering whether he's just highlighting it's existence within Spring-JS, or if it's planned to be merged into the Spring core?


  8. @Phil

    Thanks!

    As for the JacksonJsonView, there are no plans to move it to the core at this time.


  9. I have quite a bit of code using the existing javax.ws.rs.* annotations.
    Why create new annotations?


  10. @Michael

    We did not create new annotations, we extended the ones we already introduced in Spring 2.5.


  11. I just noticed that as I was writing some code with Spring 2.5.
    Maybe I could just create handlers for @PathParam/@Path/@ProduceMime and port my code over that way.
    That might be fun.


  12. The REST support looks cool. Do Spring controllers work with JSON payload as well in addition to usual form post ?
    Basically I would like to submit a form through Ajax but not with usual query params as payload, but as a JSON string from the client.

    thanks,
    Karthik


  13. Fantastic! I struggled to wrangle Spring MVC 2.0 into a RESTful web service for well over a year. This is very welcome news!


  14. I remember you mentioning something about JAX-RS support in Spring at a Spring conference. Is it going to part of Spring 3.0 RC/Final? Is ContentNegotiatingResolver meant to provide the functionality of @ProduceMime? We are hoping that Alef's post on ContentNegotiatingResolver will make it clear to us on how it can resolve a MarshallingView or RssView etc depending on "Accept" header or extension etc.


  15. @Aditya

    We were thinking about adding support to JAX-RS in a way similar to our JAX-WS support, but I don't think there is any SPI in JAX-RS which allows us to do this in a consistent way across many JAX-RS implementations. Also, the fact that all major JAX-RS implementations already have Spring support makes this less necessary.


  16. @Aditya

    yes, my post will cover that… Not for a MarshallingView but for an AtomFeedView. I'll post it next Monday.

    cheers,
    Alef


  17. Thank you Arjen & Alef for the clarification.


  18. I've experimented a bit with Spring 3.0, and have written an article "Test drive of Spring 3.0 Milestone 2 REST support" about my impressions. You may find it here: http://grzegorzborkowski.blogspot.com/2009/03/test-drive-of-spring-30-m2-rest-support.html
    Hope you find it useful for further development of Spring REST support.


  19. SpringSource is doing a great job with enhancements and each new release has substantially richer functionality compared to earlier versions. The core Spring framework is now pretty massive and it appears that the framework has been rapidly shedding XML in favor of annotations. I realize that a lot of Spring users don't necessarily like using XML. I've identified at least the following annotations in the core Spring framework (3.0)
    • @Autowired
    • @Component
    • @Controller
    • @InitBinder
    • @ManagedAttribute
    • @ManagedOperation
    • @ManagedOperationParameters
    • @ManagedOperationParameter
    • @ManagedResource
    • @PathVariable
    • @PostConstruct
    • @PreDestroy
    • @Repository
    • @RequestMapping
    • @Required
    • @Resource
    • @Service
    • @Transactional

    May I humbly recommend that SpringSource provide an annotation cheat-sheet in the documentation with brief use-cases as well as configuration entries needed to activate each annotation e.g. . I deeply appreciate the efforts that you and the rest of the SpringSource team have expended to make Spring a key Java enterprise framework. The REST support in Spring MVC looks fantastic and I'm going to try it out soon.


  20. It is great to have REST feature in the Spring MVC. I can't wait to use it in my projects. Where I can access a reference documentation in the subject? I can't see any reference documentations in the new package 3.0.0 M2 other than API.


  21. @Wei: there is no reference documentation yet, just the API docs and Petclinic sample at https://fisheye.springframework.org/browse/spring-framework/trunk/org.springframework.samples.petclinic. We hope to have more documentation in Milestone 3, and complete it in the RC phase.


  22. How much work would it be to throw in an @Interceptor annotation for the MVC Controllers?
    or may be support multiple interceptors as well through @Interceptors

    @Interceptors([
    @Interceptor(MyInterceptor.class)
    @Interceptor(MyInterceptor.class)
    ])

    ?


  23. Will there be any JSF integration? Spring 2.5.6 is a real let down for JSF users. I love Spring MVC, but Spring Source provides no samples or documentation integrating JSF and Spring MVC, only Spring WebFlow, which is a poor fit for 98% of applications (most apps don't use conversation scope and need to be bookmarkable with out creating a flow for literally every page in your application).

    Spring is leaving us with the choice of great support for primitive JSP/HTML views via MVC and poor support for anything other than complex worksflows if we want to use JSF.


  24. Apologies if this is a real newbie question or the wrong place to ask it, but is it possible to externalize and share the same URI definition between the @RequestMapping annotation and the code that builds the URLs?

    e.g.
    In the petshop code is something like:
    @RequestMapping("/owners/{ownerId}")

    and in the jsp is something like:

    and if you change the structure of the url, you have to track down all the places that this URI definition exists (you'd have to do that anyway if the parameters changed, but I'm referring to just a change like "foo/owners/{ownerId}").

    Also, out of curiosity, if you (lost your mind and) decided you no longer wanted RESTful urls, could you change your URI definition to: "owners?ownerId={ownerId}"?


  25. oops – that missing jsp code is:
    <spring:url value="owners/{ownerId}" var="ownerUrl">
    <spring:param name="ownerId" value="${owner.id}"/>
    </spring:url>


  26. I started introducing Spring 3.0 a while ago, and I see REST features are widely used. It sounds interesting and useful, but there are things I don't like. (But maybe I am just making newbie mistakes). The thing I don't like is @RequestMapping annotation. Using that we are specifying url in java file. I don't think that's right place for that, xml file would be much prettier solution. Maybe I am thinking in old fashion way ( in "Spring 2.0 way" ), but I don't see this feature as really convenient.

    Consider scenario Jamie mentioned in the post above mine: if you want to change url from "owners/{ownerId}" to "foo/owners/{ownerId}" you have to change value of @RequestMapping annotation, that means you have to recompile that java class! If that configuration is placed in xml file you wouldn't have to recompile. The same thing is for @PathVariable annotation. ( when I mentioned this, I have to say that I more prefer Struts2 actions and their style of binding parameters to class properties – without annotations)

    I was talking about all this to my colleagues, and our opinion is that we don't like so much configuration placed in annotations (that means in .java file), we like Spring 2.0 way – xml configuration. Is it possible in Spring 3.0?


  27. I completely agree with Boyan et. al. While I am not averse to having the controllers use annotation based configuration, I would love to see a functionally equivalent XML based routing configuration, for those who would rather not use it. The current model, IMHO, has the following problems:

    1. URL mapping is scattered all over the place. If I have 15 controllers, with 10 methods each (and note that there's the issue of each method potentially having a completely different URL that it can match), a newbie would have to look at 150 potential places to map a given URL to the controller action it resolves to. Admittedly, having good conventions and oversight will alleviate this problem, but seems too easy to have things go awry.

    2. As Boyan mentioned, any changes to the mapping requires a recompile.

    3. The same controller method cannot be mapped to multiple urls (or at least I can't figure out how to do it :( ), allowing different views to be driven by the same controller.

    4. A somewhat minor thing. There is now way to write a controller w/o Spring dependencies.

    Btw, It would be nice to have mappings that are pattern based, such as, a way to map /somepath/{method} to handler SomePathController, method {method}.


  28. Good point, Vijay!

    Can someone of Spring officials share his opinion about this with us?


  29. @Vijay & Boyan:

    Ad 1 & 2: Rossen wrote a post about combining XML and annotations a while ago. They key idea is to use XML for the course-grainined mappings, and annotations for further disambiguation. Check it out!

    Ad 3:The @RequestMapping annotation allows for multiple paths as a String array, so you can map multiple urls to the same controller method.

    Ad 4: It was never possible to write a controller for MVC without having Spring dependencies. Previously, you had to implement the controller interface, or extend from one of the base classes. I would say that the Spring dependency has become less with @MVC, now that we use annotations, since these are only necessary at compile time, not at runtime.


  30. Hi,
    I'm also using REST, without Spring, everyday. I would like to know a little more about your security approach.
    Would you use Authorization header, jsessionid or hash in cookies ? Does Spring implement a Digest authentication support ?

    Thanx,
    Nicolas


  31. I have upgraded my project to use spring3.0.0.M2. When I tried to access my application I have seen the below error in console.
    log4j:WARN No appenders could be found for logger (org.apache.commons.httpclient.HttpClient).
    log4j:WARN Please initialize the log4j system properly.
    returnCode –> 500
    Apache Tomcat/6.0.16 – Error report HTTP Status 500 – type Exception reportmessage description The server encountered an internal error () that prevented it from fulfilling this request.exception javax.servlet.ServletException: Servlet.init() for servlet LogReaderDispatcher threw exception
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    java.lang.Thread.run(Thread.java:619)
    root cause org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/LogReaderDispatcher-servlet.xml]; nested exception is java.lang.NoClassDefFoundError: org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor
    org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:394)
    org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:316)
    org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:284)
    org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
    org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
    org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
    org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
    org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:93)
    org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:125)
    org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:418)
    org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:348)
    org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:427)
    org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:341)
    org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:307)
    org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)
    javax.servlet.GenericServlet.init(GenericServlet.java:241)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    java.lang.Thread.run(Thread.java:619)
    root cause java.lang.NoClassDefFoundError: org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor
    org.springframework.core.type.classreading.SimpleMetadataReader.getAnnotationMetadata(SimpleMetadataReader.java:54)
    org.springframework.core.type.filter.AnnotationTypeFilter.matchSelf(AnnotationTypeFilter.java:68)
    org.springframework.core.type.filter.AbstractTypeHierarchyTraversingFilter.match(AbstractTypeHierarchyTraversingFilter.java:55)
    org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.isCandidateComponent(ClassPathScanningCandidateComponentProvider.java:252)
    org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:192)
    org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:201)
    org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(ComponentScanBeanDefinitionParser.java:83)
    org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:72)
    org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1291)
    org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1281)
    org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:135)
    org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:92)
    org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:475)
    org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:372)
    org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:316)
    org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:284)
    org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
    org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
    org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
    org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
    org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:93)
    org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:125)
    org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:418)
    org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:348)
    org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:427)
    org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:341)
    org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:307)
    org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)
    javax.servlet.GenericServlet.init(GenericServlet.java:241)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    java.lang.Thread.run(Thread.java:619)
    note The full stack trace of the root cause is available in the Apache Tomcat/6.0.16 logs.Apache Tomcat/6.0.16

    Can any one please help me out?
    Even I have spring.core package in my web-inf/lib folder.


  32. @ramesh

    This blog is not the proper place to ask for help. Did you try the Community Forums?


  33. The lack of standards support is a little bit annoying.

    The missing support for JSR 311 and description languages like WSDL 2.0 or WADL leads to not portable implementations and the support in IDE's is always incomplete. Another view is the usability by users (generating of client stubs, test clients, …)

    I would say, that there are already three FOUR JAX-RS implementations offering Spring STANDARDS support (Jersey, RESTEasy, CXF and Restlet).

    It's always a good use of valueable time to support standards and interoperability… I hope you will add a fifth framework to the group of JAX-RS compliant frameworks.


  34. This is great news to the java world!

    Currently I see two issues though:
    - How to determine format inside controller? (you probably need different data in the different scenarios)
    - How to test the request mappings?

    A standard(Convention over configuration) CRUD request mapping system, like in rails, would also be nice.

    Cheers,

    Stefan


  35. What are your thoughts on the thread http://forum.springsource.org/showthread.php?t=79114


  36. How to upload file use annotation?
    Please provide examples.
    Thank you.


  37. Consider a method like this:

    @RequestMapping(value="/businessFunctions", method=RequestMethod.POST)
    public void post(@RequestBody String body) {
    BusinessFunction bfToInsert = deserializeJson(body);
    aclService.insertBusinessFunction(bfToInsert);
    }

    What do I have to return? My GET method works perfectly returning a string with @RequestBody annotation. I suppose POST doesn't have to return anything else than a Response code 201. The question is…. HOW?


  38. My MarshallingView (Spring 3.0.0.RELEASE) seems to be picking only ONE object from a ModelAndView object and it picks the first one by key (alphabetically). Is that desired?


  39. @Michal, are you using Jaxb2Marshaller? If so, I have this same problem and I definitely don't think it is desired behavior. I submitted an issue to Spring concerning this behavior: http://jira.springframework.org/browse/SPR-6577. You can vote for the issue if you agree it is a problem.

    There is a workaround. When you define the MarshallingView bean in your Spring XML config file, set the "modelKey" property on the view bean to tell it which object from the ModelAndView to marshall. It is not a good solution, but it works.


  40. @Scott
    I tried all kinds of marshallers. I don't think it's a marshaller issue at all! I believe it is the implementation of the locateToBeMarshalled method that causes problem and I added an issue as well, please take a look:
    http://blog.springsource.com/2009/03/08/rest-in-spring-3-mvc/

    I think this is the problem – I even tried different marshallers.


  41. It's it possible to use this without an extension like .do or .action in the URIs?

    Cause I tried map the dispatcher servlet with /* but then I got some erros when trying to load other resources like scripts (js), images and static pages.

    I just would like to use http://domain/users/name insted of http://domain/users/name.do


  42. It sems that there is a solution for the problem I've pointed right here http://stackoverflow.com/questions/2047774/spring-mvc-rest-static-files-unaccessible-because-of-url-pattern

    Thanks, Anyway….


  43. Hello Arjen,

    I built a class called SiteMap (implementing BeanFactoryAware) that builds a list of my app's URIs. When clients hit my root context, I'll serve out an XHTML5 representation of this sitemap for further discovery (I could possibly even serve a WADL).

    In fear of re-inventing the wheel, do you have similar functionality already?

    Also, it will be great if RequestMapping could be made more granular, e.g.

    @RequestMappings){
    @RequestMapping("/sales_channel/{region}",
    @Arguments({@Argument(0, uri="/regions")}))
    })

    Or…

    @RequestMappings){
    @RequestMapping("/foo/{bar}/{baz}",
    @Arguments({
    @Argument(0, uri="/bars"),
    @Argument(1, doc="This is a free-text field, first 30 characters accepted.")}))
    })

    The first one tells my client that the variable "region" has options in the result provided by the call to "/regions".
    In the second one instead we provide documentation stating that the second argument is a free-text field.

    I'd like to be able to have a self-documenting system like this.

    Thanks,
    Juan


  44. A newbie question. Any help would be greatly appreciated.

    Hi,

    Attempting to be RESTFUL, I am using Marshaller/UnMarshaller and @RequestBody and @ResponseBody to render HTTP messages. Both request and response bodies have an XML string.

    After the request body has been retrieved using @RequestBody to a POJO class object, I need to process the XML data and create an HTTPResponse with an XML string to send back to the originating URL.

    Then, subsequently display the XML response data on a web page.

    My question is:

    In my controller using MVC processing an HTTPRequest POST method, what should I return? I have no View. I just want to return the HTTPResponse message with a new XML string send back to the Requester and then "render"/display the HTTPResponse message on a web page.

    My web service sends requests and receives responses, hence need to handle both.

    I am new to this, please help.

    In my controller:

    @RequestMapping(value = "/httpmsg", method = RequestMethod.PUT)
    public String create(@RequestBody HTTPMsg httpmsg) {
    System.out.println("HTTP Message PUT: " httpmsg);
    return "httpmsg";
    }
    @RequestMapping(value = "/httpmsg", method = RequestMethod.POST)
    public String create(@RequestBody HTTPMsg httpmsg, ModelMap modelMap) {
    System.out.println("HTTPMsg: " httpmsg);
    if (httpmsg == null) throw new IllegalArgumentException("An HTTP request is required");
    return "redirect:/httpmsg/";
    }

    @RequestMapping(value = "/httpmsg", method = RequestMethod.POST)
    public String createRsp(@ResponseBody HTTPMsg httpmsg, ModelMap modelMap) {
    System.out.println("HTTPMsg: " httpmsg);
    return "redirect:/httpmsg/";
    }

    // Provides a Form to enter Request parameters
    @RequestMapping(value = "/httpmsg/form", method = RequestMethod.GET)
    public String createForm(ModelMap modelMap) {
    modelMap.addAttribute("httpmsg", new HTTPMsg());
    return "httpmsg/create";
    }

    In my webmvc_config.xml:

    com.bzinc.demoBackup.domain.HTTPMsg

    <!– –>

    How off-base am I on the plumbing above? Please point out problems or the right way to do it.

    Looking forward to any info.


  45. Missing code from above:

    In my webmvc_config.xml, I added:

    com.bzinc.demoBackup.domain.HTTPMsg

    <!– –>


  46. Mimi, please see my article on this:
    http://blog.m1key.me/2010/02/programming-rest-with-spring-30-spring.html

    Hope it answers your questions. There's more articles in this series.


  47. Juan, your SiteMap class sounds like exactly what I could use. Any chance of your making that source code available? Thanks, – Jon


  48. Following REST in Spring 3 -

    I need the Controller to return a View AND an HTTP Response message to the HTTP Requestor's URI.

    Currently, my Server and Client are in one program. I created a plain string (the HTTP Response message – in XML) and return this string to @ResponseBody like below:

    @RequestMapping(value = "/httpreqmsg1", method=RequestMethod.POST)
    public @ResponseBody String createResponse(@Valid HttpReqMsg1 httpReqMsg1) {
    if (httpReqMsg1 == null)
    throw new IllegalArgumentException("A HTTP Request Message is required");
    return httpReqMsg1.createResponse(httpReqMsg1);
    }

    I persisted the Request (not the Response) and did a SystemPrintOut of the string before returning from the Controller for POST. What I got was a SystemPrintOut of the string on a blank screen. That's fine.

    However, how do I know that the HTTP Response was automatically sent to the Requester for me and not just showing me as SystemPrintOut?

    Do I have to do anything to 'send back' this HTTP Response to the Requester's URI besides have it simply print out on the screen?

    Another question is:
    How can I do the 2 things below with just one chance of returning from the Controller to the Dispatcher?

    1. Send HTTP Response to Requester (end-user: mobile devices)
    2. Show the sent HTTP Response in a View

    Any help would be greatly appreciate.


  49. How do I pass a float number on the url?

    e.f. http://localhost:8080/test/product/emd/1.2/test

    I am getting 1 instead of 1.2 in the path variable.


  50. Hi all,
    I am developing a restful web service using spring 3.0 . And I am a newbee in this.
    I am using RAD to develop it n wfetch for testing the web service and I have not used maven.
    I pass my inputs through a request xml and this request xml is sent as the body of POST method.
    My problem is the I am not able to retrieve the data that I have passed through the request xml in the controller class.
    Basically I am not able to process any data coming from request as the POST message body…..

    Please help… any suggestions welcome….
    thanks in advance……..


  51. Is there a way to achieve Streaming in REST -Spring 3


  52. Very nice article….

24 trackbacks