Enterprise Java

Content Negotiation in Spring Framework

1. Introduction

With what we had done with BeanNameViewResolver, is that we just had created multiple bean views in Spring context to generate the expected output. Spring soon introduced the Content Negotiation strategy, where we can use the traditional RESTful @ResponseBody approach and HTTP message converters, to return desired outputs in JSON or XML, along with some flexibility and dynamicity it provides with the configuration.

Often we need to provide multiple representations (or views) of the same data returned by the controller. This is very elegantly achieved with Content negotiation in Spring.

2. Implementation

To quickly start with the implementation, lets first create a new maven project. Click here to get help on creating your new maven project in Eclipse

Let’s now add the needed dependencies to the pom.xml file.

pom.xml

<!-- Spring dependencies -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-core</artifactId>
	<version>4.2.1.RELEASE</version>
</dependency>
 
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-web</artifactId>
	<version>4.2.1.RELEASE</version>
</dependency>
 
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>4.2.1.RELEASE</version>
</dependency>
 
<dependency>
	<groupId>javax.xml.bind</groupId>
	<artifactId>jaxb-api</artifactId>
	<version>2.2.6</version>
</dependency>
<dependency>
	<groupId>javax.xml</groupId>
	<artifactId>jaxb-impl</artifactId>
	<version>2.1</version>
</dependency>
 
<!-- Jackson JSON Processor -->
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>2.4.1</version>
</dependency>

Open web.xml and make sure you have the proper configuration done.

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
 
	<display-name>SpringMVCWithContentNegotiation</display-name>
 
	<servlet>
		<servlet-name>mvc-dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
 
	<servlet-mapping>
		<servlet-name>mvc-dispatcher</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
 
</web-app>

Create a new context file as <servlet name>-servlet.xml, which has to be mvc-dispatcher-servlet.xml with the following content.

mvc-dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
 
	<mvc:annotation-driven
		content-negotiation-manager="contentNegotiationManager">
		<mvc:path-matching registered-suffixes-only="true" />
	</mvc:annotation-driven>
 
	<context:component-scan base-package="com.jcombat.controller" />
 
	<!-- To disable path extension check in the path variable of URI -->
	<bean id="contentNegotiationManager"
		class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
		<property name="favorPathExtension" value="true" />
		<property name="ignoreAcceptHeader" value="true" />
		<property name="useJaf" value="false"/>
		<property name="defaultContentType" value="application/json" />
		<property name="mediaTypes">
			<map>
				<entry key="json" value="application/json" />
				<entry key="xml" value="application/xml" />
			</map>
		</property>
	</bean>
 
	<!-- For Other media types -->
	<bean id="jspViewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/jsp/" />
		<property name="suffix" value=".jsp" />
	</bean>
 
</beans>

Note that the component-scanning is applied only to com.jcombat.controller package, so Spring can auto-detect the application controller.

When making an HTTP request, we can specify what type of response we would like to have by setting the Accept header property. But due to improper working of the browsers with Accept headers, we mostly prefer ignoring the Accept headers in a Spring based web applications, which returns output in formats other than the HTML.

With Java Activation Framework (JAF), we don’t need to explicitly specify the media type mappings, instead it gets implicitly done by JAF. To use JAF, we might need to add an extra dependency of activation.jar. Probably we just want to support two output formats i.e. JSON and XML, therefore we are opting out of it and rather specifying the media type mappings explicitly.

It’s now time to write the controller, which should be like specified below.

EmployeeController.java

package com.jcombat.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
 
import com.jcombat.bean.Employee;
 
@Controller
public class EmployeeController {
 
	@RequestMapping(value = "/employeeData", method = RequestMethod.GET, produces={"application/xml", "application/json"})
	public @ResponseBody Employee getEmployee() {
		Employee employee = new Employee();
		employee.setEmailId("abc@gmail.com");
		employee.setEmpId("123");
		employee.setName("Ajit");
		return employee;
	}
}

3. Useful Links

4. Running the application

When we run the application, below is what we see.

JSON Output

json

XML Output

xml

5. Download the source code

Download the source code

Reference: Content Negotiation in Spring Framework from our JCG partner Abhimanyu Prasad at the jCombat blog.

Abhimanyu Prasad

Abhimanyu is a passionate tech blogger and senior programmer, who has an extensive end-to-end development experience with wide range of technologies. He is the founder and administrator at jCombat.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button