SlideShare a Scribd company logo
1 of 17
Restful web services
Dans la pratique
KONG TO
Code matters most
Summary
• Theory
• Principles
• CRUD
• FAQ
• Sample
Definition
REST for “REpresentation State Transfer is not a protocol, nor a format,
but an architecture style, a convention or an approach to construct
web services, on top of HTTP.
It is used to develop Resources Oriented Application. Applications that
are complied with this architecture is said RESTful”.
Contraints
• Client-server
• The separation of concerns enables independent evolution of the Client and the Server.
• Stateless
• The communication between Client and Server must be stateless between requests. Each
request from a client should contain all the necessary information for the service to complete
the request. all session state data should then be returned to the client at the end of each
request.
• Cache
• All responses from the Server should be explicitly labeled as cacheable or non-cacheable.
• Interface / Uniform Contract
• The Service and all Clients must share a single uniform technical interface.
• Layered System
• Allow for Intermediaries / Middleware.
Terminology
• Resource
• The Resource is the key abstraction of information in REST. Any information
that can be named / identified via a unique, global id (the URI) - is a Resource.
• Representation
• Any given Resource can have multiple Representations; these capture the
current state of the Resource in a specific format.
• At the lowest level, the Representation is “a sequence of bytes, plus
representation metadata to describe these bytes”.
• Hypermedia Types
• There are several Hypermedia types we can use for our Representations, and
we can build our own if we need to. Note that JSON is not a Hypermedia.
Principles
• Resources are identified by URI
• Every resource is identified by a unique identifier.
• Uniform interface, use HTTP verbs for CRUD operations on resources
• Use common set of verbs : GET, PUT, POST, DELETE, PATCH.
• Response represents resource (json, xml)
• Response is the representation of the resource.
• Links to other resources
• Within response, there are links to other resources (links, next, last, otherResource).
• Stateless services
• So the server does not maintain the states of the clients. This means that you cannot use server session storage and you have to authenticate
every request. Don’t confuse session storage and persistence into database.
• Each request from a client should contain all the necessary information for the service to complete the request. All session state data should
then be returned to the client at the end of each request.
• Cacheable, if you can
• So you don’t have to serve the same requests again and again
• Layered system
• To increase scalability, the REST system is composed of hierarchical layers. Each layer contains components which use the services of
components which are in the next layer below. So you can add new layers and components effortless. Intermediary components or middleware
must be transparent and independent.
CRUD basics
• Create : POST
• Retrieve : GET
• Update : PUT ou PATCH
• Delete : DELETE
FAQ
• Trigger an action on server side with a GET?
• E.g. : Triggering a batch or a notification
• Create a resource with a GET?
• Read a resource with a POST?
• E.g Search with complex criteria
• Update with DELETE, or Delete with PUT?
Following standards makes intent explicit. Refer to the RFC-626
Sample
GET /user/new
GET /new_user.x
POST /user/new
POST /user/delete
GET /delete_user.x?id=123
GET /user?id=1
GET /user/id/1
GET /get/user/by/profile/id
GET /get/user/address/by/city?city=paris
GET /find/user/by/name?name=Bob
PUT /user/update?id=100
GET /user/findBy?name=Bob&age=29
POST /user
GET /user/2
DELETE /user/2
PUT /user/2
GET
/user/address?city=paris
RESTfull Sample
@RestController
@RequestMapping("/address")
public class AdressController {
@Autowired
private AddressService addressService;
@PostMapping(value = "")
public AddressDto create(@RequestBody AddressDto address) {
return addressService.save(address);
}
@PutMapping(value = "/{id}")
public void update(@PathVariable Long id, @RequestBody AddressDto address) {
addressService.updateById(id, address);
}
@DeleteMapping(value = "/{id}")
public void delete(@PathVariable Long id) {
addressService.deleteById(id);
}
@GetMapping(value = "")
public Collection<AddressDto> findAll() {
return addressService.findAll();
}
}
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Address, Status } from '../address/address.model';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
@Injectable()
export class AddressService {
private url = 'api/address';
constructor(private http: HttpClient) { }
create(address: Address): Observable<Address> {
return this.http.post<Address>(this.url, user, httpOptions);
}
update(address: Address): Observable<Address> {
return this.http.put<Address>(this.url + '/' + address.id, address, httpOptions);
}
delete(address: Address): Observable<void> {
return this.http.delete<void>(this.url + '/' + address.id, httpOptions);
}
addresses(): Observable<Array<Address>> {
return this.http.get<Array<Address>>(this.url, httpOptions);
}
}
RESTfull Client Sample
RESTfull Sample
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping(value = "")
public UserDto create(@RequestBody UserDto user) {
return userService.save(user);
}
@PutMapping(value = "/{username}")
public void updateById(@PathVariable String username, @RequestBody UserDto user) {
userService.updateByUsername(username, user);
}
@DeleteMapping(value = "/{username}")
public void deleteByUsername(@PathVariable String username) {
userService.deleteByUsername(username);
}
@GetMapping(value = "", params = {"username"})
public UserDto findByUsername(@RequestParam String username) {
return userService.findByUsername(username);
}
@GetMapping(value = "")
public Collection<UserDto> findAll() {
return userService.findAll();
}
}
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { User, Status } from '../user/user.model';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
@Injectable()
export class UserService {
private url = 'api/user';
constructor(private http: HttpClient) { }
create(user: User): Observable<User> {
return this.http.post<User>(this.url, user, httpOptions);
}
update(user: User): Observable<User> {
return this.http.put<User>(this.url + '/' + user.username, user, httpOptions);
}
delete(user: User): Observable<void> {
return this.http.delete<void>(this.url + '/' + user.username, httpOptions);
}
users(): Observable<Array<User>> {
return this.http.get<Array<User>>(this.url, httpOptions);
}
}
RESTfull Client Sample
Json-patch
JSON Patch is a format for describing changes to a JSON document.
It can be used to avoid sending a whole document when only a part has
changed.
{
"username": "uncle",
"firstname": "kong",
"lastname": "to",
" roles ": ["user"]
}
[
{ "op": "replace", "path": "/username", "value": "donkey" },
{ "op": "add", "path": "/roles", "value": ["admin"] },
{ "op": "replace", "path": "/roles/0/name", "value": "guest" }
{ "op": "add", "path": "/age", "value": 25 }
{ "op": "remove", "path": "/firstname" }
]
{
"username": "donkey",
"lastname": "to",
"age": 25,
"roles": ["guest", "admin"]
}
Json-patch sample
@RestController
@RequestMapping("/address")
public class AdressController {
@Autowired
private AddressService addressService;
@PostMapping(value = "")
public AddressDto create(@RequestBody AddressDto address) {
return addressService.save(address);
}
@PutMapping(value = "/{id}")
public void update(@PathVariable Long id, @RequestBody AddressDto address) {
addressService.updateById(id, address);
}
@PatchMapping(value = "/{id}")
public void patch(@PathVariable Long id, @RequestBody List<JsonPatchOperation> operations) {
this.addressService.patch(id, operations);
}
@PatchMapping(value = "/{id}", params = {"patchById"})
public void patchById(@PathVariable Long id, @RequestBody JsonPatch jsonPatch) {
this.addressService.patchById(id, jsonPatch);
}
@DeleteMapping(value = "/{id}")
public void delete(@PathVariable Long id) {
addressService.deleteById(id);
}
@GetMapping(value = "")
public Collection<AddressDto> findAll() {
return addressService.findAll();
}
}
Json-patch sample
public class AddressService {
private AddressRepository addressRepository;
public AddressService(AddressRepository addressRepository) {
this.addressRepository = addressRepository;
}
public void updateById(Long id, AddressDto userDto) {
Optional<AddressEntity> entity = addressRepository.findById(id);
entity.ifPresent(u -> {
BeanUtils.copyProperties(AddressMapper.from(userDto), u);
addressRepository.save(u);
});
}
public void patchById(Long id, JsonPatch jsonPatch) {
this.findById(id)
.ifPresent(existing -> {
try {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode patched = jsonPatch.apply(objectMapper.convertValue(existing, JsonNode.class));
AddressEntity patchedUser = objectMapper.treeToValue(patched, AddressEntity.class);
addressRepository.save(patchedUser);
} catch (JsonPatchException | JsonProcessingException e) {
throw new IllegalStateException();
}
});
}
}
Json-patch authorized operation
public class AddressService {
private AddressRepository addressRepository;
public AddressService(AddressRepository addressRepository) {
this.addressRepository = addressRepository;
}
public void patch(Long id, List<JsonPatchOperation> operations) {
addressRepository.findById(id)
.ifPresent(existing -> {
ObjectMapper objectMapper = new ObjectMapper();
operations.stream().forEach(op -> {
try {
JsonNode node = objectMapper.readValue(op.toString(), JsonNode.class);
// allow only add operation
if ("add".equals(node.get("op"))) {
JsonNode patched = op.apply(objectMapper.convertValue(existing, JsonNode.class));
AddressEntity patchedUser = objectMapper.treeToValue(patched, AddressEntity.class);
addressRepository.save(patchedUser);
}
} catch (IOException | JsonPatchException e) {
throw new IllegalStateException();
}
});
});
}
}

