Spring RESTful Web Service Example with JSON and Jackson using Spring Tool Suite

Spring MVC RESTful Web Service

Spring is today’s leading framework for building Java, Enterprise Edition (Java EE) applications. A recent Java Tools and Technology survey in 2014 revealed that Spring MVC is the most popular Web Framework with 40% usage. One additional feature that makes Spring MVC so appealing is that it now also supports REST (REpresentational State Transfer) for build Web Services.

Spring MVC RESTful Web Service with JSON response

In this example, our Spring MVC Restful web service returns the Issuer object to the user converted to JSON using our Jackson JSON API. For the purposes of this simple tutorial and so that a majority of the functionality could be tested via the browser’s URL I made most of the request methods GET. However, if we want to follow the CRUD operations correctly. Then the create should be a POST (which we have), the Update methods should use a PUT method, the DELETE should have used a DELETE and the selection or getter functions should have used GET. Subsequent tutorials have these methods being implemented correctly per their CRUD operations.

What is REST?

REST (REpresentational State Transfer) is an architectural style, and an approach to communications that is usually used when developing Web services. REST has gained in popularity over its contender SOAP (Simple Object Access Protocol) because REST is lighter in terms of bandwidth usage. RESTful services are much easier to implement and scale than SOAP. Thus REST is the chosen architecture by service providers like Facebook, Twitter, Amazon, Microsoft, and Google.

REST architecture describes six constraints. These constraints were described in Roy Fielding’s dissertation as Uniform Interface, Stateless, Cacheable, Client-Server, Layered-System, and Code On Demand.

  • Uniform Interface – Resources are manipulated via CRUD (create, read, update, delete) operations. CRUD operations are managed via PUT, GET, POST, and DELETE request methods.
  • Stateless – In REST the state is contained within the request itself, or as part of the URI, query-string parameters, body or in the headers. After processing the request, the state may be communicated back via the headers, status or response body.
  • Cacheable – Responses from the web service to its clients are explicitly labeled as cacheable or non-cacheable. This way, the service, the consumer, or one of the intermediary middleware components can cache the response for reuse in later requests.
  • Client Server – This is a key constraint, as it based on separations of concerns. The client/server requirement ensures that a distributed environment exists. It requires the client, that sends requests and a server component that receives the requests. After processing the request, the server may return a response to the client. Error responses may be transmitted as well, which requires the client to be responsible for taking any corrective action.
  • Layered System – A client should may not be able to tell whether it is connected directly to the end server, or to an intermediary along the way. Intermediary servers may add security policies, or improve scalability.
  • Code On Demand – This is an optional constraint. It allows a client to have logic locally via the ability to download and execute code from a remote server.

RESTful Web Services for CRUD Operations

RESTFul web services define the base URI (Universal Resource Identifier) for the web service, it also defines the end points of the service via links on the web. Resources are manipulated via CRUD (create, read, update, delete) operations. CRUD operations are managed via PUT, GET, POST, and DELETE request methods.

Getting Started

In order to run this tutorial yourself, you will need the following:

Creating the Rest Example in Spring

For this example, I will be using Spring Tool Suite (STS) as it is the best integrated development environment for building the Spring framework projects.

Open STS and click on File -> New -> New Spring Project or use the shortcut Alt + Shift + N. Next choose Spring MVC Project from the list of available templates.

 spring rest example

Maven Project Object Model (pom.xml)

This Maven POM file (pom.xml) was automatically created for us by Spring Tool Suite when we select Spring MVC Project template. I only really needed to add the Jackson dependency as this will generate the JSON response back to our clients.

<!-- Jackson  -->

Failure to add Jackson classes results in the following exception:

HTTP Status 406

The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request “accept” headers.

This happens because we are using annotation based response using @ResponseBody. Once we add the required class(es), Spring transforms data into JSON or XML format. In our case, @ResponseBody encodes the issuer object in the appropriate format based (JSON) on the accept header of request and the presence of Jackson libraries in the classpath.

rest error missing jackson
<?xml version="1.0" encoding="UTF-8"?>
<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">
    <!-- Spring -->
        <!-- Exclude Commons Logging in favor of SLF4j -->
    <!-- AspectJ -->

    <!-- Jackson  -->
    <!-- Logging -->

    <!-- @Inject -->
    <!-- Servlet -->
    <!-- Test -->

Configure Spring Web DispatcherServlet (dispatcher-servlet.xml)

