File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Spring and the fly likes HttpMessageConverter Vs ContentNegotiatingViewResolver Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Frameworks » Spring
Bookmark "HttpMessageConverter Vs ContentNegotiatingViewResolver" Watch "HttpMessageConverter Vs ContentNegotiatingViewResolver" New topic
Author

HttpMessageConverter Vs ContentNegotiatingViewResolver

Maneeesh Saxena
Greenhorn

Joined: Dec 24, 2006
Posts: 26
hi All,

I am confused about HttpMessageConverter and ContentNegotiatingViewResolver. Both does the same work or they are different? if we've an object that we wanna represent in xml format we can do it by using ContentNegotiatingViewResolver, same thing can be done using HttpMessageConverter. Then what is the difference?


I am really confused. Please let me know if my question is not correct.
Maneeesh Saxena
Greenhorn

Joined: Dec 24, 2006
Posts: 26
I would be grateful if someone can describe with examples.

Thanks & Regards,
Maneesh Saxena
Mark Spritzler
ranger
Sheriff

Joined: Feb 05, 2001
Posts: 17250
    
    6

Actually they could and do work together.

a View resolver does one thing. Resolve to a view, whether that might be a .jsp file, or some other rendered view. But it could also be a rendered view of JSON or XML in the body of the request or response. So a resolver might look in the request and see that the user wants JSON back, that is what a view resolver like ContentNegotiationViewResolver is doing, but the conversion from your Java domain objects to that content type is done through a HttpMessageConverter in Spring MVC. But with that it will basically delegate to maybe JAXB for xml mapping and rendering, or Apache Jackson for JSON.

Hope that helps.

Mark


Perfect World Programming, LLC - Two Laptop Bag - Tube Organizer
How to Ask Questions the Smart Way FAQ
Maneeesh Saxena
Greenhorn

Joined: Dec 24, 2006
Posts: 26
hi Mark,

Thanks for your reply. Still I've some doubts, please refer the code below which is related to it.


web.xml




testContentNegotiation-servlet.xml



FruitController.jsva





list.jsp




Fruit.java






Everything is fine for above code. I got json view as well as xml view for Fruit resource. But as shown I didn't configure any HttpMessageConverter in my context file. If HttpMessageConverter and ContentNegotiatingViewResolver works together then how conversion is performed here ?


I've a separate class shown below.

CoffeeController.java




Coffee.java




I got only xml representation for both Urls http://localhost:8080/contextName/testContentNegotiation/coffee/mocha (.xml or .json ). I am not getting any idea how this is happening as I didn't configure any MessageConverter in context. if that's mandatory then why xml is returned for both Urls. What role @ResponseBody is playing in CoffeeController.getCoffeeInXML() method?



One more doubt what is role of defaultViews and viewResolvers properties of ContentNegotiatingViewResolver.


Thanks and Regards,
Maneesh
Bill Gorder
Bartender

Joined: Mar 07, 2010
Posts: 1649
    
    7

Ok this is probably going to be a long response so buckle your seat belt

ContentNegotiatingViewResolver does not resolve views itself but rather delegates to other view resolvers, like your MappingJacksonJsonView, or your MarshallingView. There are 2 strategies for determining the correct representation:

1. Distinct URI - This is where your request ends in .json or .xml
2. Content Negotiation - The correct media type is read off of the Accept Header of the request.

Now when you configured your view resolvers you specified the Content-Type(Media type) along with your keys for example
<entry key="json" value="application/json" />

Here what you have done is opted to use the URI strategy above. This line in turn mapped the .json file extension to the Content-Type of "application/json" . So if a request comes in with a .json file extension the ContentNegotiatingViewResolver will go down the ViewResolver chain and return the first View it finds that supports that content type, which will turn out to be MappingJacksonJsonView.

The ViewResolver chain I just mentioned is the same viewResolvers property on the ContentNegotiatingViewResolver that you asked about. If it makes it through the entire list of ViewResolvers and does not find a match it will go through the views specified by the DefaultViews property. Default views are singleton views that can render an appropriate response regardless of the logical view name. Both MappingJacksonJsonView and MarshallingView would be good examples of this.

Following is an example:



Now because in your example you did not define <property name="viewResolvers"> the ContentNegotiatingViewResolver will automatically use any ViewResolver that it can find defined in the application context.

If you chose to not include the file extension .json or .xml then it would consult the Accept Header to find the correct resolution. This is problematic at times since browsers will submit with an an Accept header similar to the following

text/html,application/xhtml+xml,application/xml

This is impossible to to change with HTML, which is why for browser based applications the URI pattern is generally used. BTW this is also why your second example only returned XML (notice there is no json in that header, but more on that later)

Now lets talk about @ResponseBody-

When your method is annotated with @ResponseBody you are indicating that the return type should be written straight the the HTTP response body and not interpreted as a view name or placed in model. In order to facilitate this Spring converts your returned object to a response body by using a HttpMessageConverter.

Where did they come from? Spring registers several of these for you automatically including MappingJacksonHttpMessageConverter if Jackson is found on the classpath and Jaxb2RootElementHttpMessageConverter if JaxB is found on the class path.

Now unlike the ContentNegotiatingViewResolver file extensions don't help you here. All the resolution is made from the headers. If the Accept header of the request is set to "application/xml" (as would have been in your example), XML will be returned regardless of whether you put a .json on the end. To be clear and enforce correct mapping you should make use of the consumes and produces properties of the @RequestMapping.


For example take this method that takes an xml or json message posted in and returns some sort of response -

What this will do for you is when spring is mapping the request to this handler method it will ensure that the Content-Type and Accept headers of the request must be either "application/xml" or "application/json" for this method to process the request.

Now say this endpoint is being posted in via some jquery/ajax from my jsp. If I set my Content-Type to "application/json" and my Accept to "application/xml" this method will accept that request. It will assume that someOtherObject is json and will unmarshall it for me. It will do whatever it needs to do and use the Jaxb2RootElementHttpMessageConverter to write my instance of SomeObject as XML to the HTTP response.


To play with this more use this fire fox extension which allows you to set the headers:

https://addons.mozilla.org/en-US/firefox/addon/restclient/


Also note there is a jira for equalizing the abilities of @ResponseBody with what the ContentNegotiatingViewResolver can do (like URI based resolution) look for it coming up in Spring 3.2

https://jira.springsource.org/browse/SPR-8410

Hope that helps.



[How To Ask Questions][Read before you PM me]
Krishna Srinivasan
Ranch Hand

Joined: Jul 28, 2003
Posts: 1844

This is great explanation to understand content negotiation in spring mvc.


Krishna Srinivasan
Spring Tutorials, OCAJP Mock Questions, 400+ OCPJP Mock Questions
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: HttpMessageConverter Vs ContentNegotiatingViewResolver