REST Project to return both JSON and XML Response using Spring ContentNegotiationManager
Overview
In this chapter we will implement the content negotiation for Spring Rest Webservices. Till now we have seen two projects, one project returned the response as xml and the other as JSON. But now suppose we we want to expose a single method as a REST webservice and this should return either xml or JSON depending on some user parameter. This is implemented using ContentNegotiation parameter defined by the Spring Framework. In the request url itself we specify the return type we want using some parameter.Lets Begin
We will create Eclipse Maven project as follows-The pom.xml is as follows-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.test</groupId> <artifactId>employee-management-system</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>employee-management-system Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.5.4</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.5.4</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.5.4</version> </dependency> </dependencies> <build> <finalName>employee-management-system</finalName> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.4</version> </plugin> </plugins> </build> </project>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <!-- Configure the Disptcher Servlet --> <servlet> <servlet-name>Dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Allow URLs with all extensions --> <servlet-mapping> <servlet-name>Dispatcher</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
Define the DispatcherServlet.xml to define the configuration for ContentNegotiation parameter.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <context:component-scan base-package="com.javainuse.controller" /> <context:component-scan base-package="com.javainuse.service" /> <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" /> <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <property name="favorPathExtension" value="false" /> <property name="favorParameter" value="true" /> <property name="parameterName" value="type" /> <!-- define the keys which will be specified in the URL to specify the return type --> <property name="mediaTypes"> <map> <entry key="json" value="application/json"></entry> <entry key="xml" value="application/xml" /> </map> </property> </bean> </beans>
package com.javainuse.domain; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Employee { private String empId; private String name; private String designation; private double salary; public Employee() { } public Employee(String empId, String name, String designation, double salary) { super(); this.setEmpId(empId); this.name = name; this.designation = designation; this.salary = salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDesignation() { return designation; } public void setDesignation(String designation) { this.designation = designation; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public String getEmpId() { return empId; } public void setEmpId(String empId) { this.empId = empId; } }
Define the service layer and its implementation as follows- Also in the Dispatcher-context.xml we have context:component-scan base-package="com.javainuse.service" Spring scans this particular package for a class annotated with @Component. The EmployeeService class will actually fetch all the required Employee information. Usually EmployeeService should call the EmployeeDAO which will return all items from the DataBase.But here we will mock the EmployeeService class to just return the list of items as follows. We are using the Programming to Interface concept here. You can read more about this in this chapter. So we create the EmployeeService.java and EmployeeServiceMockImpl.java as follows.
package com.javainuse.service; import java.util.List; import com.javainuse.domain.Employee; public interface EmployeeService { public List<Employee> getAllEmployees(); }
package com.javainuse.service; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Component; import com.javainuse.domain.Employee; @Component public class EmployeeServiceMockImpl implements EmployeeService { private List<Employee> testEmployees = new ArrayList<Employee>(); // populate the Employee List public EmployeeServiceMockImpl() { testEmployees.add(new Employee("1", "emp1", "M1", 10000)); testEmployees.add(new Employee("2", "emp2", "M2", 20000)); testEmployees.add(new Employee("3", "emp3", "M3", 30000)); testEmployees.add(new Employee("4", "emp4", "M4", 40000)); testEmployees.add(new Employee("5", "emp5", "M5", 50000)); testEmployees.add(new Employee("6", "emp6", "M6", 60000)); } // Return the Mocked Employee List public List<Employee> getAllEmployees() { return new ArrayList<Employee>(testEmployees); } }
No header information like headers="Accept=application/json" or headers="Accept=application/xml" is needed. Since the return type format is being specified by the ContentNegotiationManager in the configuration file.
package com.javainuse.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import com.javainuse.domain.Employee; import com.javainuse.service.EmployeeService; @Controller public class DisplayEmployeeController { @Autowired private EmployeeService employeeService; @RequestMapping(value = "/viewAllEmployees.do") @ResponseBody public Employee viewAllItems() { List<Employee> allEmployees = employeeService.getAllEmployees(); return allEmployees.get(0); } }
Hit the browser with the following URL for json response
http://localhost:8080/employee-management-system/viewEmployee/4?type=xml
Hit the browser with the following URL for json response
http://localhost:8080/employee-management-system/viewEmployee/4?type=json
Download Source Code
Download it - REST Project with ContentNegotiationManagerSee Also
REST Project to return XML Response REST Project to return JSON Response