TP4 - Un automate doublement réparti
Table of Contents
1 Introduction : la répartition de l'automate
Comme dans le premier TP, on cherche à décrire un service proposant la reconnaissance de langages réguliers fermés par préfixe : ce sont les langages reconnus par des automates dont tous les états sont finals. Précisément, on s'intéressera au langage régulier \((ab)^\ast + (ab)^\ast a\) formé d'une succession, éventuellement vide, de mots \(ab\), suivi possiblement d'un \(a\). Par exemple, les mots \(ab\), \(aba\) et \(abab\) sont reconnus alors que le mot \(abaa\) n'est pas reconnu. Pour reconnaître ce langage, on utilise un automate à deux états, UN et DEUX.
Automate reconnaissant le langage ((ab)∗ + (ab)∗ a)
Contrairement au premier TP, l'automate va être réparti en trois serveurs au lieu d'un seul :
- un serveur pour l'initialisation,
- un serveur pour l'état UN,
- un serveur pour l'état DEUX.
Avec une telle répartition, l'état des sessions est naturellement réparti : à tout moment, il est formé de l'ensemble des URI pointant vers les serveurs et manipulées par les clients, comme nous allons le voir.
Cette pratique a une valeur paradigmatique, car l'état de nombreux serveurs peut être modélisé par un automate. Elle permet d'obtenir un serveur "stateless" et d'appliquer le principe dit "Hateoas" (Hypermedia As The Engine Of the Application State).
2 Automates : les règles chimiques
On spécifie les serveurs et les clients à l'aide de règles chimiques. Ce modèle permet une spécification non seulement concise mais aussi précise des échanges de messages.
2.1 Serveurs "stateless"
2.1.1 Serveur 0
Etat
- Néant
Canal
- initier(ar) : renvoie sur le canal ar le canal du serveur 1.
Règles
- initier(ar) -> ar(accepterUN)
2.1.2 Serveur 1
Etat
- Néant
Canal
- accepterUN(ar, c) : suivant la valeur de c, accepte le caractère c et renvoie sur le canal ar le canal du serveur 2, ou refuse le caractère c et renvoie KO sur le canal ar.
Règles
- accepterUN(ar, 'a') -> ar(accepterDEUX) - accepterUN(ar, x) & (x != 'a') -> ar(KO)
2.1.3 Serveur 2
Etat
- Néant
Canal
- accepterDEUX(ar, c) : suivant la valeur de c, accepte le caractère c et renvoie sur le canal ar le canal du serveur 1, ou refuse le caractère c et renvoie KO sur le canal ar.
TODO Donner les règles chimiques décrivant le comportement du serveur 2 (correspondant à l'état DEUX).
2.2 Client "stateless"
Etat
- quatre états internes : Debut, EnCours, Succes, Echec
- Mot(tab) : tableau de caractères tab formant le mot à transmettre à l'automate
Etat initial
Debut & Mot(['a', 'b', 'a', 'b'])
Canaux
- rep(x) : reçoit en réponse un canal ou un message d'erreur KO.
Règles
- Debut -> initier(rep) & EnCours - EnCours & rep(k) & Mot([tete, reste]) & (k != KO) -> k(rep, tete) & Mot(reste) & EnCours - EnCours & rep(k) & Mot([]) & (k != KO) -> Succes - EnCours & rep(KO) & Mot(m) -> Echec
3 Exercice pratique : implémentation de l'automate
On cherche à implémenter l'automate précédent par des services Web Restful.
3.1 Modèle objet
Un modèle objet est fourni : cf. l'archive associée. Il contient deux interfaces et trois classes d'implémentations, à répartir sur les trois serveurs respectivement.
Interfaces
- Automate
- EtatAutomate
Classes d'implémentation
- Par_AB_Par_Etoile
- EtatUn et EtatDeux
La classe de configuration configuration.JAXRS fournit toutes les constantes utiles. Elles doivent être systématiquement utilisées dans le code (et particulièrement dans les annotations).
TODO Mettre à jour la constante PROJET avant tout usage de vos services. Sa valeur dépend du nom du projet dédié au code des serveurs.
3.2 Services Restful sans état (stateless)
TODO Créer un nouveau projet Dynamic Web Project. Ajouter la bibliothèque cxf au projet. Y importer l'archive codeFourni_restServeur.zip fournissant les éléments suivants.
- paquet configuration contenant la classe de configuration
- paquet modele contenant le modèle objet
- paquet infrastructure.jaxrs contenant
- une classe générique Hyperlien<T> pour représenter un hyperlien vers une ressource de type T,
- le filtre AdapterReponsesNull404GET
- fichiers de configuration web.xml et restful-beans.xml pour le déploiement
3.2.1 Annotations
TODO Annoter les méthodes des interfaces Automate et EtatAutomate de manière à vérifier les propriétés suivantes.
Rappel : on utilisera les constantes déclarées dans configuration.JAXRS.
- Les méthodes HTTP annotant les méthodes objet correspondent à des requêtes pures et idempotentes.
- Les chemins relatifs d'accès aux ressources correspondant aux deux
méthodes sont les suivants :
- initier : automate/initial,
- accepter : automate/suivant?etiquette=c.
- Les résultats sont produits au format application/xml (une constante déclarée dans la classe JAXRS).
- Toutes les méthodes utilisent le filtre AdapterReponsesNull404GET.
(Toutes les annotations appartiennent au paquet javax.ws.rs.)
TODO Décrire le filtrage réalisé par le filtre AdapterReponsesNull404GET.
TODO A quoi servent les annotations de la classe Hyperlien ? Dans quelle norme sont-elles définies ?
3.2.2 Implémentation
TODO Compléter la classe EtatDeux.
3.2.3 Déploiement et test
TODO Vérifier la valeur de la constante configuration.JAXRS.PROJET.
TODO Déployer les services sur le serveur Tomcat. Les trois services sont déployés sur le même serveur, mais à des adresses différentes :
- http://localhost:8080/projet/serveur0,
- http://localhost:8080/projet/serveur1 et
- http://localhost:8080/projet/serveur2.
On pourrait aussi les déployer sur trois serveurs différents.
TODO Tester vos services avec le module POSTER (ou un module analogue).
TODO Donner le résultat d'une requête réussie (le corps du message).
TODO Quel est le statut d'une requête réussie ?
3.3 Client
TODO Créer un nouveau projet Java en y incluant la bibliothèque de CXF (Runtime). Y importer à la racine l'archive codeFourni_restClient.zip fournissant les éléments suivants.
- paquet configuration contenant la classe de configuration
- paquet modele contenant le modèle objet (interfaces uniquement)
- paquet infrastructure.jaxrs contenant
- une classe générique Hyperlien<T> pour représenter un hyperlien vers une ressource de type T,
- une classe générique ClientRessource<T> pour représenter un proxy de type T client d'une ressource pointée par un hyperlien
TODO Mettre à jour la constante PROJET avant tout usage des services. Sa valeur dépend du nom du projet dédié au code des serveurs.
TODO Annoter les interfaces Automate et EtatAutomate comme sur le serveur, à l'exception du filtre, inutile côté client.
TODO Dans une classe modele.Client, implémenter le scénario suivant dans la fonction principale.
- Créer un automate (en utilisant la fabrique JAXRSClientFactory.create).
- Récupérer l'état initial de l'automate.
- Initialiser un mot avec le tableau de caractères {'a', 'b', 'a', 'b', 'a', 'b'}.
- Vérifier si ce mot est accepté en appelant les serveurs distants.
- Si c'est le cas, afficher un message de succès, sinon afficher un message d'échec.
- Refaites le test avec le mot {'a', 'b', 'a', 'b', 'a', 'a'}.
- Récupérer l'exception de type WebApplicationException correspondant à une erreur de statut 404.
TODO Tester votre application.
TODO Décrire une requête correspondant à l'invocation de la méthode accepter dans l'état UN et avec l'étiquette *'a'*.
méthode Http : Adresse :
TODO Décrire la réponse.
TODO Comment faire pour obtenir des réponses au format JSON ? Quelle est la réponse alors ?