More Related Content

What's hot

Json-based Service Oriented Architecture for the web
Json-based Service Oriented Architecture for the webJson-based Service Oriented Architecture for the web
Json-based Service Oriented Architecture for the web
kriszyp
 
Consuming RESTful services in PHP
Consuming RESTful services in PHPConsuming RESTful services in PHP
Consuming RESTful services in PHP
Zoran Jeremic
 

What's hot (20)

RestFull Webservices with JAX-RS
RestFull Webservices with JAX-RSRestFull Webservices with JAX-RS
RestFull Webservices with JAX-RS
 
PHP And Web Services: Perfect Partners
PHP And Web Services: Perfect PartnersPHP And Web Services: Perfect Partners
PHP And Web Services: Perfect Partners
 
So various polymorphism in Scala
So various polymorphism in ScalaSo various polymorphism in Scala
So various polymorphism in Scala
 
Introduction to JAX-RS
Introduction to JAX-RSIntroduction to JAX-RS
Introduction to JAX-RS
 
Json-based Service Oriented Architecture for the web
Json-based Service Oriented Architecture for the webJson-based Service Oriented Architecture for the web
Json-based Service Oriented Architecture for the web
 
Wsdl
WsdlWsdl
Wsdl
 
JSON-RPC - JSON Remote Procedure Call
JSON-RPC - JSON Remote Procedure CallJSON-RPC - JSON Remote Procedure Call
JSON-RPC - JSON Remote Procedure Call
 
Consuming RESTful services in PHP
Consuming RESTful services in PHPConsuming RESTful services in PHP
Consuming RESTful services in PHP
 
Web Services - WSDL
Web Services - WSDLWeb Services - WSDL
Web Services - WSDL
 
Soap and restful webservice
Soap and restful webserviceSoap and restful webservice
Soap and restful webservice
 
Introduction to SOAP/WSDL Web Services and RESTful Web Services
Introduction to SOAP/WSDL Web Services and RESTful Web ServicesIntroduction to SOAP/WSDL Web Services and RESTful Web Services
Introduction to SOAP/WSDL Web Services and RESTful Web Services
 
WSDL
WSDLWSDL
WSDL
 
OAuth: Trust Issues
OAuth: Trust IssuesOAuth: Trust Issues
OAuth: Trust Issues
 
SCDJWS 6. REST JAX-P
SCDJWS 6. REST  JAX-PSCDJWS 6. REST  JAX-P
SCDJWS 6. REST JAX-P
 
XML-RPC (XML Remote Procedure Call)
XML-RPC (XML Remote Procedure Call)XML-RPC (XML Remote Procedure Call)
XML-RPC (XML Remote Procedure Call)
 
Database connect
Database connectDatabase connect
Database connect
 
Java Servlet
Java ServletJava Servlet
Java Servlet
 
Restful web services by Sreeni Inturi
Restful web services by Sreeni InturiRestful web services by Sreeni Inturi
Restful web services by Sreeni Inturi
 
Url programming
Url programmingUrl programming
Url programming
 
Web Services (SOAP, WSDL, UDDI)
Web Services (SOAP, WSDL, UDDI)Web Services (SOAP, WSDL, UDDI)
Web Services (SOAP, WSDL, UDDI)
 

Similar to Restful webservices

Rest with Java EE 6 , Security , Backbone.js
Rest with Java EE 6 , Security , Backbone.jsRest with Java EE 6 , Security , Backbone.js
Rest with Java EE 6 , Security , Backbone.js
Carol McDonald
 
JAX-RS JavaOne Hyderabad, India 2011
JAX-RS JavaOne Hyderabad, India 2011JAX-RS JavaOne Hyderabad, India 2011
JAX-RS JavaOne Hyderabad, India 2011
Shreedhar Ganapathy
 
Pinterest like site using REST and Bottle
Pinterest like site using REST and Bottle Pinterest like site using REST and Bottle
Pinterest like site using REST and Bottle
Gaurav Bhardwaj
 
REST API Recommendations
REST API RecommendationsREST API Recommendations
REST API Recommendations
Jeelani Shaik
 
Services in Drupal 8
Services in Drupal 8Services in Drupal 8
Services in Drupal 8
Andrei Jechiu
 

Similar to Restful webservices (20)

Java colombo-deep-dive-into-jax-rs
Java colombo-deep-dive-into-jax-rsJava colombo-deep-dive-into-jax-rs
Java colombo-deep-dive-into-jax-rs
 
JAX-RS 2.0 and OData
JAX-RS 2.0 and ODataJAX-RS 2.0 and OData
JAX-RS 2.0 and OData
 
Switch to Backend 2023
Switch to Backend 2023Switch to Backend 2023
Switch to Backend 2023
 
Rest with Java EE 6 , Security , Backbone.js
Rest with Java EE 6 , Security , Backbone.jsRest with Java EE 6 , Security , Backbone.js
Rest with Java EE 6 , Security , Backbone.js
 
Rest
RestRest
Rest
 
Android and REST
Android and RESTAndroid and REST
Android and REST
 
REST & RESTful Web Service
REST & RESTful Web ServiceREST & RESTful Web Service
REST & RESTful Web Service
 
Restful webservice
Restful webserviceRestful webservice
Restful webservice
 
RESTEasy
RESTEasyRESTEasy
RESTEasy
 
Services Stanford 2012
Services Stanford 2012Services Stanford 2012
Services Stanford 2012
 
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy ClarksonMulti Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson
 
Consuming RESTful Web services in PHP
Consuming RESTful Web services in PHPConsuming RESTful Web services in PHP
Consuming RESTful Web services in PHP
 
May 2010 - RestEasy
May 2010 - RestEasyMay 2010 - RestEasy
May 2010 - RestEasy
 
JAX-RS JavaOne Hyderabad, India 2011
JAX-RS JavaOne Hyderabad, India 2011JAX-RS JavaOne Hyderabad, India 2011
JAX-RS JavaOne Hyderabad, India 2011
 
Rest service in mule
Rest service in mule Rest service in mule
Rest service in mule
 
Pinterest like site using REST and Bottle
Pinterest like site using REST and Bottle Pinterest like site using REST and Bottle
Pinterest like site using REST and Bottle
 
Overview of RESTful web services
Overview of RESTful web servicesOverview of RESTful web services
Overview of RESTful web services
 
Rest Service In Mule
Rest Service In Mule Rest Service In Mule
Rest Service In Mule
 
REST API Recommendations
REST API RecommendationsREST API Recommendations
REST API Recommendations
 
Services in Drupal 8
Services in Drupal 8Services in Drupal 8
Services in Drupal 8
 

Recently uploaded

%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 

Recently uploaded (20)

%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
Generic or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisionsGeneric or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisions
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions Presentation
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 

