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. Let’s get going.
Following technologies being used:
Let’s begin.
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:
We will be using Spring Java configuration with no xml. Now let’s add/update the content mentioned in above project structure.
<?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.
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.
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].
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.
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[] { "/" }; } }
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.
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.
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:
Without redeployment, you can get the same result by suffixing url with format.
Using Postman:
Set the ‘Accept’ request header [to appliction/json or application/xml ] and send the request. Check the response body:
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:
That’s it. Check out Spring MVC 4 RESTFul Web Services CRUD Example+RestTemplate post for more advanced example.
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 improve further our learning process.
In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…
Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…
Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…
Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…
Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…
This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…
View Comments
why is giving 404 on http://localhost:8080/Spring4MVCCRUDRestService/ url..?
great !!!!!
Hello,
I have downloaded and running Spring4MVCHelloWorldRestServiceDemo example as it is on weblogic sever.
But I am getting below error on chrome.
Error 403--Forbidden
From RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1:
10.4.4 403 Forbidden
Can you please help fixing this.
Thanks,
Hi Vaibhav, Sorry i don't have weblogic setup with me at the moment. Are you able to deploy a simple hello world to see if you are missing some basic weblogic configuration?
Using this code , Jboss EAP will throw 404 . It is a simple fix , in the HelloWorldInitializer class , getServletMappings() method , return "/*" instead of "/"
Thanks for pointing it out Samrat.
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.
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.
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
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.
The problem is giving for ResponseEntity return type.If I return "string" by converting JSON object, then its working
Hi, Whenever I am running this application on Tomcat, its working fine. but on Jboss EAP 6.4.0, its not working. please help
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.
H Raaj, Yes you can use this project for your company's internal projects. Glad you liked it.
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.
Thanks for this article.....