Web services

Web services are self-contained, modular, distributed, dynamic applications that can be described, published, located, or invoked over the network to create products, processes, and supply chains. These applications can be local, distributed, or web-based. Web services are built on top of open standards such as TCP/IP, HTTP, Java, HTML, and XML.
A web service is a collection of open protocols and standards used for exchanging data between applications or systems. Software applications written in various programming languages and running on various platforms can use web services to exchange data over computer networks like the Internet in a manner similar to inter-process communication on a single computer. This interoperability (e.g., between Java and Python, or Windows and Linux applications) is due to the use of open standards.
There are two types of webservices
1.     SOAP
2.     RestFul
Difference between SOA and a Web service
SOA is a software design principle and an architectural pattern for implementing loosely coupled, reusable and coarse grained services. You can implement SOA using any protocols such as HTTP, HTTPS, JMS, SMTP, RMI, IIOP (i.e. EJB uses IIOP), and RPC etc. Messages can be in XML, JSON, TEXT or Data Transfer Objects (DTOs).
Web service is an implementation technology and one of the ways to implement SOA. You can build SOA based applications without using Web services – for example by using other traditional technologies like Java RMI, EJB, JMS based messaging, etc. But what Web services offer is the standards based and platform-independent service via HTTP, XML, SOAP, WSDL and UDDI, thus allowing interoperability between heterogeneous technologies such as J2EE, .NET and any other languages.

Soap
Restful
The SOAP WS is transport protocol neutral. Supports multiple protocols like HTTP , HTTPS,  TCP, UDP SMTP, etc
The REST is transport protocol specific. Supports only HTTP or HTTPS protocols
The SOAP WS permits only XML data format. You define operations, which tunnels through the POST. The focus is on accessing the named operations and exposing the application logic as a service
The REST permits multiple data formats like XML, JSON data, text, HTML, etc. Any browser can be used because the REST approach uses the standard GET, PUT, POST, and DELETE Web operations. The focus is on accessing the named resources and exposing the data as a service. REST has AJAX support. It can use the XMLHttpRequest object. Good for stateless CRUD (Create, Read, Update, and Delete) operations.
         GET - read()
         POST - create()
         PUT - update()
         DELETE - delete()
SOAP based reads cannot be cached
REST based reads can be cached. Performs and scales better.
The SOAP WS supports both remote procedure call (i.e. RPC) and message oriented middle-ware (MOM) integration styles
The Restful Web Service supports only RPC integration style
The SOAP has success or retry logic built in and provides end-to-end reliability even through SOAP intermediaries
REST does not have a standard messaging system, and expects clients invoking the service to deal with communication failures by retrying
SOAP WS supports both SSL security and WS-security, which adds some enterprise security features like maintaining security right up to the point where it is needed, maintaining identities through intermediaries and not just point to point SSL only, securing different parts of the message with different security algorithms, etc
The REST supports only point-to-point SSL security. The SSL encrypts the whole message, whether all of it is sensitive or not.
The SOAP has comprehensive support for both ACID based transaction management for short-lived transactions and compensation based transaction management for long-running transactions. It also supports two-phase commit across distributed resources
The REST supports transactions, but it is neither ACID compliant nor can provide two phase commits across distributed transactional resources as it is limited by its HTTP protocol
Defines the contract via WSDL.
Traditionally, the big drawback of REST was the lack of contract for the web service
Best Practice (BP): In general, a REST based web service is preferred due to its simplicity, performance, scalability, and support for multiple data formats. SOAP is favored where service requires comprehensive support for security, transactional reliability and stricter contract.

Components of SOAP Web Services

The basic web services platform is XML + HTTP. All the standard web services work using the following components −
  • SOAP (Simple Object Access Protocol)
  • UDDI (Universal Description, Discovery and Integration)
  • WSDL (Web Services Description Language)
