Archive

Posts Tagged ‘rest’

Spring MVC: @ResponseBody and URL Extensions

December 29th, 2016 No comments

If you use Spring MVC to develop web services then you most likely have run into a limitation with @ResponseBody.  Specifically, Spring will automatically marshal the return value of an annotated method to XML, JSON, etc. depending on what the client requests.  Unfortunately, Spring only considers the Accepts header of the client.  While this works well enough when using REST clients, it is particularly difficult to work with in web browsers.  In this article I’ll show you how to extend @ResponseBody to support more advanced forms of content negotiation including analyzing the URL’s extension.

Updated 9/22/11 — Fixed a bug where CNRB was not setting an Accept header if the client did not already include one. Many thanks to Leone Parise for finding the bug, reporting it, and submitting the patch.

Ideally, we would like Spring to consider the URL’s extension when determining what format should be used.  For example, /pets.xml should return a list of pets in an XML format while /pets.json should return a list of pets in JSON format.

Until support is officially added to the Spring Framework, I would recommend using my ContentNegotatingResponseBody class.  To do so, put the class in your class path and add the following being registration to your Spring configuration:

<bean class='me.tedyoung.blog.contentnegotatingresponsebody.ContentNegotatingResponseBody'>
	<property name="mediaTypes">
		<map>
			<entry key="atom" value="application/atom+xml"/>
			<entry key="xml" value="application/xml"/>
			<entry key="json" value="application/json"/>
			<entry key="pdf" value="application/pdf"/>
		</map>
	</property>
</bean>

You will likely have to modify the class’s package from this example.

The mediaTypes property maps file extensions to content types.  Internally, ContentNegotatingResponseBody will look at the file extension of the URL.  If the file extension is found in the list of mediaTypes, it will set the content type to the corresponding value.  Otherwise, it will fall back to Spring’s default behavior of analyzing the Accepts header.

Feel free to use this in your own applications.  The exact copyright can be found here.