Workshop 7
Workshop 7
In many ways, the World Wide Web itself, based on HTTP, can be viewed as a REST-
based architecture. RESTful applications use HTTP requests to post data (create and/or
update), read data (e.g., make queries), and delete data. Thus, REST uses HTTP for all
four CRUD (Create/Read/Update/Delete) operations.
REST Guidelines
RESTful systems typically, but not always, communicate over Hypertext Transfer
Protocol (HTTP) with the same HTTP verbs (GET, POST, PUT, DELETE, etc.) that web
browsers use to retrieve web pages and to send data to remote servers. REST systems
interface with external systems as web resources identified by Uniform Resource
Identifiers (URIs), for example /people/tom, which can be operated upon using standard
verbs such as GET /people/tom.
With the representational state transfer (REST) style architecture, requests and
responses are built around the transfer of representations of resources. Resources are
identified by global IDs that typically use a uniform resource identifier (URI). Client
applications use HTTP methods (such as GET, POST, PUT, or DELETE) to manipulate
the resource or collection of resources. Generally, a GET method is used to get or list
the resource or collection of resources, POST is used to create, PUT is used to update
or replace, and DELETE is for removing the resource.For example, GET
http://host/context/employees/12345 gets the representation of the employee with the ID
12345.
In Rest based design, resources are being manipulated using a common set of verbs.
Often Rest based Web services return JSON or XML as response, although it is not
limited to these types only. Clients can specify (using HTTP Accept header) the
resource type they are interested in, and server may return the resource ,
specifying Content-Type of the resource it is serving
Advantages of REST
Level 0-HTTP
Level 1- Resources: This is the starting level for Restful APIs. In this model, we
have to define individual URIs for each resources. A resource is a unique
identifier for an element [ user, tweet etc]. In above example,
- request to /api/user/ returns a list of users
- request to /api/user/1 returns the user with ID 1
- request to /api/user/ with a user object as JSON creates a new user
- request to /api/user/3 with a user object as JSON updates the user with ID 3
- request to /api/user/4 deletes the user with ID 4
- request to /api/user/ deletes all the users
Level 2-HTTP Verbs: If your APIs use different HTTP verbs(GET,PUT,DELETE,
POST etc) for different operations using resource URIs, then you are in level 2.
URIs specify the resources that are operated on and the HTTP method specifies
what the operation is. In this level, we also make use of various HTTP status
codes. You can easily guess how the above API that we had created earlier is in
Level 2.
Level 3- Hypermedia Controls: If your API implements HAETOS (Hypermedia As
The Engine Of Application State). To comply this level, the responses should
have the links that controls the application state for the client. In other words,
responses have links that client can use. For instance, after the creation of
resource with PUT, the server should return a response with a code 201
CREATED and send the Location header containing the URI of the created
resource. Our controller shown above uses this while creating a user
We can include URIs in client response in different ways. There is no standard
that defines how the link should look.
Following example uses Rest based controller, implementing REST API. This is what
the controller REST API does:
Let us create a sample application that uses REST principles as shown below. We call
the below application as REST API:
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;
import com.fasterxml.jackson.annotation.JsonView;
import ch7.restdemo.model.Message;
import ch7.restdemo.model.User;
import ch7.restdemo.model.View;
import ch7.restdemo.service.MyService;
@RestController
public class MyRestController {
@Autowired
MyService myservice;
@JsonView(View.Summary.class)
@RequestMapping("/hello/{player}")
public Message message(@PathVariable String player) {//REST
Endpoint.
System.out.println("Hello World");
List<User> users =myservice.displayAllUsers();
if(users.isEmpty()){
return new
ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);//You many decide to
return HttpStatus.NOT_FOUND
}
return new ResponseEntity<List<User>>(users,
HttpStatus.OK);
}
//Retrieve user with id=some value
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<User> getUser(@PathVariable("id") long id)
{
System.out.println("Fetching User with id " + id);
User user=myservice.getUserById(id);
if(user==null)
{
return new
ResponseEntity<User>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<User>(user,HttpStatus.OK);
}
@RequestMapping(value = "/user/", method = RequestMethod.POST)
public ResponseEntity<Void> createUser(@RequestBody User user,
UriComponentsBuilder ucBuilder) {
System.out.println("Creating User " + user.getName());
if (myservice.isUserExist(user)) {
System.out.println("A User with name " + user.getName() + "
already exist");
return new ResponseEntity<Void>(HttpStatus.CONFLICT);
}
myservice.saveUser(user);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/user/{id}").buildAndExpand(user.get
Id()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
@RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)
public ResponseEntity<User> updateUser(@PathVariable("id") long
id, @RequestBody User user) {
System.out.println("Updating User " + id);
User current=myservice.getUserById(id);
if(current==null)
{
System.out.println("User With ID="+id+" Does Not
Exist");
return new
ResponseEntity<User>(HttpStatus.NOT_FOUND);
}
current.setName(user.getName());
current.setAge(user.getAge());
current.setSalary(user.getSalary());
myservice.updateUser(current);
return new ResponseEntity<User>(user,HttpStatus.OK);
}
@RequestMapping(value = "/user/{id}", method =
RequestMethod.DELETE)
public ResponseEntity<User> deleteUser(@PathVariable("id") long
id) {
System.out.println("Fetching & Deleting User with id " +
id);
myservice.deleteUserById(id);
return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
}
@RequestMapping(value = "/user/", method = RequestMethod.DELETE)
public ResponseEntity<User> deleteAllUsers() {
System.out.println("Deleting All Users");
myservice.deleteAllUsers();
return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
}
}
4. Create following files inside ch7.restdemo.model package
A
package ch7.restdemo.model;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlRootElement;
import com.fasterxml.jackson.annotation.JsonView;
@XmlRootElement
public class User implements Serializable {
package ch7.restdemo.service;
import java.util.List;
import ch7.restdemo.model.User;
List<User> displayAllUsers();
}
////////
package ch7.restdemo.service;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import ch7.restdemo.model.User;
static{
users= populateDummyUsers();
@Override
return users;
return users;
@Override
for(User user:users)
if(user.getId()==id)
return user;
return null;
// Before saving the user, We need to check whether a particular user already
exists
@Override
String uname=user.getName();
for(User u:users)
{
if(uname.equalsIgnoreCase(u.getName()))
return true;
return false;
user.setId(counter.incrementAndGet());
users.add(user);
@Override
int index=users.indexOf(user);
users.set(index, user);
@Override
if (user.getId() == id) {
iterator.remove();
@Override
users.clear();
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-
cache.xsd">
<mvc:annotation-driven >
<mvc:message-converters>
<bean
class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessag
eConverter"/>
<bean
class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessag
eConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
</beans>
@RestController : First of all, we are using Spring 4′s new @RestController annotation.
This annotation eliminates the need of annotating each method with @ResponseBody.
Under the hood, @RestController is itself annotated with @ResponseBody, and can be
considered as combination of @Controller and @ResponseBody.
@RequestBody : If a method parameter is annotated with @RequestBody, Spring will
bind the incoming HTTP request body(for the URL mentioned in @RequestMapping for
that method) to that parameter. While doing that, Spring will [behind the scenes] use
HTTP Message converters to convert the HTTP request body into domain object
[deserialize request body to domain object], based on ACCEPT or Content-Type header
present in request.
@ResponseEntity is a real deal. It represents the entire HTTP response. Good thing
about it is that you can control anything that goes into it. You can specify status code,
headers, and body. It comes with several constructors to carry the information you want
to sent in HTTP Response.
Postman
https://chrome.google.com/webstore/detail/postman/
fhbjgbiflinjbdggehcddcbncdddomop?hl=en
2. After Downloading, open the exe file and Click on "ADD TO CHROME" button.
3. Open all Apps that come up with Chrome browser using following URLs
chrome://apps/
4. Now Run REST API above by Right Clicking your Project->Run As-> Run on
Server and test Rest API as shown below:
ii) Retrieve a Single User: In above example, we retrieved all users's at once,
however to retrieve a single user whose id=1, you have to specify following
URI as shown below:
iii) Create User: Select Request type as "POST" and enter following URI. Click
on Body Tab, check on "Raw", select JSON(application/json) from the down
arrow box (by default Text is selected), enter following information about the
user that you want to create and click on "Send" button as shown below:
You will see the following while clicking the "Send" button:[ Scroll Down and
below section, Click on Headers tab]
You can see the URIs as part of response. This confirms that above REST API confirms
to Richardson maturity level 3.
If you test for the above URI, then you will get recently created users information as
shown below:
iv) Update User: Select Request type as "PUT" and enter following URI
containing id of the user whose information you want to update. Click on Body
Tab, check on "Raw", select JSON(application/json) from the down arrow box
(by default Text is selected), enter following new information about the user
with above id that you want to update and click on "Send" button as shown
below:
If you repeat test no 1 as shown above for user with id=5, you will see the
updated information.
v) Delete a User: Select Request type as "DELETE" and enter following URI to
delete a user with id=5
If you repeat test no 1 as shown above for user with id=5, you will see the
updated information.
vi) Delete All Users: Select Request Type as "DELETE" and enter following URL:
vii) Verify Whether all yours are deleted: Select Request Type as "GET" and
enter following URL:
In above example, we have used POSTMAN tool to test our REST API.
However, we can also develop our own TestClient program to test above REST
API. For this, create a package named ch7.restdemo.client inside src foloder and
create a class named TestClient Pro inside it and put following codes inside it:
Run above code[ Right Client TestClient->Run As->Java Application], it will test
every aspects of REST API that we had earlier tested using POSTMAN. You will
see following output after running above code:
Testing listAllUsers API-----------
User : id=1, Name=Sam, Age=30, Salary=70000.0
User : id=2, Name=Tom, Age=40, Salary=50000.0
User : id=3, Name=Jerome, Age=45, Salary=30000.0
User : id=4, Name=Silvia, Age=50, Salary=40000.0
Testing getUser API----------
User [id=1, name=Sam, age=30, salary=70000.0]
Testing create User API----------
Location : http://localhost:8080/RESTDemo/user/5
Testing listAllUsers API-----------
User : id=1, Name=Sam, Age=30, Salary=70000.0
User : id=2, Name=Tom, Age=40, Salary=50000.0
User : id=3, Name=Jerome, Age=45, Salary=30000.0
User : id=4, Name=Silvia, Age=50, Salary=40000.0
User : id=5, Name=Sarah, Age=51, Salary=134.0
Testing update User API----------
User [id=1, name=Tomy, age=33, salary=70000.0]
Testing listAllUsers API-----------
User : id=1, Name=Tomy, Age=33, Salary=70000.0
User : id=2, Name=Tom, Age=40, Salary=50000.0
User : id=3, Name=Jerome, Age=45, Salary=30000.0
User : id=4, Name=Silvia, Age=50, Salary=40000.0
User : id=5, Name=Sarah, Age=51, Salary=134.0
Testing delete User API----------
Testing listAllUsers API-----------
User : id=1, Name=Tomy, Age=33, Salary=70000.0
User : id=2, Name=Tom, Age=40, Salary=50000.0
User : id=4, Name=Silvia, Age=50, Salary=40000.0
User : id=5, Name=Sarah, Age=51, Salary=134.0
Testing all delete Users API----------
Testing listAllUsers API-----------
No user exist----------
XML Generation
Server response can be obtained on client side either in json format or XML format or
any other suitable format. To obtain server response in XML format at client do the
following steps:
import com.fasterxml.jackson.annotation.JsonView;
String name;
String text;
}
3. Put following additional method inside MyRestController class of
ch7.restdemo.controller package.
@RequestMapping("/hello/{player}")
public Message message(@PathVariable String player) {//REST
Endpoint.
ii) To get the json response type the following URL and specify "Accept" and
"application/json" to as shown below:
1. Create a class called View inside ch7.restdemo.model package and put following
codes inside it.
package ch7.restdemo.model;
System.out.println("Hello World");
List<User> users =myservice.displayAllUsers();
if(users.isEmpty()){
return new
ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);//You many decide to
return HttpStatus.NOT_FOUND
}
return new ResponseEntity<List<User>>(users,
HttpStatus.OK);
}
4. Run your REST API
5. Specify following URL in Postman, you will only see name and salary being
displayed.
Swagger Documentation
Swagger is a specification for documenting REST API. It specifies the format (URL,
method, and representation) to describe REST web services. Swagger is one of the
most popular frameworks for Restful API documentation. It provides documentation
generation and a user interface to display the documentation in an awesome manner.
Developers write client applications that can consult a beautiful UI that tells them how to
use the API. The UI even tells them what kind of documents the API expects. This UI
exists and is called Swagger UI.
Swagger is a documentation format for REST services that describes the methods and
models in your REST web service in a JSON format. Together with Swagger UI you get
a documentation format that is machine readable AND human readable. It also supports
experimenting with the API.
Sample Application
Reference:
1. http://stackoverflow.com/questions/671118/what-exactly-is-restful-programming
2. http://www.ibm.com/developerworks/library/wa-spring3webserv/
3. https://www.youtube.com/watch?v=NK3HNEwDXUk
4. http://www.journaldev.com/8934/spring-rest-xml-and-json-example
5. http://websystique.com/springmvc/spring-mvc-4-restful-web-services-crud-
example-resttemplate/
6. http://websystique.com/springmvc/spring-4-mvc-rest-service-example-using-
restcontroller/
7. https://rahulvishwakarma.wordpress.com/2014/06/01/show-off-your-spring-web-
services-through-swagger-just-like-that/
8. http://ufasoli.blogspot.com/2013/06/spring-mvc-and-swagger-generating_6.html
9. http://borislavroussanov.com/spring/integrate-swagger-ui-spring-mvc/
10. https://www.youtube.com/watch?v=bgzWvbvERV4&feature=youtu.be
11. http://www.thegamecontriver.com/2016/04/document-rest-api--swagger-2-spring-
mvc.html
12. http://www.peej.co.uk/articles/rest.html