Spring 4 MVC REST Service Example using @RestController

Spring provides first class support for developing REST services. In this article, we will be developing a Spring 4 MVC based RESTful JSON service & RESTful XML service using Spring 4 @RestController annotation. Spring, behind the scenes, uses HttpMessageConverters to convert the response into desired format [ JSON/XML/etc..] based on certain libraries available on the classpath and optionally, Accept Headers in request.

In order to serve JSON, we will be using Jackson library [jackson-databind.jar]. For XML, we will use Jackson XML extension [jackson-dataformat-xml.jar]. Mere presence of these libraries in classpath will trigger Spring to convert the output in required format. Additionally, We will go a step further by annotating the domain class with JAXB annotations to support XML in case Jackson’s XML extension library is not available for some reason.

Note: If you are sending the request by just typing the URL in browser, you may add the suffix [.xml/.json] which help spring to determine the type of content to be served.

In case you want to dive bit deeper in details, have a look at Spring MVC 4 RESTFul Web Services CRUD Example+RestTemplate post.


Following technologies being used:

  • Spring 4.3.0.RELEASE
  • jackson-databind 2.7.5
  • jackson-dataformat-xml 2.7.5
  • Maven 3
  • JDK 1.7
  • Tomcat 8.0.21
  • Eclipse MARS.1

Let’s begin.

Step 1: Create the directory structure

Post Creating a maven web project with eclipse contains step-by-step instruction to create a maven project with eclipse.

Following will be the final project structure:

Spring4MVCHelloWorldRestServiceDemo_img1

We will be using Spring Java configuration with no xml. Now let’s add/update the content mentioned in above project structure.

Step 2: Update pom.xml with required dependencies

<?xml version="1.0"?>
<project
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
	xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.websystique.springmvc</groupId>
	<artifactId>Spring4MVCHelloWorldRestServiceDemo</artifactId>
	<packaging>war</packaging>
	<version>1.0.0</version>
	<name>Spring4MVCHelloWorldRestServiceDemo Maven Webapp</name>

	<properties>
		<springframework.version>4.3.0.RELEASE</springframework.version>
		<jackson.library>2.7.5</jackson.library>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${springframework.version}</version>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
		</dependency>
		<dependency>
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-databind</artifactId>
		    <version>${jackson.library}</version>
		</dependency>
		<dependency>
    		<groupId>com.fasterxml.jackson.dataformat</groupId>
    		<artifactId>jackson-dataformat-xml</artifactId>
    		<version>${jackson.library}</version>
		</dependency>
	</dependencies>


	<build>
		<pluginManagement>
			<plugins>
				<plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.2</version>
                    <configuration>
                        <source>1.7</source>
                        <target>1.7</target>
                    </configuration>
                </plugin>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-war-plugin</artifactId>
					<version>2.4</version>
					<configuration>
						<warSourceDirectory>src/main/webapp</warSourceDirectory>
						<warName>Spring4MVCHelloWorldRestServiceDemo</warName>
						<failOnMissingWebXml>false</failOnMissingWebXml>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>

		<finalName>Spring4MVCHelloWorldRestServiceDemo</finalName>
	</build>
</project>

Main dependencies to be noticed here are Jackson library (jackson-databind) which will be used to convert the response data into JSON string, and Jackson XML Extension library (jackson-dataformat-xml) which will help to provide XML converted response. Again, if the jackson-dataformat-xml is not included, only JSON response will be served, unless the domain object is annotated explicitly with JAXB annotations.

Step 3: Add a Pojo/domain object

package com.websystique.springmvc.domain;

public class Message {

	String name;
	String text;

	public Message(String name, String text) {
		this.name = name;
		this.text = text;
	}

	public String getName() {
		return name;
	}

	public String getText() {
		return text;
	}

}

Above object will be returned from controllers and converted by Jackson into JSON format. If the jackson-dataformat-xml is present, then it can also be converted into XML.

Step 4: Add a Controller

Add a controller class under src/main/java with mentioned package as shown below.

package com.websystique.springmvc.controller;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.websystique.springmvc.domain.Message;