Notice that Spring adds annotation-driven tag. This allows a developer to use any POJO as a controller and allows us to use tags like @Controller, @RequestMapping, @RequestParam, @ModelAttribute, and @ResponseBody. By adding annotation-driven we add support for automatic marshalling from object model to JSON/XML.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
  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.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

  <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
  <!-- Enables the Spring MVC @Controller programming model -->
  <annotation-driven />

  <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
  <resources mapping="/resources/**" location="/resources/" />

  <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
  <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/views/" />
    <beans:property name="suffix" value=".jsp" />
  <context:component-scan base-package="com.avaldes.tutorial" />

Configure DispatcherServlet (web.xml)

<?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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

RESTful Web Service End Points

1/tutorial/issuersGETReturns a list of all the issuers available
2/tutorial/issuer/{ticker}GETReturn the issuer based on the Ticker
3/tutorial/issuer/delete/{ticker}GETDelete the issuer in the data store based on the Ticker
4/tutorial/issuer/createPOSTInserts the issuer into the data store based on the contents of the form

Model Class (Issuer.java)

This Model class called Issuer is just a POJO. According to Investopedia, An Issuer is, “A legal entity that develops, registers and sells securities for the purpose of financing its operations. Issuers may be domestic or foreign governments, corporations or investment trusts“. We will use this model to represent our data and serve as input and output for our Spring MVC Web Service.

package com.avaldes.model;

