Web services - API REST
Introduction aux API REST¶
Une API ou Application Programming Interface est une interface permettant d'exposer les fonctions d'un logiciel au monde exterieur.
Une API référence les différentes fonctions (services) de l'application qui sont accessibles par le consommateur.

Representational State Transfert1 (REST) est un type d'architecture pour les systèmes distribués qui propose de représenter le modèle de données et les services sous la forme de ressources (web services).
L'architecture REST définie un ensemble de conventions et de bonnes pratiques à respecter, il ne s'agit pas d'une technologie à part entière.
L'architecture REST est simple et se repose sur les méthodes standards du protocole HTTP, à l'instar des protocoles SOAP et XML-RPC qui sont des surcouches basées sur le procole HTTP.
REST est une architecture sans état (stateless) du côté du serveur. Le fait d'être «sans état» signifie que le serveur ne mémorise pas l'état du client entre deux requêtes. Du point de vue du serveur, chaque requête est une entité distincte des autres.
Le format d'échange entre le client et le serveur le plus couramment utilisé pour les API REST est le JSON2(JavaScript Object Notation).
Une ressource REST c'est :
- Une
URI: représente une ressource unique sur le système. - Un verbe
HTTP: identifie l'opération à réaliser. - Des entêtes
HTTP: défini le format du contenu d'échange, le jeton d'authentification, la version de la ressource à utiliser etc... - Des paramètres de requêtes : définissent des paramètres facultatifs à la ressource.
- Une réponse
HTTP: représente l'état de la ressource (via un codeHTTPet du contenu).

L'URI comme identifiant des ressources¶
L'apporche REST se base sur les URI (Uniform Resource Identifier) afin d'identifier une ressource.
Les ressources (URI) doivent rester simple cf. KISS (Keep It Simple, Stupid) :
Les ressources sont basées sur des noms et non des verbes, c'est la méthode HTTP qui determine l'opération à réaliser.
Quelques exemples de construction d'URL REST correspondant aux fonctionnalités de l'application Room Manager vue dans les séances précédentes :
Cible toutes les salles :
Cible une salle (d'identifiant 12):
Cible les évènements d'entrée/sortie pour une salle :
Cible l'évènement d'entrée/sortie (d'identifiant 345) pour une salle :
Les verbes HTTP comme identifiant des opérations¶
L'approche REST se base sur la méthode HTTP pour determiner l'opération à réaliser.
L'utilisation des verbes HTTP rend l'API intuitive et permet d'éviter que le développeur n'ait à consulter une documentation verbeuse pour comprendre comment manipuler les ressources.
Les verbes HTTP correspondant aux opérations de type CRUD :
- Créer (Create) :
POST - Afficher (Read) :
GET - Mettre à jour (Update) :
PUT - Mettre à jour partiellement (Update) :
PATCH - Supprimer (Delete) :
DELETE
Ressources et actions associées en fonction du verbe HTTP utilisé dans room manager¶
| Ressource\Action | POST |
GET |
PUT |
DELETE |
|---|---|---|---|---|
/rooms |
Crée une salle | Liste toutes les salles | Met à jour toutes les salles | Supprime toutes les salles |
/rooms/12 |
- | Lit la salle 12 | Met à jour la salle 12 | Supprime la salle 12 |
/rooms/12/events |
Ajoute un évènement à la salle 12 | Liste tous les évènements de la salle 12 | Met à jour tous les évènements de la salle 12 | Supprime tous les évènements de la salle 12 |
/rooms/12/events/345 |
- | Lit l'évènement 345 de la salle 12 | Met à jour l'évènement 345 de la salle 12 | Supprime l'évènement 345 de la salle 12 |
Ainsi pour une même URI plusieurs actions sont disponibles :
Afficher la liste des salles¶
Contenu de retour :[
{
"id" : 12,
"name" : "Salle 307"
},
{
"id" : 13,
"name" : "Salle 311",
"description" : "La salle de TD JEE"
}
]
Ajouter une salle¶
Contenu de reqûete : Code retour Contenu de retourLes paramètres de requetes (Query strings)¶
Les paramètres de reqûetes viennent en complément de l'URI, ils peuvent nottament servir à ajouter des fonctions :
- De recherche / filtre,
- De tri,
- De pagination
Dans l'exemple suivant :
- Le paramètre
searchpermet de filtrer les résultats contenant le mot clé fourni :informatique. - Le paramètre
orderpermet de trier les résultats par ordre croissant/décroissant.
Les entêtes (headers)¶
Les entêtes HTTP permettent de fournir des informations complémentaires sur la nature de l'échange entre le client et l'API.
Par exemple, l'appelant doit définir quel format de réponse il souhaite reçevoir via l'entête Accept (à condition que le format de réponse demandé soit supporté par l'API) :
- Entête permettant de demander le contenu de réponse au format JSON :
Accept: application/json, - Entête permettant de demander le contenu de réponse au format XML :
Accept: application/xml
L'entête Accept-Language permet de préciser dans quelle langue le client souhaite recevoir le contenu.
L'entête Authorization permet de définir les informations d'authentification.
Les codes retour¶
La méthode REST se base sur les codes retour HTTP pour préciser le statut d'une ressource suite à l'exécution d'une requête.
Il existe plus de 70 codes HTTP regroupés en 5 grandes familles, ils sont composés de trois chiffres et sont catégorisés en fonction du chiffre des centaines :
1xx- Réponses informatives.2xx- Réponses de succès.3xx- Réponses de redirection.4xx- Réponses d'erreur côté client.5xx- Réponses d'erreur côté serveur.
Les codes retour les plus couramment utilisés dans les API `REST sont les suivants :
200- OK - code de base indiquant la réussite d'une requête.201- Created - indique que la requête a réussi et qu'une ressource a été créée en conséquence.204- No Content - indique que la requête a réussi et que le serveur ne renvoie pas de contenu (requêtePUT).400- Bad Request - indique que le serveur ne peut pas comprendre la requête en raison d'une syntaxe invalide.404– Not Found - indique qu'un serveur ne peut pas trouver la ressource demandée.401- Unauthorized - indique que la requête n'a pas été effectuée car il manque des informations d'authentification valides.403- Forbidden - indique qu'un serveur comprend la requête mais refuse de l'autoriser (problème de droit d'accès).415- Unsupported Media Type - indique que le serveur refuse la requête car le format de contenu demandé n'est pas pris en charge.500- Internal Server Error - indique que le serveur a rencontré un problème inattendu qui l'empêche de répondre à la requête.
API REST en JAVA : JSR-311 JAX-RS¶
La spécification concernant les API REST en JEE est la JSR 3114: JAX-RS: The JavaTM API for RESTful Web Services
Les JSR 339 et 370 sont des mises à jour de la JSR 311.
La construction d'une ressource REST en java à l'aide de JAX-RS est réalisé de la façon suivante :
- L'
URI/ le chemin de la ressource est défini par l'annotation@Path - Les verbes
HTTPsont définis par les annotations suivantes *@GET*@POST*@PUT*@DELETE*@HEAD*@PATCH - Les variables déclarées dans l'
URIde la ressource@Pathsont définies via l'annotation@PathParam - Les paramètres de requêtes (query parameters) sont définis via l'annotation
@QueryParam - Les types de médias3 (MIME types) consommés en entrée et délivrés en sortie sont définis respectivement par les annotations
@Consumeset@Produces
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.sun.jersey.api.NotFoundException;
@Path("/rooms") // Le point d'entrée de toutes les ressources déclarées dans la classe
public class RoomResource {
/**
* Retrieve a room by its name.
*
* @param roomId room identifier
* @return found room
*/
@GET // Précise qu'il s'agit d'une ressource de lecture (READ)
@Path("/{roomId}") // Le point d'entrée déclare le PathParam roomId
@Produces({MediaType.APPLICATION_JSON + "; charset=UTF-8"}) // (Response Header) la resource GET renvoie du contenu de type "application/json"
public RoomDetailsVO getRoom(@PathParam(value = "roomId") long roomId) { // Le Path Param roomId est de type "long", une ressource valide est donc : /rooms/12
logger.debug("Retrieve room with id {}", roomId);
//Retrieve rooms from DB
final Room room = roomDao.get(roomId);
if (room == null) {
throw new NotFoundException("Room with id " + roomId + " does not exist");
}
// TODO : Convert rooms into visual object (select only necessary fields)
RoomDetailsVO roomVO = new RoomDetailsVO();
//Return room
return roomVO;
}
}
Plusieurs librairies implémentent la spécification JAX-RS.
Dans le cadre du TD nous utiliserons le projet JERSEY 1.195 fourni par Oracle / Glassfish
Les dépendances Jersey à ajouter dans un projet WEB géré par Guice sont les suivantes :
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-guice</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.9</version>
</dependency>
com.sun.jersey.contribs:jersey-guiceCelle-ci contient entre-autres une classe déclarant un module Guice spécifique pour Jersey :
JerseyServletModule
En effet, c'est le filtre de servlet Guice qui intercepte toutes les requêtes HTTP (cf. configuration dans le fichier de description web.xml) et qui déclare le listener de contexte de Servlet Guice fr.iut.rm.web.WebGuiceServletConfig
Le listener crée l'injecteur Guice et les différents modules du projet dont le module spécifique pour la couche d'API : RestServletModule
this.currentInjector = Guice.createInjector(new MainModule(), new WebModule(interceptors), new RestServletModule());
Contenu du module Guice de configuration de Jersey RestServletModule :
import com.google.inject.persist.PersistFilter;
import com.google.inject.persist.jpa.JpaPersistModule;
import com.sun.jersey.guice.JerseyServletModule;
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServlet;
/**
* Servlet module used to serve REST resources
*/
public class RestServletModule extends JerseyServletModule {
/**
* Logger
*/
private static final Logger logger = LoggerFactory.getLogger(RestServletModule.class);
@Override
protected void configureServlets() {
logger.debug("Configuration started");
//JPA management
install(new JpaPersistModule("room-manager"));
filter("/*").through(PersistFilter.class);
// Route all requests through GuiceContainer
serve("/*").with((Class<? extends HttpServlet>) GuiceContainer.class);
logger.debug("Configuration done");
}
}
Le module démarre également le moteur de persistance JPA (JpaPersistModule)
Exercice¶
L'exercice consiste à récupérer le projet room-manager-api-src.tar.gz puis d'enrichir les ressources d'API contenues dans la classe RoomResource
1 - Enrichir la méthode existante de création de salle createRoom, pour permettre l'enregistrement d'une salle en base de données.¶
Utiliser la commande curl suivante pour valider l'enregistrement d'une salle :
curl -X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name":"Salle 311","description":"La salle de TD JEE"}' \
"http://localhost:8080/room-manager-api/rooms"
Utiliser la commande curl suivante pour Lister toutes les salles
2 - Enrichir la méthode de lecture d'une salle getRoom¶
Utiliser la commande curl suivante pour la récupération d'une salle en prenant soin de selectionner un identifiant valide
3 - Enrichir la ressource permettant de lister toutes les salles listRooms en y ajoutant un paramètre de filtre sur le nom de la salle¶
Choisissez un nom de paramètre (exemple q) puis testez le à l'aide la commande suivante :
4 - Ajouter la ressource permettant d'ajouter un accès à une salle existante¶
Un nouvel évènement du point de vue l'API est composé des informations suivantes :
- nom de l'utilisateur
- type d'accès (IN/OUT)
L'identifiant de la salle concernée est récupérée dans l'URI,
La date de l'accès est positionné dans la méthode lors de la création de l'évènement en base.
La ressource doit renvoyer un code retour http 200 et l'identifiant de l'accès nouvellement créé.
La ressource doit renvoyer un code retour http 404 si l'accès porte sur une salle inexistante.
Utiliser la commande curl suivante pour valider l'enregistrement d'un évènement :
curl -X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"userName":"John DOE","type":"IN"}' \
"http://localhost:8080/room-manager-api/rooms/12/events"
5 - Ajouter la ressource permettant de lister tous les évènement d'accès à une salle¶
Utiliser la commande curl suivante pour tester
Ajouter un filtre sur le type d'évènement type puis tester avec la commande suivante
curl -H "Accept: application/json" \
"http://localhost:8080/room-manager-api/rooms/12/events?type=OUT"
6 - Ajouter la ressource permettant de supprimer un évènement d'accès à une salle¶
Utiliser la commande curl suivante pour tester
Utilisation d'un client graphique¶
L'utilisation d'un client d'API graphique peut s'avérer plus confortable que l'outil en ligne de commande cURL.

POSTMAN est l'outil graphique de référence permettant de gérer l'ensemble des interactions avec les API REST.
Quelques exemples d'utilisation¶
Création d'une salle POST /rooms:

Lecture de la liste des salles GET /rooms:

Lecture de la salle #1 GET /rooms/1:
¶
-
https://fr.wikipedia.org/wiki/Representational_state_transfer ↩
-
https://www.json.org/json-fr.html ↩
-
https://developer.mozilla.org/fr/docs/Web/
HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types ↩ -
https://jcp.org/en/jsr/detail?id=311 ↩
-
https://jersey.github.io/ ↩
-
https://www.getpostman.com/downloads/ ↩
-
https://developer.paypal.com/docs/api/overview/ ↩
-
https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol#M%C3%A9thodes ↩
-
https://docs.oracle.com/cd/E19798-01/821-1841/6nmq2cp1v/index.html ↩
-
https://openclassrooms.com/fr/courses/3449001-utilisez-des-api-rest-dans-vos-projets-web/3449008-quest-ce-quune-api ↩
-
https://blog.octo.com/designer-une-api-rest/ ↩