Structure of a WSDL Document
Web Services Description Language (WSDL) is an XML grammar for describing network services as collections of communication endpoints capable of exchanging messages. The diagram below illustrates the elements that are present in a WSDL document, and indicates their relationships.
·       WSDL breaks down Web services into three specific, identifiable elements that can be combined or reused once defined.
·       Three major elements of WSDL that can be defined separately and they are:
Types
Operations
Binding
·       A WSDL document has various elements, but they are contained within these three main elements, which can be developed as separate documents and then they can be combined or reused to form complete WSDL files.
·       Following are the elements of WSDL document. Within these elements are further sub elements, or parts:
·       Definition: element must be the root element of all WSDL documents. It defines the name of the web service, declares multiple namespaces used throughout the remainder of the document, and contains all the service elements described here.
·       Data types: the data types - in the form of XML schemas or possibly some other mechanism - to be used in the messages
·       Message: an abstract definition of the data, in the form of a message presented either as an entire document or as arguments to be mapped to a method invocation.
·       Operation: the abstract definition of the operation for a message, such as naming a method, message queue, or business process, that will accept and process the message
·       Port type : an abstract set of operations mapped to one or more end points, defining the collection of operations for a binding; the collection of operations, because it is abstract, can be mapped to multiple transports through various bindings.
·       Binding: the concrete protocol and data formats for the operations and messages defined for a particular port type.
·       Port: a combination of a binding and a network address, providing the target address of the service communication.
·       Service: a collection of related end points encompassing the service definitions in the file; the services map the binding to the port and include any extensibility definitions.
·       In addition to these major elements, the WSDL specification also defines the following utility elements:
·       Documentation: element is used to provide human-readable documentation and can be included inside any other WSDL element.
·       Import: element is used to import other WSDL documents or XML Schemas.
·       NOTE: WSDL parts usually are generated automatically using Web services-aware tools.

The main structure of a WSDL document looks like this:
<definitions>
<types>
   definition of data types........
</types>

<message>
   definition of a message....
</message>

<portType>
      <operation>
definition of a operation i/p and o/p....... 
      </operation>
</portType>
<binding>
   definition of a binding....
</binding>
<service>
   definition of a service.... (URI)
</service>
</definitions>

<definitions name="HelloService"
   targetNamespace="http://www.examples.com/wsdl/HelloService.wsdl"
   xmlns="http://schemas.xmlsoap.org/wsdl/"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:tns="http://www.examples.com/wsdl/HelloService.wsdl"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema">

   <message name="SayHelloRequest">
      <part name="firstName" type="xsd:string"/>
   </message>
   <message name="SayHelloResponse">
      <part name="greeting" type="xsd:string"/>
   </message>

   <portType name="Hello_PortType">
      <operation name="sayHello">
         <input message="tns:SayHelloRequest"/>
         <output message="tns:SayHelloResponse"/>
      </operation>
   </portType>

   <binding name="Hello_Binding" type="tns:Hello_PortType">
   <soap:binding style="rpc"
      transport="http://schemas.xmlsoap.org/soap/http"/>
   <operation name="sayHello">
      <soap:operation soapAction="sayHello"/>
      <input>
         <soap:body
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
            namespace="urn:examples:helloservice"
            use="encoded"/>
      </input>
      <output>
         <soap:body
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
            namespace="urn:examples:helloservice"
            use="encoded"/>
      </output>
   </operation>
   </binding>

   <service name="Hello_Service">
      <documentation>WSDL File for HelloService</documentation>
      <port binding="tns:Hello_Binding" name="Hello_Port">
         <soap:address
            location="http://www.examples.com/SayHello/">
      </port>
   </service>
</definitions>

Difference between RPC and Document web services
There are many differences between RPC and Document web services. The important differences between RPC and Document are given below:
RPC Style
1) RPC style web services use method name and parameters to generate XML structure.
2) The generated WSDL is difficult to be validated against schema.
3) In RPC style, SOAP message is sent as many elements.
4) RPC style message is tightly coupled.
5) In RPC style, SOAP message keeps the operation name.
6) In RPC style, parameters are sent as discrete values.
Let's see the RPC style generated WSDL file.
WSDL file: In WSDL file, it doesn't specify the types details.
1.     <message name="getHelloWorldAsString">  
2.     <part name="arg0" type="xsd:string"/>  
3.     </message>  
4.     <message name="getHelloWorldAsStringResponse">  
5.     <part name="return" type="xsd:string"/>  
6.     </message>  
For soap:body, it defines use and namespace attributes.
1.     <binding name="HelloWorldImplPortBinding" type="tns:HelloWorld">  
2.     <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>  
3.     <operation name="getHelloWorldAsString">  
4.     <soap:operation soapAction=""/>  
5.     <input>  
6.     <soap:body use="literal" namespace="http://abc.com/"/>  
7.     </input>  
8.     <output>  
9.     <soap:body use="literal" namespace="http://abc.com/"/>  
10.  </output>  
11.  </operation>  
12.    </binding>  

Document Style
1) Document style web services can be validated against predefined schema.
2) In document style, SOAP message is sent as a single document.
3) Document style message is loosely coupled.
4) In Document style, SOAP message loses the operation name.
5) In Document style, parameters are sent in XML format.
Let's see the Document style generated WSDL file.

WSDL file:In WSDL file, it specifies type’s details having namespace and schemaLocation.
1.     <types>  
2.     <xsd:schema>  
3.     <xsd:import namespace="http://abc.com/" schemaLocation="http://abc:7779/ws/hello?xsd=1"/>  
4.     </xsd:schema>  
5.     </types>  
For message part, it defines name and element attributes.
1.     <message name="getHelloWorldAsString">  
2.     <part name="parameters" element="tns:getHelloWorldAsString"/>  
3.     </message>  
4.     <message name="getHelloWorldAsStringResponse">  
5.     <part name="parameters" element="tns:getHelloWorldAsStringResponse"/>  
6.     </message>  
For soap:body, it defines use attribute only not namespace.
1.     <binding name="HelloWorldImplPortBinding" type="tns:HelloWorld">  
2.     <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>  
3.     <operation name="getHelloWorldAsString">  
4.     <soap:operation soapAction=""/>  
5.     <input>  
6.     <soap:body use="literal"/>  
7.     </input>  
8.     <output>  
9.     <soap:body use="literal"/>  
10.  </output>  
11.  </operation>  
12.    </binding>  

Contract-first (top-down) and Contract-last (bottom-up) approach of developing SOAP web services
In top-down approach first WSDL document is created and then Java classes are developed based on WSDL contract, so if WSDL contract changes you got to change your Java classes while in case of bottom up approach of web service development you first create Java code and then use annotations like @WebService to specify contract or interface and WSDL field will be automatically generated from your build.
Contract-first Web service (top-down approach)
PROS:
Clients are decoupled from the server, hence the implementation logic can be revised on the server without affecting the clients.
Developers can work simultaneously on client and server side based on the contract both agreed on.
You have full control over how the request and response messages are constructed -- for example, should "status" go as an element or as an attribute? The contract clearly defines it. You can change OXM (i.e. Object to XML Mapping) libraries without having to worry if the "status" would be generated as "attribute" instead of an element. Potentially, even Web service frameworks and tool kits can be changed as well from say Apache Axis to Apache CXF, etc
CONS:
More upfront work is involved in setting up the XSDs and WSDLs. There are tools like XML Spy, Oxygen XML, etc to make things easier.
Developers need to learn XSDs and WSDLs in addition to just knowing Java.
Contract-last Web service (bottom-up)
PROS:
Developers don't have to learn anything related to XSDs, WSDLs, and SOAP. The services are created quickly by exposing the existing service logic with frameworks/tool sets. 
The learning curve and development time can be smaller compared to the Contract-first Web service. 
CONS:
The development time can be shorter to initially develop it, but what about the ongoing maintenance and extension time if the contract changes or new elements need to be added? In this approach, since the clients and servers are more tightly coupled, the future changes may break the client contract and affect all clients or require the services to be properly versioned and managed.
 In this approach, The XML payloads cannot be controlled. This means changing your OXM libraries could cause something that used to be an element to become an attribute with the change of the OXM.

