• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

HttpMessageConverter Vs ContentNegotiatingViewResolver

 
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 26
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I would be grateful if someone can describe with examples.

Thanks & Regards,
Maneesh Saxena
 
ranger
Posts: 17347
11
Mac IntelliJ IDE Spring
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Maneeesh Saxena
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Bartender
Posts: 1682
7
Android Mac OS X IntelliJ IDE Spring Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.


 
Ranch Hand
Posts: 1880
Firefox Browser Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This is great explanation to understand content negotiation in spring mvc.
 
Live ordinary life in an extraordinary way. Details embedded in this tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic