UP | HOME

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, l'état initial étant UN.

../medias/soc_automata_ab-star.svg

Automate reconnaissant le langage ((ab) + (ab) a)

Contrairement au premier TP, l'automate va être réparti en trois services au lieu d'un seul :

  • un service pour l'initialisation,
  • un service pour l'état UN,
  • un service pour l'état DEUX.

Avec une telle répartition, l'état des sessions devient doublement réparti : à tout moment, il est formé de l'ensemble des URI pointant vers les services et manipulées par les clients, comme nous allons le voir.

Cette pratique a une valeur paradigmatique, car l'état de nombreux services peut être modélisé par un automate. Elle permet d'obtenir un service "stateless" et d'appliquer le principe dit "Hateoas" ("Hypermedia As The Engine Of the Application State").

Q ? Donner les cinq principes caractérisant les architectures REST.

2 Automates : les règles chimiques

On spécifie les services 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 Services "stateless"

2.1.1 Service 0

Etat

  • Néant

Canal

  • initier(ar) : renvoie sur le canal ar le canal du service 1.

Règles

- initier(ar) -> ar(accepterUN)

2.1.2 Service 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 service 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 Service 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 service 1, ou refuse le caractère c et renvoie KO sur le canal ar.

Q ? Donner les règles chimiques décrivant le comportement du service 2 (correspondant à l'état DEUX).

- 
-

2.2 Client des services "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 de style Rest.

3.1 Préambule

3.1.1 Serveur (ServeurEval)

Créer un nouveau projet de type Dynamic web project. Nommer ce projet ServeurEval. Utiliser Tomcat 8.5 comme serveur. Noter que le nom du projet servira de préfixe aux chemins des ressources. Engendrer le fichier web.xml décrivant le déploiement. Transformer ensuite le projet en projet Maven.

  • Ajouter les dépendances suivantes dans le fichier pom.xml.

    <dependencies>
     <dependency>
      <groupId>org.glassfish.jersey.containers</groupId>
      <artifactId>jersey-container-servlet</artifactId>
      <version>2.26</version>
     </dependency>
     <dependency>
      <groupId>org.glassfish.jersey.inject</groupId>
      <artifactId>jersey-hk2</artifactId>
      <version>2.26</version>
     </dependency>
     <dependency>
      <groupId>org.glassfish.jersey.media</groupId>
      <artifactId>jersey-media-json-jackson</artifactId>
      <version>2.26</version>
     </dependency>
    </dependencies>
    
  • Dans le fichier WebContent/WEB-INF/web.xml, ajouter après l'élément welcome-file-list la référence de la servlet à utiliser.

    <servlet>
       <servlet-name>Jersey</servlet-name>
       <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    </servlet>
    <servlet-mapping>
       <servlet-name>Jersey</servlet-name>
       <url-pattern>/*</url-pattern>
    </servlet-mapping>
    

3.1.2 Client (ClientEval)

Créer un nouveau projet Java, de nom ClientEval.

  • Le transformer en projet Maven.
  • Ajouter les dépendances suivantes dans le fichier pom.xml.

    <dependencies>
     <dependency>
      <groupId>org.glassfish.jersey.core</groupId>
      <artifactId>jersey-client</artifactId>
      <version>2.26</version>
     </dependency>
     <dependency>
      <groupId>org.glassfish.jersey.ext</groupId>
      <artifactId>jersey-proxy-client</artifactId>
      <version>2.26</version>
     </dependency>
     <dependency>
      <groupId>org.glassfish.jersey.media</groupId>
      <artifactId>jersey-media-jaxb</artifactId>
      <version>2.26</version>
     </dependency>
     <dependency>
      <groupId>org.glassfish.jersey.media</groupId>
      <artifactId>jersey-media-json-jackson</artifactId>
      <version>2.26</version>
     </dependency>
     <dependency>
      <groupId>org.glassfish.jersey.inject</groupId>
      <artifactId>jersey-hk2</artifactId>
      <version>2.26</version>
     </dependency>
    </dependencies>
    

3.2 Modèle objet

Un modèle objet est fourni : cf. l'archive associée. Il contient deux interfaces et trois classes d'implémentations, correspondant aux trois services à déployer en trois adresses distinctes (adresses qui pourraient être associées à trois machines distinctes).

Interfaces

  • Automate
  • EtatAutomate

Classes d'implémentation

  • A_B_point_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).

Mettre à jour si nécessaire la constante JAXRS.PROJET avant tout usage de vos services. Sa valeur dépend du nom du projet dédié aux services, soit ServeurEval si les instructions liminaires ont été suivies à la lettre.

3.3 Services Rest sans état (stateless)

Importer dans le projet ServeurEval l'archive codeFourni_serveurEval.zip fournissant les éléments suivants.

  • paquet configuration contenant les classes 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

3.3.1 Annotations

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.

  1. Les méthodes HTTP annotant les méthodes objet correspondent à des requêtes pures et idempotentes.
  2. Les chemins relatifs d'accès aux ressources correspondant aux deux méthodes sont les suivants :
    • initier : automate/initial,
    • accepter : automate/suivant?etiquette=c.
  3. Les résultats sont produits au format application/xml (une constante déclarée dans la classe JAXRS).
  4. Toutes les méthodes utilisent le filtre AdapterReponsesNull404GET.

(Toutes les annotations JAX-RS appartiennent au paquet javax.ws.rs.)

Annoter les classes A_B_point_Etoile, EtatUn et EtatDeux de manière à garantir les deux propriétés suivantes :

  • ce sont des classes singletons,
  • les chemins d'accès sont donnés par les constantes JAXRS.CHEMIN_AUTOMATE, JAXRS.CHEMIN_UN et JAXRS.CHEMIN_DEUX respectivement.

Q ? Décrire le filtrage réalisé par le filtre AdapterReponsesNull404GET.

Q ? A quoi servent les annotations de la classe Hyperlien ?

Q ? Dans quelle norme sont-elles définies ?

Q ? Compléter les définitions suivantes.

  • Une requête est dite pure lorsque
  • Une requête est dite idempotente lorsque

Q ? Qualifier chaque type de requête HTTP par pur ou impur d'une part, et idempotent ou non-idempotent d'autre part.

  • GET :
  • PUT :
  • POST :

Q ? Quelles sont les cinq composantes d'une URI ?

3.3.2 Implémentation

Compléter la classe EtatDeux.

3.3.3 Déploiement et test

Vérifier (encore une fois) la valeur de la constante configuration.JAXRS.PROJET.

Dans le fichier web.xml, référencer à l'intérieur de l'élément servlet la définition des services dans la classe Service (du paquet configuration).

<init-param>
   <param-name>javax.ws.rs.Application</param-name>
   <param-value>configuration.Service</param-value>
</init-param>
<load-on-startup>1</load-on-startup>

Déployer les services sur le serveur Tomcat. Les services sont déployés sur le même serveur, mais avec des adresses différentes.

Tester les services avec votre navigateur.

Q ? Définir la requête initiale (méthode HTTP et URI).

Q ? Quelle est la réponse ?

Q ? Quel est le statut de la réponse ?

3.4 Client

Importer à la racine du projet ClientEval l'archive codeFourni_clientEval.zip. Elle fournit les paquets 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 LienVersRessource permettant d'obtenir un proxy de type T connecté à une ressource pointée par un hyperlien
  • Paquet client contenant les classes principales clientes

Mettre à jour si besoin la constante PROJET avant tout usage des services. Sa valeur dépend du nom du projet dédié au code des services.

Annoter les interfaces Automate et EtatAutomate comme sur le serveur, à l'exception du filtre, inutile côté client.

Dans la classe client.AppliCliente, implémenter le scénario suivant dans la fonction principale.

  • Créer une cible (de type WebTarget) en utilisant la variable clientJAXRS.
  • Créer un automate (en utilisant la fabrique WebResourceFactory).
  • Appeler la fonction tester en lui passant l'automate et le mot 'a', 'b', 'a', 'b', 'a', 'b', puis le mot 'a', 'b', 'a', 'b', 'a', 'a'.

Compléter la fonction tester ainsi.

  • Récupérer un hyperlien vers l'état initial de l'automate.
  • Tester si le mot passé en argument est accepté ou non.
  • Si c'est la cas, afficher dans la console : mot reconnu : X, où X est le mot passé en argument.
  • Sinon, récupérer l'exception de type WebApplicationException correspondant à une erreur de statut 404 pour afficher dans la console le message associé à l'exception puis la chaîne mot non reconnu : X.
  • Indication : pour transformer un hyperlien en un proxy, utiliser la fonction proxyEtat, qui, une fois complétée, renverra un proxy vers l'état de l'automate pointé par l'hyperlien.

Compléter la fonction proxyEtat en utilisant la classe LienVersRessource.

Tester votre application.

Q ? 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:
  • champ Accept:

Modifier la constante JAXRS.TYPE_MEDIA de manière à traiter des données au format JSON (côtés serveur et client).

Q ? Donner la réponse à la requête précédente au format JSON, dans cette nouvelle configuration.

Author: Hervé Grall
Version history: v1: 2016-04-20; v2: 2017-04-21[update]; v3: 2017-12-12[update].
Comments or questions: Send a mail.
The webpage content is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.