public class Issuer {
  private String ticker;
  private String issuerName;
  private String issuerType;
  private String country;
  public Issuer() {
  public Issuer(String ticker, String issuerName, String issuerType, String country) {
  public String getTicker() {
    return ticker;
  public void setTicker(String ticker) {
    this.ticker = ticker;
  public String getIssuerName() {
    return issuerName;
  public void setIssuerName(String issuerName) {
    this.issuerName = issuerName;
  public String getIssuerType() {
    return issuerType;
  public void setIssuerType(String issuerType) {
    this.issuerType = issuerType;
  public String getCountry() {
    return country;
  public void setCountry(String country) {
    this.country = country;
  public String toString() {
    return "[" + getTicker() 
        + ", " + getIssuerName()
        + ", " + getIssuerType()
        + ", " + getCountry()
        + "]";

Controller Class (RestController.java)

Our RestController class is the main class that contains all web service mapping end points defined in our table above. The @Controller annotation indicates that this particular class is playing the role of a controller.

I am using a Map of Issuers as our data store. This data store is being initialized with ten well known issuers inside of the default constructor of RestController. Our key of each of the objects is the Ticker.

The @RequestMapping annotation tells Spring that the this method will process requests beginning with /issuers in the URL path. You will also notice, that I have added method=RequestMethod.GET parameter. This parameter states that it will only handle requests using HTTP GET. @ResponseBody is used to return the complete MAP containing all the issuers. This request will be converted to JSON by the Jackson libraries in the classpath.

For the getIssuerByTicker method I have added @RequestMapping(value=”/issuer/{ticker} annotation with a value of /issuer/{ticker} to signify the end point of this operation accepting a method of GET method=RequestMethod.GET.

I have added @ResponseBody annotation, which states that the return of this method will be bound to the web response body.

Using the @PathVariable annotation allows a path variable in the URI to be injected as a parameter. This is the simplest way to extract parameters from the URIs in REST Web Services.

For the addIssuer method you will notice the @ModelAttribute(“issuer”) annotation as a method parameter. Using this annotation, will actually save quite a bit of work because instead of @PathVariable for each parameter, we can use @ModelAttribute for the entire model and let Spring populate the entire model and all its respective fields from the addIssuer JSP Form.

package com.avaldes.tutorial;

import java.text.DateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
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.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.avaldes.model.Issuer;

 * Handles requests for the application home page.
public class RestController {
  private static final Logger logger = LoggerFactory.getLogger(RestController.class);
  private Map<String, Issuer> issuers = new HashMap<String, Issuer>();
  public RestController() {
    // pre-initialize the list of issuers available ...
    issuers.put("ATEN", new Issuer("ATEN", "A10 Networks Inc", "corp", "USA"));
    issuers.put("AAPL", new Issuer("AAPL", "Apple Inc", "corp", "USA"));
    issuers.put("T", new Issuer("T", "AT&T", "corp", "USA"));
    issuers.put("CSCO", new Issuer("CSCO", "Cisco Systems, Inc.", "corp", "USA"));
    issuers.put("CTXS", new Issuer("CTXS", "Citrix Systems, Inc.", "corp", "USA"));
    issuers.put("GOOGL", new Issuer("GOOGL", "Google Inc", "corp", "USA"));
    issuers.put("IBM", new Issuer("IBM", "IBM", "corp", "USA"));
    issuers.put("JNPR", new Issuer("JNPR", "Juniper Networks, Inc.", "corp", "USA"));
    issuers.put("MSFT", new Issuer("MSFT", "Microsoft Corporation", "corp", "USA"));
    issuers.put("ORCL", new Issuer("ORCL", "Oracle Corporation", "corp", "USA"));
   * Simply selects the home view to render by returning its name.
  @RequestMapping(value = "/", method = RequestMethod.GET)
  public String home(Locale locale, Model model) {
    logger.info("Welcome home! The client locale is {}.", locale);
    Date date = new Date();
    DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
    String formattedDate = dateFormat.format(date);
    model.addAttribute("serverTime", formattedDate );
    return "status";
  @RequestMapping(value="/issuers", method=RequestMethod.GET)
  public Map<String, Issuer> getAllIssuers() {
    logger.info("Inside getAllIssuers() method...");
    return issuers;
  @RequestMapping(value="/issuer/{ticker}", method=RequestMethod.GET)
  public Issuer getIssuerByTicker(@PathVariable("ticker") String ticker) {
    Issuer myIssuer = issuers.get(ticker); 
    if (myIssuer != null) {
      logger.info("Inside getIssuerByTicker, returned: " + myIssuer.toString());
    } else {
      logger.info("Inside getIssuerByTicker, ticker: " + ticker + ", NOT FOUND!");
    return myIssuer; 

  @RequestMapping(value="/issuer/delete/{ticker}", method=RequestMethod.GET)
  public Issuer deleteIssuerByTicker(@PathVariable("ticker") String ticker) {
    Issuer myIssuer = issuers.remove(ticker); 
    if (myIssuer != null) {
      logger.info("Inside deleteIssuerByTicker, deleted: " + myIssuer.toString());
    } else {
      logger.info("Inside deleteIssuerByTicker, ticker: " + ticker + ", NOT FOUND!");
    return myIssuer;

  @RequestMapping(value="/issuer/create", method=RequestMethod.GET)
  public ModelAndView addIssuer() {
    return new ModelAndView("addIssuer", "command", new Issuer());
  @RequestMapping(value="/issuer/addIssuer", method=RequestMethod.POST)
  public Issuer addIssuer(@ModelAttribute("issuer") Issuer issuer) {
    if (issuer != null) {
      logger.info("Inside addIssuer, adding: " + issuer.toString());
    } else {
      logger.info("Inside addIssuer...");
    issuers.put(issuer.getTicker(), issuer);
    return issuer; 

Add Issuer View (addIssuer.jsp)

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="f" %>
<%@ page session="false" %>
    <f:form method="POST" action="addIssuer">
          <td><f:input path="ticker" size="10" maxlength="10"></f:input></td>
          <td>Issuer Name:</td>
          <td><f:input path="issuerName" size="30"></f:input></td>
          <td>Issuer Type:</td>
          <td><f:input path="issuerType" size="6"></f:input></td>
          <td><f:input path="country" size="20"></f:input></td>
          <td colspan="2"><input type="submit" value="Add Issuer"></td>

Complete Project Overview

I have added the project overview to give you a full view of the structure and show you all files contained in this sample project.

spring rest sts project

Testing Our RESTful Service using Chrome

Now its time to deploy the code and test it our using any web browser. In my case, I will be using Google Chrome browser. The following screenshots will give you a good idea of the running code.

Get a List of All Issuers

As you can see from the screenshot below, we have a properly formatted JSON string containing all the issuers available in the local data store.

issuer get all

Get Issuer By Ticker (IBM)

Using this end point URI /issuer/IBM, we are able to get the Issuer using the Ticker from the local data store and display the contents as a JSON formatted string in the response body of the HTTP message.

issuer get by ticker ibm

Get Issuer By Ticker (GOOGL)

issuer get by ticker googl

Delete Issuer By Ticker (MSFT)

Using this end point URI /issuer/delete/MSFT, we are able to delete the Issuer using the Ticker from the local data store and display the contents as a JSON formatted string in the response body of the HTTP message. At this point Microsoft will be removed from the local MAP data store.

issuer delete by ticker msft

To make things a little more interesting, I will also remove AT&T (T), Google (GOOGL), and IBM (IBM) from the data store and display the newly updated data store after the operation.

issuer get all after delete

Adding an Issuer Using Online Form

Using this online form JSP we will go ahead and add a new issuer. I will add avaldes.com as the new issuer and see what happens. Once we submit the form, our REST service handler will map the incoming POST request to the addIssuer() method and process the form elements using the @ModelAttribute directly into the Issuer object for us. We could have used @RequestParam on each field in the Issuer entity but that would have resulted in a lot more coding and for possibility of additional bugs. Using Spring MVC, we just avoided a ton of extra work. Let’s work smarter, not harder!

issuer add form
issuer add processed
issuer get all after add

Download the Code

That’s It!

I hope you enjoyed this tutorial. It was certainly a lot of fun putting it together and testing it out. Please continue to share the love and like us so that we can continue bringing you quality tutorials. Happy Coding!!!

spring mvc rest

Related Spring Posts

  • Creating Hello World Application using Spring MVC on Eclipse IDE
    In this tutorial we will go into some detail on how to set up your Eclipse IDE environment so that you can develop Spring MVC projects. In this post, we will create our first Spring MVC project with the all to familiar “Hello World” sample program.
  • Spring MVC Form Handling Example
    The following tutorial will guide you on writing a simple web based application which makes use of forms using Spring Web MVC framework. With this web application you will be able to interact with the customer entry form and enter all of the required values and submit them to the backend processes. I have taken the liberty of using CSS to beautify and transform the HTML page from a standard drab look and feel to a more appealing view.
  • Spring @RequestHeader Annotation Example
    In this tutorial, we will discuss the different ways that Spring MVC allow us to access HTTP headers using annotation. We will discuss how to access individual header fields from the request object as well accessing all the headers by supplying Map and then iterating through the LinkedHashMap collection. We will also show you how to set the headers in the response object.
  • Spring MVC Exception Handling using @ExceptionHandler with AngularJS GUI
    Good exception handling is a essential part of any well developed Application Framework and Spring MVC is no exception — pardon the pun. Spring MVC provides several different ways to handle exceptions in our applications. In this tutorial, we will cover Controller Based Exception Handling using the @ExceptionHandler annotation above the method that will handle it.
  • Spring RESTful Web Service Example with JSON and Jackson using Spring Tool Suite
    For this example, I will be using Spring Tool Suite (STS) as it is the best integrated development environment for building the Spring framework projects. Spring is today's leading framework for building Java, Enterprise Edition (Java EE) applications. One additional feature that makes Spring MVC so appealing is that it now also supports REST (REpresentational State Transfer) for build Web Services.
  • Spring MVC RESTful Web Service Example with Spring Data for MongoDB and ExtJS GUI
    This post will show another example of how to build a RESTful web service using Spring MVC 4.0.6, Spring Data for MongoDB 1.6.1 so that we can integrate the web application with a highly efficient datastore (MongoDB 2.6). In this tutorial we will walk you through building the web service and NoSQL database backend and show you how to implement CRUD (Create, Read, Update and Delete) operations.
  • Building DHTMLX Grid Panel User Interface with Spring MVC Rest and MongoDB Backend
    In this tutorial we will show how easy it is to use DHTMLX dhtmlxGrid component while loading JSON data with Ajax pulling in data from the Spring MVC REST web service from our MongoDB data source. You will see how simple it is to create a visually appealing experience for your client(s) with minimal javascript coding.
  • Spring MVC with JNDI Datasource for DB2 on AS/400 using Tomcat
    In this tutorial we will discuss how to set up Spring MVC web services and configure a JNDI Datasource using Tomcat and connect to IBM DB2 Database on a AS/400. JNDI (Java Naming and Directory Interface) provides and interface to multiple naming and directory services.
  • Java Spring MVC Email Example using Apache Velocity
    In this tutorial we will discuss how to set up a Java Spring MVC RESTful Webservice with Email using Apache Velocity to create a Velocity template that is used to create an HTML email message and embed an image, as shown below, using MIME Multipart Message.
  • Implementing Basic and Advanced Search using Angular Material Design, Grid-UI, Spring MVC REST API and MongoDB Example
    In this tutorial we will discuss how to implement basic and advanced search techniques in MongoDB using AngularJS and Google’s Material Design with Spring MVC REST API backend. The advanced search user interface (UI) will use logical operators and build a JSON object which contains the search field name, boolean or logical operator and the search value.
  • Spring MVC Interceptor using HandlerInterceptorAdapter Example
    In this tutorial we will discuss how to use the HandlerInterceptorAdapter abstract class to create a Spring MVC interceptor. These interceptors are used to apply some type of processing to the requests either before, after or after the complete request has finished executing.

Please Share Us on Social Media


Leave a Reply

Your email address will not be published. Required fields are marked *