How does the Spring @ResponseBody annotation work?
First of all, the annotation doesn't annotate List
. It annotates the method, just as RequestMapping
does. Your code is equivalent to
@RequestMapping(value="/orders", method=RequestMethod.GET)
@ResponseBody
public List<Account> accountSummary() {
return accountManager.getAllAccounts();
}
Now what the annotation means is that the returned value of the method will constitute the body of the HTTP response. Of course, an HTTP response can't contain Java objects. So this list of accounts is transformed to a format suitable for REST applications, typically JSON or XML.
The choice of the format depends on the installed message converters, on the values of the produces
attribute of the @RequestMapping
annotation, and on the content type that the client accepts (that is available in the HTTP request headers). For example, if the request says it accepts XML, but not JSON, and there is a message converter installed that can transform the list to XML, then XML will be returned.
The first basic thing to understand is the difference in architectures.
One end you have the MVC architecture, which is based on your normal web app, using web pages, and the browser makes a request for a page:
Browser <---> Controller <---> Model
| |
+-View-+
The browser makes a request, the controller (@Controller) gets the model (@Entity), and creates the view (JSP) from the model and the view is returned back to the client. This is the basic web app architecture.
On the other end, you have a RESTful architecture. In this case, there is no View. The Controller only sends back the model (or resource representation, in more RESTful terms). The client can be a JavaScript application, a Java server application, any application in which we expose our REST API to. With this architecture, the client decides what to do with this model. Take for instance Twitter. Twitter as the Web (REST) API, that allows our applications to use its API to get such things as status updates, so that we can use it to put that data in our application. That data will come in some format like JSON.
That being said, when working with Spring MVC, it was first built to handle the basic web application architecture. There are may different method signature flavors that allow a view to be produced from our methods. The method could return a ModelAndView
where we explicitly create it, or there are implicit ways where we can return some arbitrary object that gets set into model attributes. But either way, somewhere along the request-response cycle, there will be a view produced.
But when we use @ResponseBody
, we are saying that we do not want a view produced. We just want to send the return object as the body, in whatever format we specify. We wouldn't want it to be a serialized Java object (though possible). So yes, it needs to be converted to some other common type (this type is normally dealt with through content negotiation - see link below). Honestly, I don't work much with Spring, though I dabble with it here and there. Normally, I use
@RequestMapping(..., produces = MediaType.APPLICATION_JSON_VALUE)
to set the content type, but maybe JSON is the default. Don't quote me, but if you are getting JSON, and you haven't specified the produces
, then maybe it is the default. JSON is not the only format. For instance, the above could easily be sent in XML, but you would need to have the produces
to MediaType.APPLICATION_XML_VALUE
and I believe you need to configure the HttpMessageConverter
for JAXB. As for the JSON MappingJacksonHttpMessageConverter
configured, when we have Jackson on the classpath.
I would take some time to learn about Content Negotiation. It's a very important part of REST. It'll help you learn about the different response formats and how to map them to your methods.