Restful webservices

  • 1. Restful web services Dans la pratique KONG TO Code matters most
  • 2. Summary • Theory • Principles • CRUD • FAQ • Sample
  • 3. Definition REST for “REpresentation State Transfer is not a protocol, nor a format, but an architecture style, a convention or an approach to construct web services, on top of HTTP. It is used to develop Resources Oriented Application. Applications that are complied with this architecture is said RESTful”.
  • 4. Contraints • Client-server • The separation of concerns enables independent evolution of the Client and the Server. • Stateless • The communication between Client and Server must be stateless between requests. Each request from a client should contain all the necessary information for the service to complete the request. all session state data should then be returned to the client at the end of each request. • Cache • All responses from the Server should be explicitly labeled as cacheable or non-cacheable. • Interface / Uniform Contract • The Service and all Clients must share a single uniform technical interface. • Layered System • Allow for Intermediaries / Middleware.
  • 5. Terminology • Resource • The Resource is the key abstraction of information in REST. Any information that can be named / identified via a unique, global id (the URI) - is a Resource. • Representation • Any given Resource can have multiple Representations; these capture the current state of the Resource in a specific format. • At the lowest level, the Representation is “a sequence of bytes, plus representation metadata to describe these bytes”. • Hypermedia Types • There are several Hypermedia types we can use for our Representations, and we can build our own if we need to. Note that JSON is not a Hypermedia.
  • 6. Principles • Resources are identified by URI • Every resource is identified by a unique identifier. • Uniform interface, use HTTP verbs for CRUD operations on resources • Use common set of verbs : GET, PUT, POST, DELETE, PATCH. • Response represents resource (json, xml) • Response is the representation of the resource. • Links to other resources • Within response, there are links to other resources (links, next, last, otherResource). • Stateless services • So the server does not maintain the states of the clients. This means that you cannot use server session storage and you have to authenticate every request. Don’t confuse session storage and persistence into database. • Each request from a client should contain all the necessary information for the service to complete the request. All session state data should then be returned to the client at the end of each request. • Cacheable, if you can • So you don’t have to serve the same requests again and again • Layered system • To increase scalability, the REST system is composed of hierarchical layers. Each layer contains components which use the services of components which are in the next layer below. So you can add new layers and components effortless. Intermediary components or middleware must be transparent and independent.
  • 7. CRUD basics • Create : POST • Retrieve : GET • Update : PUT ou PATCH • Delete : DELETE
  • 8. FAQ • Trigger an action on server side with a GET? • E.g. : Triggering a batch or a notification • Create a resource with a GET? • Read a resource with a POST? • E.g Search with complex criteria • Update with DELETE, or Delete with PUT? Following standards makes intent explicit. Refer to the RFC-626
  • 9. Sample GET /user/new GET /new_user.x POST /user/new POST /user/delete GET /delete_user.x?id=123 GET /user?id=1 GET /user/id/1 GET /get/user/by/profile/id GET /get/user/address/by/city?city=paris GET /find/user/by/name?name=Bob PUT /user/update?id=100 GET /user/findBy?name=Bob&age=29 POST /user GET /user/2 DELETE /user/2 PUT /user/2 GET /user/address?city=paris
  • 10. RESTfull Sample @RestController @RequestMapping("/address") public class AdressController { @Autowired private AddressService addressService; @PostMapping(value = "") public AddressDto create(@RequestBody AddressDto address) { return addressService.save(address); } @PutMapping(value = "/{id}") public void update(@PathVariable Long id, @RequestBody AddressDto address) { addressService.updateById(id, address); } @DeleteMapping(value = "/{id}") public void delete(@PathVariable Long id) { addressService.deleteById(id); } @GetMapping(value = "") public Collection<AddressDto> findAll() { return addressService.findAll(); } }
  • 11. import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Address, Status } from '../address/address.model'; const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) }; @Injectable() export class AddressService { private url = 'api/address'; constructor(private http: HttpClient) { } create(address: Address): Observable<Address> { return this.http.post<Address>(this.url, user, httpOptions); } update(address: Address): Observable<Address> { return this.http.put<Address>(this.url + '/' + address.id, address, httpOptions); } delete(address: Address): Observable<void> { return this.http.delete<void>(this.url + '/' + address.id, httpOptions); } addresses(): Observable<Array<Address>> { return this.http.get<Array<Address>>(this.url, httpOptions); } } RESTfull Client Sample
  • 12. RESTfull Sample @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @PostMapping(value = "") public UserDto create(@RequestBody UserDto user) { return userService.save(user); } @PutMapping(value = "/{username}") public void updateById(@PathVariable String username, @RequestBody UserDto user) { userService.updateByUsername(username, user); } @DeleteMapping(value = "/{username}") public void deleteByUsername(@PathVariable String username) { userService.deleteByUsername(username); } @GetMapping(value = "", params = {"username"}) public UserDto findByUsername(@RequestParam String username) { return userService.findByUsername(username); } @GetMapping(value = "") public Collection<UserDto> findAll() { return userService.findAll(); } }
  • 13. import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { User, Status } from '../user/user.model'; const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) }; @Injectable() export class UserService { private url = 'api/user'; constructor(private http: HttpClient) { } create(user: User): Observable<User> { return this.http.post<User>(this.url, user, httpOptions); } update(user: User): Observable<User> { return this.http.put<User>(this.url + '/' + user.username, user, httpOptions); } delete(user: User): Observable<void> { return this.http.delete<void>(this.url + '/' + user.username, httpOptions); } users(): Observable<Array<User>> { return this.http.get<Array<User>>(this.url, httpOptions); } } RESTfull Client Sample
  • 14. Json-patch JSON Patch is a format for describing changes to a JSON document. It can be used to avoid sending a whole document when only a part has changed. { "username": "uncle", "firstname": "kong", "lastname": "to", " roles ": ["user"] } [ { "op": "replace", "path": "/username", "value": "donkey" }, { "op": "add", "path": "/roles", "value": ["admin"] }, { "op": "replace", "path": "/roles/0/name", "value": "guest" } { "op": "add", "path": "/age", "value": 25 } { "op": "remove", "path": "/firstname" } ] { "username": "donkey", "lastname": "to", "age": 25, "roles": ["guest", "admin"] }
  • 15. Json-patch sample @RestController @RequestMapping("/address") public class AdressController { @Autowired private AddressService addressService; @PostMapping(value = "") public AddressDto create(@RequestBody AddressDto address) { return addressService.save(address); } @PutMapping(value = "/{id}") public void update(@PathVariable Long id, @RequestBody AddressDto address) { addressService.updateById(id, address); } @PatchMapping(value = "/{id}") public void patch(@PathVariable Long id, @RequestBody List<JsonPatchOperation> operations) { this.addressService.patch(id, operations); } @PatchMapping(value = "/{id}", params = {"patchById"}) public void patchById(@PathVariable Long id, @RequestBody JsonPatch jsonPatch) { this.addressService.patchById(id, jsonPatch); } @DeleteMapping(value = "/{id}") public void delete(@PathVariable Long id) { addressService.deleteById(id); } @GetMapping(value = "") public Collection<AddressDto> findAll() { return addressService.findAll(); } }
  • 16. Json-patch sample public class AddressService { private AddressRepository addressRepository; public AddressService(AddressRepository addressRepository) { this.addressRepository = addressRepository; } public void updateById(Long id, AddressDto userDto) { Optional<AddressEntity> entity = addressRepository.findById(id); entity.ifPresent(u -> { BeanUtils.copyProperties(AddressMapper.from(userDto), u); addressRepository.save(u); }); } public void patchById(Long id, JsonPatch jsonPatch) { this.findById(id) .ifPresent(existing -> { try { ObjectMapper objectMapper = new ObjectMapper(); JsonNode patched = jsonPatch.apply(objectMapper.convertValue(existing, JsonNode.class)); AddressEntity patchedUser = objectMapper.treeToValue(patched, AddressEntity.class); addressRepository.save(patchedUser); } catch (JsonPatchException | JsonProcessingException e) { throw new IllegalStateException(); } }); } }
  • 17. Json-patch authorized operation public class AddressService { private AddressRepository addressRepository; public AddressService(AddressRepository addressRepository) { this.addressRepository = addressRepository; } public void patch(Long id, List<JsonPatchOperation> operations) { addressRepository.findById(id) .ifPresent(existing -> { ObjectMapper objectMapper = new ObjectMapper(); operations.stream().forEach(op -> { try { JsonNode node = objectMapper.readValue(op.toString(), JsonNode.class); // allow only add operation if ("add".equals(node.get("op"))) { JsonNode patched = op.apply(objectMapper.convertValue(existing, JsonNode.class)); AddressEntity patchedUser = objectMapper.treeToValue(patched, AddressEntity.class); addressRepository.save(patchedUser); } } catch (IOException | JsonPatchException e) { throw new IllegalStateException(); } }); }); } }