Spring MVC 4 - @RestController example

Posted on September 18, 2017


Technologies used: Java SE 1.8 | Spring 4.3.10.RELEASE | Maven 3.3.9 | Eclipse Neon.3 | Apache Tomcat  7.0.47

When a handler method of @Controller class is annotated with @ResponseBody annotation, Spring writes the returned java object to the HTTP response body i.e. Spring transforms the java object to a format suitable for REST application, typically TEXT, JSON or XML.  For example -

@Controller
public class MyRestController {
   @GetMapping(path = "/get/xml", produces = MediaType.APPLICATION_XML_VALUE)
   public @ResponseBody String getXML() {
      return "<user><id>12</id><name>John</name></user>";
   }
}

The above example will produce the XML response without setting the response body in model or resolving any view.

Instead of annotating all handler method of a @Controller class with @RequestMapping annotation, you can annotate your class with @RestController annotation to produce the same result as produced by @ResponseBody and @Controller. For example -

@RestController
public class MyRestController {
   @GetMapping(path = "/get/xml", produces = MediaType.APPLICATION_XML_VALUE)
   public String getXML() {
      return "<user><id>12</id><name>John</name></user>";
   }
}

@RestController is a stereotype annotation that combines @ResponseBody and @Controller and serves only JSON, XML or custom content type.

In this post, I will show you how to use the @RestController annotation in Spring web MVC application for REST services.

Project structure

Review the following web project structure build using Maven build tool.

Spring-mvc-restcontroller.png

Related - How to create a web project using maven build tool in eclipse IDE.

Jar dependencies

Edit pom.xml file of your maven project and add the following dependencies in it.

<dependencies>
  <!-- Spring MVC Dependency -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.10.RELEASE</version>
  </dependency>
  
  <!-- Jackson API for JSON -->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.8.7</version>
  </dependency>
  
  <!-- Servlet Dependency -->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
  </dependency>
</dependencies>

REST Controller class

Create a @RestController class under com.boraji.tutorial.spring.controller package and write the following code in it.

MyRestController.java

package com.boraji.tutorial.spring.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.http.CacheControl;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/rest")
public class MyRestController {

   // Handler method to produce text response
   @GetMapping(path = "/get/text", produces = MediaType.TEXT_PLAIN_VALUE)
   public ResponseEntity<String> getText() {
      return ResponseEntity
            .ok()
            .body("Spring MVC - REST Controller Hello World example.");
   }

   // Handler method to produce JSON response
   @GetMapping(path = "/get/json", produces = MediaType.APPLICATION_JSON_VALUE)
   public ResponseEntity<List<String>> getJSON() {
      List<String> list = new ArrayList<>();
      list.add("One");
      list.add("Two");
      list.add("Three");
      return ResponseEntity
            .ok()
            .cacheControl(CacheControl.noCache())
            .body(list);
   }

   // Handler method to produce XML response
   @GetMapping(path = "/get/xml", produces = MediaType.APPLICATION_XML_VALUE)
   public ResponseEntity<String> getXML() {
      String xml = "<user><id>12</id><name>John</name></user>";
      return ResponseEntity
            .ok()
            .header("myheader", "myvalue") // add custom headers
            .body(xml);
   }

   // Handler method to consume JSON request and produce text response
   @PostMapping(path = "/post/json", consumes = MediaType.APPLICATION_JSON_VALUE, 
         produces = MediaType.TEXT_PLAIN_VALUE)
   public ResponseEntity<String> postJSON(@RequestBody List<String> body) {
      System.out.println(body);
      // Process request
      //....
      return ResponseEntity
            .ok()
            .body("Done");
   }

   // Handler method to consume XML request and produce text response
   @PostMapping(path = "/post/xml", consumes = MediaType.APPLICATION_XML_VALUE, 
         produces = MediaType.TEXT_PLAIN_VALUE)
   public ResponseEntity<String> postJSON(@RequestBody String body) {
      System.out.println(body);
      // Process request
      //....
      return ResponseEntity
            .ok()
            .body("Done");
   }
}

HttpEntity represents an HTTP request or response entity, consisting of headers and body. 

Spring web configuration

Create a web @Configuration class annotated with @EnableWebMvc and @ComponentScan.

WebConfig.java

package com.boraji.tutorial.spring.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.boraji.tutorial.spring.controller" })
public class WebConfig extends WebMvcConfigurerAdapter {

}

 

Servlet container initialization

Create a container initializer class by extending the AbstractAnnotationConfigDispatcherServletInitializer to bootstrap the Spring MVC application.

MyWebAppInitializer.java

package com.boraji.tutorial.spring.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

   @Override
   protected Class<?>[] getRootConfigClasses() {
      return new Class[] {};
   }

   @Override
   protected Class<?>[] getServletConfigClasses() {
      return new Class[] { WebConfig.class };
   }

   @Override
   protected String[] getServletMappings() {
      return new String[] { "/" };
   }
}

Build + Deploy + Run application

Use the following maven commands to build, package, deploy and run application.

mvn clean install  (This command triggers war packaging)

mvn tomcat7:run (This command run embedded tomcat and deploy war file automatically)

You can refer this link to learn how to run the above commands in Eclipse IDE.

 

In this example, I will use POSTMAN tool (A Chrome App) to test our rest controller.

In Postman tool, select request type GET.

Enter the http://localhost:8080/rest/get/text URL and click on SEND.

Spring-mvc-restcontroller-01.png

In Postman tool, select request type GET.

Enter the http://localhost:8080/rest/get/json URL and click on SEND.

Spring-mvc-restcontroller-02.png

In Postman tool, select request type GET.

Enter the http://localhost:8080/rest/get/xml URL and click on SEND.

Spring-mvc-restcontroller-03.png

In Postman tool, select request type POST.

Select raw option button to enter the JSON request message and content type as application/json.

Enter the http://localhost:8080/rest/post/json URL and click on SEND.

Spring-mvc-restcontroller-04.png

In Postman tool, select request type POST.

Select raw option button to enter the XML request and content type as application/xml.

Enter the http://localhost:8080/rest/post/xml URL and click on SEND.

Spring-mvc-restcontroller-05.png