Mapping JSON Request With Spring MVC

Inspired by ContentNegotiatingViewResolver section on Spring manual, this is a short tutorial on how you can map a request with *.json extension into a JSON view.

This tutorial will demonstrate a small subset of Spring JSON capability using the ‘Spring MVC Project’ template application generated by STS. When you first created a new project from the template, the web app came with a default home page showing ‘Hello World’ and a server time passed via Model attribute.

We will extend this home page a little bit so we can obtain the JSON view. Note that the JSON view will only contain the formatted attributes inside the Model object

By the way, if you haven’t already know — JSON stands for Java Script Object Notation. It’s a textual representation of a Java Script object, and it’s one of the most popular way of transferring information from server to client in modern Ajax application.

Create a new project using a template

  1. Assuming you have SpringSource Tools Suite (STS) installed, create a new project and select Spring Template Project Wizard
  2. Select ‘Spring MVC Project’ from the selection of template, it might prompt you to download if this is the first time you’re using it
  3. Enter a project name and top-level package and hit ‘Finish’

Change the view resolver to ContentNegotiatingViewResolver

ContentNegotiatingViewResolver is a unique resolver which will delegate request to another resolver by the requested media types. There are multiple way it can determine the media type, but here we’ll just use the URL extension method (see the javadoc for more).

On the servlet spring beans configuration (servlet-context.xml), replace the default InternalResourceViewResolver with this:

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory.
	If the request has an extension .json, always provide MappingJacksonJsonView regardless -->
	<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
		<property name="mediaTypes">
			<map>
				<entry key="json" value="application/json" />
			</map>
		</property>
		<property name="viewResolvers">
			<list>
				<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
					<property name="prefix" value="/WEB-INF/views/" />
					<property name="suffix" value=".jsp" />
				</bean>
			</list>
		</property>
		<property name="defaultViews">
			<list>
				<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
			</list>
		</property>
	</bean>

In the example above, we define request with the extension “.*json” into “application/json” media type. Normal request is set to “text/html” by the browser by default. When a request came, the list of view resolvers on the “viewResolver” property will be consulted, and if it supports the requested  media type, that view resolver will be used.

The “defaultViews” property specifies the view that will be override the ones provided by matching resolvers (even if none matches) — regardless of the view name returned by the controller. This however only hold true if the View supports the requested media type.

For example, if “/home” path is requested with Accept header “text/html”, ContentNegotiatingViewResolver will set the media type to “text/html”, consult InternalResoursceViewResolver bean (which supports text/html) and use it. If “/home.json” path is requested, the media type is set to “application/json” (not supported by InternalResourceViewResolver), and since the specified default view MappingJacksonJsonView supports it, it will be used. This is sufficient for common usage because all JSON view can be rendered in the same fashion

Have a look at Spring Reference Section 16.5.4 ContentNegotiatingViewResolver for more info.

Change the Controller mapping

STS Spring MVC new project template mapped the MainController into “/”, however for our demonstration purpose, let’s map it to “/home”, so we can compare the different media type easily.

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {

	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/home", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		logger.info("Welcome home! the client locale is "+ locale.toString());

		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

		String formattedDate = dateFormat.format(date);

		model.addAttribute("serverTime", formattedDate );

		return "home";
	}

}

Add Jackson dependency to your classpath

The MappingJacksonJsonView requires Jackson library in your classpath. This library will help you to transform java objects into JSON representation. Add the following dependency to your pom.xml

		<dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-mapper-lgpl</artifactId>
			<version>1.2.1</version>
		</dependency>

Ready to go

Fire up embedded tomcat using mvn package tomcat:run goals, and:

  1. Point your browser to http://localhost:8080/json-simple/home. Inspect you are getting the normal hello world page with server time
  2. Point your browser to http://localhost:8080/json-simple/home.json. Inspect you are getting the json representation of the model object

The sourcecode for this tutorial is available:

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s