@RestController
public class HelloWorldRestController {

	@RequestMapping("/")
	public String welcome() {//Welcome page, non-rest
		return "Welcome to RestTemplate Example.";
	}

	@RequestMapping("/hello/{player}")
	public Message message(@PathVariable String player) {//REST Endpoint.

		Message msg = new Message(player, "Hello " + player);
		return msg;
	}
}

@PathVariable indicates that this parameter will be bound to variable in URI template. More interesting thing to note here is that here we are using @RestController annotation, which marks this class as a controller where every method returns a domain object/pojo instead of a view. It means that we are no more using view-resolvers, we are no more directly sending the html in response but we are sending domain object converted into format understood by the consumers. In our case, due to jackson library included in class path, the Message object will be converted into JSON format[ or in XML if either the jackson-dataformat-xml.jar is present in classpath or Model class i annotated with JAXB annotations].

Step 5: Add Configuration Class

package com.websystique.springmvc.configuration;

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

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.websystique.springmvc")
public class HelloWorldConfiguration {
	

}

Here this class is mainly providing the component-scanning and annotation support.Note that we don’t have any view-resolvers configured as we don’t need one in Rest case.

Step 6: Add Initialization class

Add an initializer class as shown below(which in this case acts as replacement of any spring configuration defined in web.xml). During Servlet 3.0 Container startup, this class will be loaded and instantiated.

package com.websystique.springmvc.configuration;

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

public class HelloWorldInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { HelloWorldConfiguration.class };
	}
 
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}
 
	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}

}

Step 7: Build and Deploy the application

Now build the war (either by eclipse using m2e plugin) or via maven command line( mvn clean install). Deploy the war to a Servlet 3.x container . Since here i am using Tomcat, i will simply put this war file into tomcat webapps folder and click on startup.bat inside tomcat bin directory.

In order to test it, you can use either the browser or a true-client.POSTMAN is a nice tool to test your REST Endpoints as in a real scenario. Advantage of Postman is that you can send the “Accept” header along with request which will then be used by Spring while sending the response in required format. With browsers it is not so straight-forward to send the “Accept” Header but you can suffix the URL with format[.json/.xml] to get similar results.

Let’s start with the browser.
Spring4MVCHelloWorldRestServiceDemo_img2

Now let’s access the REST Endpoint. Please note that since we have included the jackson-dataformat-xml.jar in classpath, the response you will get will be XML.

Spring4MVCHelloWorldRestServiceDemo_img3_2

If you want Spring to serve JSON response instead, you can either
– remove the jackson-dataformat-xml.jar [comment it in pom.xml, build and deploy it again].
– Or Suffix the URL with .json

Had you redeployed the app with removing the dataformat dependency, you would have seen the following:
Spring4MVCHelloWorldRestServiceDemo_img3_1
Without redeployment, you can get the same result by suffixing url with format.

Spring4MVCHelloWorldRestServiceDemo_img3_3
Using Postman:
Set the ‘Accept’ request header [to appliction/json or application/xml ] and send the request. Check the response body:
Spring4MVCHelloWorldRestServiceDemo_img4_1
Spring4MVCHelloWorldRestServiceDemo_img4_2
With JAXB
In case jackson-dataformat-xml.jar is not available, and you still want to get the XML response, just by adding JAXB annotations on model class (Message), we can enable XML output support. Below is the demonstration of same :

package com.websystique.springmvc.domain;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "player")
public class Message {

	String name;
	String text;

	public Message(){
		
	}
	
	public Message(String name, String text) {
		this.name = name;
		this.text = text;
	}

	@XmlElement
	public String getName() {
		return name;
	}
	
	@XmlElement
	public String getText() {
		return text;
	}

}

Remove dataformat dependency[jackson-dataformat-xml.jar], Compile, deploy and run it again, Send the request, you should see following response:

Spring4MVCHelloWorldRestServiceDemo_img5_1

Spring4MVCHelloWorldRestServiceDemo_img4_1

Spring4MVCHelloWorldRestServiceDemo_img5_2

Spring4MVCHelloWorldRestServiceDemo_img3_3