RESTful web services
REST stands for REpresentational State Transfer (REST) which enforces a stateless client server design where web services are treated as resource and can be accessed and identified by their URL.
Web services written by apply REST Architectural concept are called RESTful web services which focus on System resources and how state of Resource should be transferred over http/https protocol to a different clients written in different languages. In RESTful web services http methods like GET, PUT, POST and DELETE can be used to perform CRUD operations.
Resource in REST framework
A resource is a unique URL with representation of an object which we can get contents via GET and modify via PUT, POST and DELETE.

HTTP methods supported by REST
·       GET: It requests a resource at the request URL. It should not contain a request body as it will be discarded. May be it can be cached locally or on the server.
·       POST: It submits information to the service for processing; it should typically return the modified or new resource
·       PUT: At the request URL it update the resource and it is idempotent
·       DELETE: At the request URL it removes the resource
·       OPTIONS: It indicates which techniques are supported
·       HEAD: About the request URL it returns meta information

What happens if RestFull resources are accessed by multiple clients ? do you need to make it thread-safe?
Since a new Resource instance is created for every incoming Request there is no need to make it thread-safe or add synchronization. multiple client can safely access RestFull resources concurrently.

Jersey framework
Jersey is open source framework for developing RESTful Web Services in Java that provides support for JAX-RS APIs and serves as a JAX-RS (JSR 311 & JSR 339) Reference Implementation. It has advantages such as 
§  contains support for Web Application Description Language (WADL); 
§  contains Jersey Test Framework which lets run and test Jersey REST services inside JUnit;   
§  Supports for the REST MVC pattern, which would allow to return a View from Jersey services rather than just data.
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.FormParam;
import javax.ws.rs.core.Response;

@Path("/persons")
public class PersonRestService {

/*
@PathParam annotation injects the value of URI parameter that defined in @Path expression
On calling URI: “/persons/1” result:  getPersonById is called, id : 1
*/
@GET
@Path("{id}")
public Response getPersonById(@PathParam("id") String id) {

  return Response.status(200).entity("getPersonById is called, id : " + id).build();
 }

/*
@QueryParam annotation injects URI query parameter into Java method
“/persons/query?from=10&to=20&orderBy=age&orderBy=name” result: getPersons is called, from : 10, to : 20, orderBy[age, name]
*/
@GET
@Path("/query")
public Response getPersons(
@QueryParam("from") int from,
@QueryParam("to") int to,
@QueryParam("orderBy") List&lt;String&gt; orderBy) {

return Response
  .status(200)
  .entity("getPersons is called, from : " + from + ", to : " + to
+ ", orderBy" + orderBy.toString()).build();
 }
/*
@FormParam bind HTML form parameters value to a Java method
*/
@POST
@Path("/add")
public Response addPerson(
@FormParam("name") String name,
@FormParam("age") int age) {

return Response.status(200)
.entity("addPerson is called, name : " + name + ", age : " + age)
.build();
 }
}


@MatrixParam are a set of “name=value” in URI path.
import javax.ws.rs.GET;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;

@Path("/books")
public class BookService {

@GET
@Path("{year}")
public Response getBooks(@PathParam("year") String year,
@MatrixParam("author") String author,
@MatrixParam("country") String country) {

return Response
.status(200)
.entity("getBooks is called, year : " + year
+ ", author : " + author + ", country : " + country)
.build();

 }
}
On calling URI: “/books/2015” result: getBooks is called, year : 2015, author : null, country : null
On calling URI: “/books/2015;author= doyle;country=scotland” result: getBooks is called, year : 2015, author : doyle, country : scotland

download img/file in JAX-RS
§  put @Produces(“?”) on service method, with a Response return type. Instead “?” write a type text/plain, image/png, etc. 
§  set “Content-Disposition” in Response header to tell browser pop up a download box for user to download.
import java.io.File;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

@Path("/image")
public class ImageService {
private static final String FILE_PATH = "c:\\my.png";
@GET
@Path("/get")
@Produces("image/png")
public Response getFile() {
File file = new File(FILE_PATH);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition",
"attachment; filename=image_from_server.png");
return response.build();
 }
}

