Sample restful web service using Spring framework

Spring framework helps us to create good restful web service using the Spring's annotation based MVC framework.

In this example, I am using a) Spring Framework 3.1.1 b) maven 3.0.5 c) Apache Tomcat 6


Spring Controller class 

This class will serve as the restful handler class. In this class the methods getStudent(), getAllStudents()have the annotation RequestMapping maps the incoming HTTP request which matches the format /rest/student/{studId} will redirect to the method getStudent(), like that /rest/student/ will redirect to the getAllStudents() method. method = RequestMethod.GET says that the HTTP GET method process by this method. These method returns Student object in the JSON format to the client.

StudentController.java

package com.smash.webservices.rest;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import com.smash.domain.Student;
import com.smash.services.StudentService;
/**
 * StudentController class will expose a series of Restful end points
 */
@Controller
public class StudentController {

 @Autowired
 private StudentService studService;

 @Autowired
 private View jsonView;

 private static final String DATA_FIELD = "data";
 private static final String ERROR_FIELD = "error";

 private static final Logger log = Logger.getLogger(StudentController.class);
 @RequestMapping(value = "/rest/student/", method = RequestMethod.GET)
 public ModelAndView getAllStudents() {
  List studentList = null;

  try {
   studentList = studService.getAllStudents();
  } catch (Exception e) {
   String sMessage = "Error invoking getStudent";
   return getErrorJSON(String.format(sMessage, e.toString()));
  }

  log.debug("Returing Student: " + studentList.toString());
  return new ModelAndView(jsonView, DATA_FIELD, studentList);
 }
 @RequestMapping(value = "/rest/student/{studId}", method = RequestMethod.GET)
 public ModelAndView getStudent(@PathVariable("studId") String studId) {
  Student student = null;

  /* validate student Id parameter */
  if (isEmpty(studId) || studId.length() < 2) {
   String sMessage = "Error invoking getStudent - Invalid student Id parameter";
   return getErrorJSON(sMessage);
  }

  try {
   student = studService.getStudById(studId);
  } catch (Exception e) {
   String sMessage = "Error invoking getStudent. [%1$s]";
   return getErrorJSON(String.format(sMessage, e.toString()));
  }

  log.debug("Returing Student: " + student.toString());
  return new ModelAndView(jsonView, DATA_FIELD, student);
 }
 
 public static boolean isEmpty(String id) {
  return (null == id) || id.trim().length() == 0;
 }

 /**
  * Create an error REST response.
  * @param sMessage
  * @return
  */
 private ModelAndView getErrorJSON(String sMessage) {
  return new ModelAndView(jsonView, ERROR_FIELD, sMessage);
 }
 /**
  * Injector methods.
  *
  * @param studentService_p
  * the new student service
  */
 public void setStudentService(StudentService studService_p) {
  studService = studService_p;
 }
}

Service Class 

Rest handler class calls the service method to get the data for the view.
StudentService.java
package com.smash.services;

import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.smash.domain.Student;

@Service
public class StudentService {
 
 /**
  * Returns the student details based on ID
  * @param studentId
  * @return
  */
 public Student getStudById(String studentId) {
  Student student = new Student();

  student.setStudentId(studentId);
  student.setName("mark");
  student.setGender('M');
  student.setAddress("Dubai");
  return student;
 }
 /**
  * Returns all student details.From this class you can connect to database through impl-*ementation classes to get the real data
  * @param studentId
  * @return
  */
 public List getAllStudents() {
  Student student = new Student();

  student.setStudentId("101");
  student.setName("Mark");
  student.setGender('M');
  student.setAddress("Dubai");
  List sList= new ArrayList();
  sList.add(student);
  student = new Student();

  student.setStudentId("102");
  student.setName("Steve");
  student.setGender('M');
  student.setAddress("Dubai");
  sList.add(student);
  return sList;
 }
}

The Domain Class

Student.java
package com.smash.domain;

public class Student {
 private String studentId;
 private String name;
 private char gender;
 private String address;
      /*get and set methods here*/
     }

Web.xml file

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   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>REST Sample</display-name>

 <!--
  Main configuration file for this Spring web application.
 -->
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
   /WEB-INF/config/rest-services-config.xml
  </param-value>
 </context-param>

 <!--
  Loads the Spring web application context using the config file defined above.
 -->
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

 <!--
  Define the Spring Dispatcher Servlet for the REST services.
  The 'contextConfiguration' param with an empty value means that the
  Spring Context won't try to load a default file called restservices-servlet.xml
  -->
 <servlet>
  <servlet-name>restservices</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
   <param-name>contextConfigLocation</param-name>
   <param-value></param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <!--
  This Servlet mapping means that this Servlet will handle all incoming requests
  -->
 <servlet-mapping>
  <servlet-name>restservices</servlet-name>
  <url-pattern>/</url-pattern>
 </servlet-mapping>

</web-app>

Restful services configuration file

rest-services-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:oxm="http://www.springframework.org/schema/oxm"
  xmlns:util="http://www.springframework.org/schema/util"
  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.0.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-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/oxm
       http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd
       http://www.springframework.org/schema/util
         http://www.springframework.org/schema/util/spring-util-3.0.xsd">


 <!--
   Enables automatic mapping of fund objects to and from JSON
 -->
 <mvc:annotation-driven/>

 <!--
   Setup spring to pull in @Controller, @RequestMapping, etc Configuration scans specified packages
   for classes configured as Spring managed beans and automatically sets up objects annotated with
   @Controller, @Service etc.
 -->
    <context:component-scan base-package="com.smash.webservices.rest" />
 <context:component-scan base-package="com.smash.services" />

 <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
 <!--
   Configures view for returning JSON to the client
 -->
 <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
  <property name="contentType" value="text/plain"/>
 </bean>
 <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  <property name="messageConverters">
   <util:list id="beanList">
    <ref bean="jsonMessageConverter"/>
   </util:list>
  </property>
 </bean>
 <!--
   Converts JSON to POJO and vice versa
 -->
 <bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>

</beans>


Output of the restful web service

  • Get all the student details. URL: 
    http://localhost:8080/rest-sample/rest/student/
  • Get the student based on student Id, GET operation, URL: 
    http://localhost:8080/rest-sample/rest/student/11

Comments

  1. Hi, this is a very good example. Could you provide this example with JPA/mysql? Thanks in advance.

    ReplyDelete
  2. I got this error "The constructor ModelAndView(View, String, List) is undefined"

    from : return new ModelAndView(jsonView, DATA_FIELD, studentList);

    ReplyDelete
  3. Hi,
    Can you tell me what is the spring version you are using?

    ReplyDelete
  4. Please post the code for a sample client to make it easier to understand

    ReplyDelete

Post a Comment

Please type your comments here