That’s it. Check out Spring MVC 4 RESTFul Web Services CRUD Example+RestTemplate post for more advanced example.

Download Source Code



References

If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help me improve further our learning process.

If you appreciate the effort I have put in this learning site, help me improve the visibility of this site towards global audience by sharing and linking this site from within and beyond your network. You & your friends can always link my site from your site on www.websystique.com, and share the learning.

After all, we are here to learn together, aren’t we?

  • Samrat Roy

    Using this code , Jboss EAP will throw 404 . It is a simple fix , in the HelloWorldInitializer class , getServletMappings() method , return “/*” instead of “/”

    • websystique

      Thanks for pointing it out Samrat.

  • Vinay Yadav

    Example works fine .But i have a question from where json/xml object is being produced ? simply i want to ask who is taking care of creating json object.

    • websystique

      Hi Vinay, First of all. this application doesn’t involve any tradition view resolver. Before delivering the response [can be anything] , spring will try to convert the response into appropriate format the client is interested in. To convert, it relies on presence of certain libraries in classpath + any other input from client[Accept header/url suffix extension].If nothing is specified from client,Spring will generate the JSON response by default. If client asked for XML, spring will try to convert the response into XML. You can help spring by annotating the file with appropriate JAXB annotations.
      Hope this helps.

  • Andrey Stepanov

    Thank you a lot for this great series.

    Can you please explain why welcome()-method of the controller returns here what is considered to be http response body, and not the name of the jsp-resource as was the case in ‘Hello World’ example ?

    Thank you in advance

    • websystique

      Hi Andrey, goal of welcome method was not to return the REST response but just to act as a ‘welcome page’ handler.Even this method is not required at all. You as a developer decide which part of your app will be available as a REST service.

  • bhormilind

    The problem is giving for ResponseEntity return type.If I return “string” by converting JSON object, then its working

  • bhormilind

    Hi, Whenever I am running this application on Tomcat, its working fine. but on Jboss EAP 6.4.0, its not working. please help

  • raaj

    Hi I meant to ask if it may be ok for me to use this project as base ground for the project at my company.

    Seeking your consent please.

    • websystique

      H Raaj, Yes you can use this project for your company’s internal projects. Glad you liked it.

      • raaj

        Thanks so very sincerely. Though ever part is done so well, I think the AbstractDao allows so easy to transition to JPA based entity manager factory.

  • Balasaheb Karjule

    Thanks for this article…..

  • Dariel R.

    Dariel

    • websystique

      Hi Daniel, I don;t have NetBeans setup at my side, but looking at 404 i can tell you it may be related with tomcat setup in your IDE. Look at Setup Tomcat With Eclipse, although this is for Eclipse, you may get idea about how to fix it in your IDE.

  • Pingback: Spring MVC @RequestBody @ResponseBody Example - WebSystique()

  • Nico Grossi

    Hello, this is a really good tutorial, I have just 1 question, how I can set a default page like tag, but in the Initialization class??

    Thanks

    • websystique

      Hi Nico, Sorry i missed your message. I am not aware of any official way to represent welcome-file-list with annotations, only the welcome page can be configured to return from controller method using default url mapping.

  • Suraj Kadam

    Hi, whenever i run it it shows hello World message, but when i typed hello/messi it shows HTTP Status 404 – /Spring4MVCHelloWorldRestServiceDemo/hello/messi, i dont know what it made wrong , i am following same as u do. still getting this error, by the way your tutorials are very help full, thx for sharing…..

    • websystique

      Hi Suraj, Sorry I missed your message. In case you could not solve your issue, let me know.

      • Suraj Kadam

        thx for replay, The issue has been solved.

  • Pingback: Example Of A Domain Name |()

  • Pingback: How to use Apache kafka with Spring mvc ? Is it possible? - spring-integration()

  • Paul C

    Thank you for sharing your knowledge. It’s very helpful.
    I had some sample Angular code in .jsp and it worked well. But if I change the file name to .html, I would get the HTTP 404 page. I think it must be the view-resolver issue but wasn’t able to figure out the correct syntax. I would greatly appreciate if you could post the answers. Thanks.

    • websystique

      Hey Paul,

      If i understood correctly, you are referring to templates and not only the data. In that case you need to configure view resolver.

      I would suggest you to visit this & this post. First one shows AngularJS with JSP using REST backend, and second one showing AngularJS with HTML templates, again using REST backend.

      Any doubts, let me know.

  • Lee Namkyu

    Thanks for sharing this article~

    • websystique

      Glad you liked it. You might want to go through this post which is bit more realistic.

  • 康大玮

    thank you ! idea run well.

    • websystique

      Hi,
      Great to see you liked it. You might want to go through this post which is bit more realistic.

  • cristian

    I was following you tutorial but when I run the application over Jboss the url localhost:8080/project/hello/something always shows Http get status 404 I’m using AbstractAnnotationConfigDispatcherServletInitializer, do you now why?

    • websystique

      Hi Cristian, i have tested this example on multiple versions of tomcat without any issue. I can try on JBoss as well. Which version of JBOSS are you using? How are you deploying [From within Eclipse or using JBoss Admin console]?

      • cristian

        Thanks for your quickly answer, the JBoss version is 7.1, and I use eclipse to deploy the application.

        • websystique

          Cristian, as you mentioned using Eclipse to deploy your app, May i ask you if you have successfully deployed any other maven based project till now with your eclipse+JBoss setup? What i want to know is whether your Eclipse+Jboss setup itself is working correctly?

          To help with that, I would recommend going through the post Setup Eclipse with Tomcat which details the steps for the setting up tomcat to deploy any project successfully. Although the steps here are for tomcat, somewhat similar setup should be applicable for JBoss. Can you try this please and let me know the findings? In the mean time, i will try to simulate your setup at my end.

          • cristian

            Im trying to run with tomact and I get the following error: WARNING: No mapping found for HTTP request with URI [/project/] in DispatcherServlet with name ‘dispatcher’, so where I must to setup the dispatcher?

          • websystique

            Hi Cristian, this is normal because in controller we have only one type mapping defined ['/hello/{something}']. It was sufficient to demonstrate this example [see the screenshots in post] but you can define additional mappings ['/' for example so that you can see something on home page].
            Try : http://localhost:8080/Spring4MVCHelloWorldRestServiceDemo/hello/bla

            Note: Try to use other browser than Eclipse default one (window->Web browser->..). Sometimes the default browser used by Eclipse does not perform very well.

          • cristian

            Thanks for you tutorial, to summary works over tomcat but not over jboss,maybe because I need and extra configurations.

  • Dillip Kumar

    Simple and good example to learn REST on Spring

  • RAJ GOPAL

    Hello @websystique:disqus Can you help me with how should i maintain the session.

  • Mack

    By the way, thanks for this post.

  • Mack

    I built the project and was able to deploy and test the service on Tomcat. But using the same war file on Jboss 7.1.1 did not work. I wasn’t able to hit the service the same way that I did using tomcat. Any idea why?

  • Kishore Saraswathula

    Can you please help me understand DI concept in the above example? Is there a way to avoid use of “new”

    • websystique

      Hey Kishore,

      The trivial example shown above is not really about DI concept. It’s mainly focused on Spring REST capabilities to serve a resource to a client using default HttpMessageConverters.

      For the DI concept, please have a look on this post.

      Let me know if i misunderstood your question.

  • Pingback: Mazi Muhlari — Link: Spring MVC 4 Rest Tutorial()

  • Pingback: Créer un projet Java Restful web avec le module Spring MVC, l’API Jackson JSON et l’API Deployd (PARTIE 3) | News IT, Tutoriels, curiosités…()

  • http://bschandramohan.blogspot.com Chandra

    Very helpful – Thanks. One question though – this app works for 4.0.6 Spring release BUT Not for 4.1.6. Unable to find the info in Spring release notes. Do you know the reason?

    • Olivier

      Same problem. The REST service returns a 406 HTTP error code. It looks like the problem deals with the data to JSON translation. But no problem with Spring 4.0.6.