HTTP request header in JAX-RS (2 ways)
§  inject directly with @HeaderParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.core.Response;

@Path("/persons")
public class PersonService {

@GET
@Path("/get")
public Response getPerson(
@HeaderParam("person-agent") String personAgent) {
return Response.status(200)
.entity("getPerson is called, personAgent : " + personAgent)
.build();
 }
}
On calling URI: “/persons/get” result: getPerson is called, personAgent : Mozilla/5.0(Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0
§  pragmatically via @Context.
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;

@Path("/persons")
public class PersonService {
@GET
@Path("/get")
public Response getPerson(@Context HttpHeaders headers) {
String personAgent = headers.getRequestHeader("person-agent").get(0);
return Response.status(200)
.entity("getPerson is called, personAgent : " + personAgent)
.build();
 }
}
On calling URI: “/persons/get” result: getPerson is called, personAgent : Mozilla/5.0(Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0
JAX-WS and JAX-RS
Both JAX-WS and JAX-RS are libraries (APIs) for doing communication in various ways in Java.  JAX-WS is a library that can be used to do SOAP communication in JAVA, and JAX-RS lets you do the REST communication in JAVA

Spring RESTFul webservice
Using spring framework we can develop the RESTFul webservices, the all other concepts remains the same.
Example
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.sathish.tutorials.springboot.restapi.dto.Employee;
import com.sathish.tutorials.springboot.restapi.service.EmployeeService;

/**
 * Handles requests for the Employee service.
 */
@RestController
public class EmployeeController {

            // Map to store employees, ideally it should come from database
            Map<Integer, Employee> empData = new HashMap<Integer, Employee>();

            @Autowired
            private EmployeeService employeeService;

            // URL http://localhost:8080/rest/emp/default
            @RequestMapping(value = "/rest/emp/default", method = RequestMethod.GET, produces      = "application/json")
            public @ResponseBody Employee getDefaultEmployee() {
                        Employee emp = new Employee();
                        emp = employeeService.getDefaultEmployeeService();
                        empData.put(9999, emp);
                        return emp;
            }

            // URL http://localhost:8080/rest/emp/9999
            @RequestMapping(value = "/rest/emp/{id}", method = RequestMethod.GET, produces = "application/json")
            public @ResponseBody Employee getEmployee(@PathVariable("id") int empId) {
                        System.out.println("Start getEmployee. ID=" + empId);

                        return empData.get(empId);
            }

            // URL http://localhost:8080//rest/emp/create
            // request {"id":1,"name":"Sathish
            // Kariyanna","createdDate":"2018-06-24T20:25:58.096+0000"}
            @RequestMapping(value = "/rest/emp/create", method = RequestMethod.POST, produces = "application/json")
            public @ResponseBody Employee createEmployee(@RequestBody Employee emp) {
                        System.out.println("Start createEmployee.");
                        emp.setCreatedDate(new Date());
                        empData.put(emp.getId(), emp);
                        return emp;
            }

            // URL http://localhost:8080/rest/emps
            @RequestMapping(value = "/rest/emps", method = RequestMethod.GET, produces = "application/json")
            public @ResponseBody List<Employee> getAllEmployees() {
                        System.out.println("Start getAllEmployees.");
                        List<Employee> emps = new ArrayList<Employee>();
                        Set<Integer> empIdKeys = empData.keySet();
                        for (Integer i : empIdKeys) {
                                    emps.add(empData.get(i));
                        }
                        return emps;
            }

            // URL http://localhost:8080//rest/emp/update
            // request
            // {"id":1,"name":"Sathish","createdDate":"2018-06-25T20:25:58.096+0000"}
            @RequestMapping(value = "/rest/emp/update", method = RequestMethod.PUT, produces = "application/json")
            public @ResponseBody Employee updateEmployee(@RequestBody Employee emp) {
                        System.out.println("Start updateEmployee.");
                        empData.put(emp.getId(), emp);
                        return emp;
            }

            // URL http://localhost:8080//rest/emp/delete/1
            @RequestMapping(value = "/rest/emp/delete/{id}", method = RequestMethod.DELETE)
            public @ResponseBody Employee deleteEmployee(@PathVariable("id") int empId) {
                        System.out.println("Start delete Employee.");
                        Employee emp = empData.get(empId);
                        empData.remove(empId);
                        return emp;
            }
}

 

@RestController annotation was introduced in Spring 4.0 to simplify the creation of RESTful web services. It’s a convenience annotation that combines @Controller and @ResponseBody – which eliminates the need to annotate every request handling method of the controller class with the @ResponseBody annotation. (we do not need to use @ResponseBody)
@RequestMapping annotation is used to map the request URI to the handler method.
@ResponseBody annotation is used to map the response object in the response body. Once the response object is returned by the handler method, MappingJackson2HttpMessageConverter kicks in and convert it to JSON response.
@PathVariable annotation is the easy way to extract the data from the rest URI and map it to the method argument.
@RequestBody annotation is used to map the request body JSON data into the Employee object, again this is done by the MappingJackson2HttpMessageConverter mapping.


Restful Web Services Versioning
·       The best approach to versioning is NOT to do it. Yeah, that’s right. Do not version as long as versioning is not needed. However there are a number of situations where versioning is needed.
·       Build your services to backward compatible so that you can avoid versioning as much as possible.       
package com.sathish.springboot.restapi.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.sathish.springboot.restapi.dto.Name;
import com.sathish.springboot.restapi.dto.PersonV1;
import com.sathish.springboot.restapi.dto.PersonV2;

@RestController
publicclass PersonVersioningController {
// URI Versioning
// URL http://localhost:8080/rest/v1/person
@RequestMapping(value = "/rest/v1/person", method = RequestMethod.GET)
          public PersonV1 PersonV1() {
                   returnnew PersonV1("Sathish Kariyanna");
}

// URI Versioning
// URL http://localhost:8080/rest/v2/person
@RequestMapping(value = "/rest/v2/person", method = RequestMethod.GET)
          public PersonV2 PersonV2() {
                   returnnew PersonV2(new Name("Sathish", "Kariyanna"));
}
//Request Parameter versioning
// URL http://localhost:8080/rest/person/param?version=1
@RequestMapping(value = "/rest/person/param", method = RequestMethod.GET, params = "version=1")
          public PersonV1 paramV1() {
                   returnnew PersonV1("Sathish Kariyanna");
}

//Request Parameter versioning
// URL http://localhost:8080/rest/person/param?version=2
@RequestMapping(value = "/rest/person/param", method = RequestMethod.GET, params = "version=2")
          public PersonV2 paramV2() {
                   returnnew PersonV2(new Name("Sathish", "Kariyanna"));
}
          
// Headers(Custom) versioning
// URL http://localhost:8080/rest/person/header and add header [X-API-VERSION=1]
@RequestMapping(value = "/rest/person/header", method = RequestMethod.GET, headers = "X-API-VERSION=1")
          public PersonV1 headerV1() {
                   returnnew PersonV1("Sathish Kariyanna");
}

// Headers(Custom) versioning
// URL http://localhost:8080/rest/person/header and add header [X-API-VERSION=2]
@RequestMapping(value = "/rest/person/header", method = RequestMethod.GET, headers = "X-API-VERSION=2")
          public PersonV2 headerV2() {
                   returnnew PersonV2(new Name("Sathish", "Kariyanna"));
//Media type versioning (“content negotiation” or “accept header”)
// URL http://localhost:8080/rest/person/produces and add headers[Accept=application/vnd.company.app-v1+json]
@RequestMapping(value = "/rest/person/produces", method = RequestMethod.GET, produces = "application/vnd.company.app-v1+json")
          public PersonV1 producesV1() {
                   returnnew PersonV1("Sathish Kariyanna");
}
          
//Media type versioning (“content negotiation” or “accept header”)
// URL http://localhost:8080/rest/person/produces and add headers[Accept=application/vnd.company.app-v2+json]
@RequestMapping(value = "/rest/person/produces", method = RequestMethod.GET, produces = "application/vnd.company.app-v2+json")
          public PersonV2 producesV2() {
                   returnnew PersonV2(new Name("Sathish", "Kariyanna"));
}
}

URI Versioning

Basic approach to versioning is to create a completely different URI for the new service. Example implementation is shown in the example code.
Example URL’s
http://localhost:8080/rest/v1/person
http://localhost:8080/rest/v2/person

Request Parameter versioning

In request parameter versioning the version number is passed URI as the request parameter. 
Example URL’s
·       http://localhost:8080/rest/person/param?version=1
·       http://localhost:8080/rest/person/param?version=2

(Custom) Headers versioning

The third approach to versioning is to use a Request Header, pass the version number in the header.
Example URL’s
·       http://localhost:8080/rest/person/header
o   headers [X-API-VERSION=1]
·       http://localhost:8080/rest/person/header
o   headers [X-API-VERSION=2]

Media type versioning (“content negotiation” or “accept header”)

The fourth versioning approach is to use the Accept Header in the request.
Examples
·       http://localhost:8080/rest/person/produces
o   headers[Accept=application/vnd.company.app-v1+json]
·       http://localhost:8080/rest/person/produces

o   headers[Accept=application/vnd.company.app-v2+json]

Writing Unit Test for the Get/POST Rest Service

When we are unit testing a rest service, we would want to launch only the specific controller and the related MVC Components. WebMvcTest annotation is used for unit testing Spring MVC application. This can be used when a test focuses only Spring MVC components. Using this annotation will disable full auto-configuration and only apply configuration relevant to MVC tests.
@RunWith(SpringRunner.class)
@WebMvcTest(value = EmployeeController.class, secure = false)
publicclass EmployeeControllerTest {
            @Autowired
            private MockMvc mockMvc;

            @MockBean
            private EmployeeService employeeService;

            Employee mockEmployee = new Employee(9999, "default");
                        
            @Test
            publicvoid getDefaultEmployeeTest() throws Exception {            
               System.out.println("********************TEST*******************");  
               Mockito.when(employeeService.getDefaultEmployeeService())
.thenReturn(mockEmployee);

                        RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/rest/emp/default")
                                                .accept(MediaType.APPLICATION_JSON);

                        MvcResult result = mockMvc.perform(requestBuilder).andReturn();

                        System.out.println("Response : " + result.getResponse().getContentAsString());
                        String expected = "{id:9999,name:default}";

                        JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false);
            }          
} 

·       @RunWith(SpringRunner.class) : SpringRunner is short hand for SpringJUnit4ClassRunner which extends BlockJUnit4ClassRunner providing the functionality to launch a Spring TestContext Framework.
·       @WebMvcTest(value = EmployeeController.class, secure = false): WebMvcTest annotation is used for unit testing Spring MVC application. This can be used when a test focuses only Spring MVC components. In this test, we want to launch only EmployeeController. All other controllers and mappings will not be launched when this unit test is executed.
·       @Autowired private MockMvc mockMvc: MockMvc is the main entry point for server-side Spring MVC test support. It allows us to execute requests against the test context.
·       @MockBean private EmployeeService employeeService: MockBean is used to add mocks to a Spring ApplicationContext. A mock of employeeService is created and auto-wired into the EmployeeController.
·       Mockito.when(employeeService.getDefaultEmployeeService()).thenReturn(mockEmployee): Mocking the method getDefaultEmployeeService to return the specific mockEmployee when invoked.
·       MockMvcRequestBuilders.get("/rest/emp/default").accept(MediaType.APPLICATION_JSON): Creating a Request builder to be able to execute a get request to uri “/rest/emp/default” with accept header as “application/json”
·       mockMvc.perform(requestBuilder).andReturn(): mockMvc is used to perform the request and return the response back.
·       JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false): We are using org.skyscreamer.jsonassert.JSONAssert. This allows us to do partial asserts against a JSON String. We are passing strict as false since we do not want to check for all fields in the response.
·       MockMvcRequestBuilders.post(“/rest/emp/create").accept(MediaType.APPLICATION_JSON): Create a post request with an accept header for application\json
·       content(exampleCourseJson).contentType(MediaType.APPLICATION_JSON): Use the specified content as body of the request and set content type header.
·       assertEquals(HttpStatus.CREATED.value(), response.getStatus()): Assert that the return status is CREATED.
·       response.getHeader(HttpHeaders.LOCATION): Get the location from response header and later assert that it contains the URI of the created resource.

Important constraints for a RESTful Web Service

The five important constraints for RESTful Web Service are
·       Client - Server : There should be a service producer and a service consumer.
·       The interface (URL) is uniform and exposing resources. Interface uses nouns (not actions)
·       The service is stateless. Even if the service is called 10 times, the result must be the same.
·       The service result should be Cacheable. HTTP cache, for example.
·       Service should assume a Layered architecture. Client should not assume direct connection to server - it might be getting info from a middle layer - cache.

Best practices in designing RESTful APIs

·       While designing any API, the most important thing is to think about the api consumer i.e. the client who is going to use the service. What are his needs? Does the service uri make sense to him? Does the request, response format make sense to him?
·       In Rest, we think Nouns (resources) and NOT Verbs (NOT actions). So, URI’s should represent resources. URI’s should be hierarchical and as self-descriptive as possible. Prefer plurals.
·       Always use HTTP Methods.

Core components of a HTTP Request
A HTTP Request has five major parts −
·      Verb − Indicate HTTP methods such as GET, POST, DELETE, PUT etc.
·      URI − Uniform Resource Identifier (URI) to identify the resource on server.
·      HTTP Version − Indicate HTTP version, for example HTTP v1.1 .
·      Request Header − Contains metadata for the HTTP Request message as key-value pairs. For example, client (or browser) type, format supported by client, format of message body, cache settings etc.
·      Request Body − Message content or Resource representation.

Core components of a HTTP response
A HTTP Response has four major parts −
·      Status/Response Code − Indicate Server status for the requested resource. For example 404 means resource not found and 200 means response is ok.
·      HTTP Version − Indicate HTTP version, for example HTTP v1.1 .
·      Response Header − Contains metadata for the HTTP Response message as key-value pairs. For example, content length, content type, response date, server type etc.
·      Response Body − Response message content or Resource representation.

Format of a URI in REST architecture and best practices to create a standard URI
A URI is of following format −
<protocol>://<service-name>/<ResourceType>/<ResourceID>
Following are important points to be considered while designing a URI −
·      Use Plural Noun − Use plural noun to define resources. For example, we've used users to identify users as a resource.
·      Avoid using spaces − Use underscore(_) or hyphen(-) when using a long resource name, for example, use authorized_users instead of authorized%20users.
·      Use lowercase letters − Although URI is case-insensitive, it is good practice to keep url in lower case letters only.
·      Maintain Backward Compatibility − As Web Service is a public service, a URI once made public should always be available. In case, URI gets updated, redirect the older URI to new URI using HTTP Status code, 300.
·      Use HTTP Verb − Always use HTTP Verb like GET, PUT, and DELETE to do the operations on the resource. It is not good to use operations names in URI.
Some of the HTTP states codes:
·                 1xx Informational
·       100 Continue

2xx Success
·       200 OK, shows success.
·       201 Created, when a resource is successful created using POST or PUT request.
·       204 No Content, when response body is empty for example, a DELETE request.

3xx Redirection
·       302 Found
·       304 Not Modified, used to reduce network bandwidth usage in case of conditional GET requests. Response body should be empty
·       307 Temporary Redirect
·       308 Permanent Redirect

4xx Client Error
·       400 Bad Request, , states that invalid input is provided e.g. validation error, missing data.
·       401 Unauthorized, the request has not been applied because it lacks valid authentication credentials for the target resource.
·       403 Forbidden, states that user is not having access to method being used for example, delete access without admin rights.
·       404 Not Found, states that method is not available.
·       405 Method Not Allowed

5xx Server Error
·       500 Internal Server Error, states that server has thrown some exception while executing the method.
·       502 Bad Gateway
·       503 Service Unavailable
·       504 Gateway Timeout
·       


No comments:

Post a Comment