Communication entre une applet et une servlet

Chapitres traités   

Attention : Dans cette étude, il serait préférable de demander la reconstruction complète des projets que vous téléchargez sur votre ordinateur, pour qu'ils correspondent parfaitement au serveur Tomcat que vous utilisez. Pour bien maîriser cette étude, il est nécessaire d'avoir pris connaissance avec les rubriques antérieures, comme les applets et les applets mais également avec la notion de page Web dynamiques.


Pour en savoir plus sur les applets et les servlets, les pages Web dynamiques.

Communication Applet - Servlet

Dans le chapitre précédent, nous avons pris connaissance avec les servlets, notamment dans une utilisation classique où la servlet répond à une requête issue d'un formulaire HTML. Avec la technologie Java, il est possible de dépasser largement ce standard d'utilisation, en remplaçant notamment les formulaires HTML par une applet Java, ce qui laisse envisagé plus de possibilité. Souvenez-vous que dans une applet, nous pouvons placer tout ce que nous désirons comme pour une application classique, en introduisant par exemple des menus, des onglets, des zones de saisie, etc.

Bref, une applet présente une interface utilisateur plus sophistiquée. L'avantage de l'applet, c'est qu'elle fonctionne constamment "en temps réel", répond aux événements de la souris, tout en restant sur la même page Web. Ce principe est intéressant, puisque si dans l'applet nous utilisons également des formulaires, il est possible de contrôler les valeurs d'entrée avant d'envoyer la requête.

Nous pouvons donc utiliser une applet côté client et une servlet côté serveur. Souvenez-vous que dans l'utilisation classique, une servlet répond à la requête proposée par le navigateur, généralement au travers d'un formulaire en envoyant une nouvelle page Web - page Web Dynamique. Lorsque la servlet est en communication avec une applet, c'est l'applet qui propose une requête et c'est la même applet qui reçoit le résultat, et ceci tout en restant sur la même page Web. Avec ce principe, nous obtenons une plus grande souplesse d'utilisation sans mettre en oeuvre les pages Web dynamiques.

Comme nous communiquons avec le serveur Web, le standard de communication est le protocole HTTP classique. Nous pouvons d'ailleurs choisir d'utiliser les méthodes classiques get et post.

  1. La méthode get est beaucoup plus simple d'utilisation mais elle ne permet pas d'envoyer intrinsèquement tout type d'information. Elle permet uniquement de placer du texte à la suite de son URL. Par contre, avec une applet, la réponse à la requête peut-être de n'importe quel type. Nous pouvons donc renvoyer des objets en retour.
  2. La méthode post est plus compliquée et également plus lourde (de façon interne). En contre parti, elle est plus performante. Elle permet d'effectuer des échanges bidirectionnels et de dépasser le cadre d'envoie de texte ou de page HTML. En fait, en prenant la méthode post, nous nous retrouvons dans la même situation que lors de l'utilisation des sockets. Il est alors possible d'envoyer et de recevoir n'importe quel type de flux de données. Notamment, et c'est là toute la puissance du système, il va être possible de passer des objets plus ou moins sophistiqués au travers du tube HTTP.

Objectif : Dans cette étude, nous allons utiliser les deux méthodes d'appel afin de nous familiariser d'une part avec le protocole HTTP et d'autre part avec la puissance de la technologie Java.

Il faut souligner, pour terminer, que puisque nous utilisons le tube HTTP, nous ne serons nullement inquiété par le Firewall, puisque ce dernier accepte tout ce qui passe par le port 80 (ou 8080 si il est réglé pour cela).

Rappel : Attention, pour la mise en place des projets, et puisque nous utilisons des applets, il absolument nécessaire de définir le répertoire de sortie de telle sorte qu'il corresponde au répertoire d'utilisation de votre application Web contenant la servlet. Revoir les cours antérieurs si nécessaire.

Dans le premier chapitre, nous allons construire le projet en entier pour se rappeler ses principes et bien maîtriser l'ensemble du concept. Pour les autres chapitres, nous nous interesserons uniquement aux codes sources. Par ailleurs, nous utiliserons systématiquement le même sujet, mais traité avec des solutions différentes.

 

Choix du chapitre Communication Applet-Servlet avec échange de textes par la méthode GET

L'exemple qui suit ne présente pas une grande utilité puisque l'applet pourrait se débrouiller toute seule sans l'intervention de la servlet. De plus, l'applet et la servlet sont très rudimentaires. Le but est de comprendre la communication entre les deux sans rajouter de choses trop complexes par ailleurs. Il sera toujours temps de le faire par la suite. En fait, l'applet va disposer d'un texte qui sera envoyé au serveur Web lorsque l'on cliquera sur le bouton. La servlet renverra alors à l'applet le même texte mais à l'envers.

Construction du projet et mise en place de l'application Web

Comme toujours lorsqu'il s'agit de mettre en oeuvre une application Web, il est préférable de faire en sorte que l'ensemble de votre projet avec les sources nécessaires soient placés en dehors de votre serveur Web afin de préserver une certaine confidentialité et afin de se prémunir contre les intrusions externes. L'application Web - version compilée avec toute l'arborescence inhérente à toute application Web, avec descripteur de déploiement, etc. - doit par contre être située dans un autre répertoire afin qu'elle puisse être déployée.

Rappelez-vous que l'application Web est celle qui est demandée à la suite de l'URL par le navigateur client :

http://site/applicationWeb ou dans notre cas http://NomDeVotreSite:8080/InversionGet

Il est généralement souhaitable que le nom de votre projet porte le même nom que votre application Web. Le nom de notre projet sera donc <InversionGet.jpx>. Le choix des répertoires n'a pas une grande importance sauf pour le répertoire de sortie puisque nous utilisons une applet. En effet, l'applet avec sa page Web doit impérativement être placées directement dans la structure de l'application Web et même au niveau de la racine de cette application.

Pour en savoir plus sur le serveur Tomcat.

Mise en place de l'application Web

Tout de suite après, comme nous le savons maintenant, nous devons impérativement définir l'application Web en sollicitant l'expert approprié. Vous pouvez choisir le nom que vous désirez. Personnellement, afin d'éviter de se casser la tête, je donne lui donne le même nom que le projet.

Nous avons donc pris comme nom, le nom de l'application Web correspondante. Toutefois, il s'agit juste d'un nom d'affichage qui descrit l'application Web. Vous pouvez placer, en fait, le texte qui vous convient.

Construction de l'applet AppletInversion

Nous faisons appel ensuite à l'expert applet pour construire notre applet - de dimension 270x150 - avec sa page Web que vous appellerez AppletInversion et qui hérite de JApplet.

revoir le cours sur les applets si nécessaire.

Penser à changer le nom de votre page Web en <index.html> afin que se soit plus agréable lors de la saisie de l'URL.
.

Dans le mode "Conception", vous allez construire votre applet de dimension 270 par 150. Vous placerez dans la partie basse de l'applet un panneau sur lequel vous placerez une zone de saisie et un bouton qui s'appelleront tout simplement saisie et envoyer. Vous placerez également dans la zone principale de l'applet un label que vous nommerez message.

Réglage de la page Web

Avant d'aller plus loin, nous allons tout de suite régler la page Web afin de bien contrôler l'interface graphique de notre applet. Nous nous interesserons au codage propre à la communication tout de suite après. Saisissez et modifier le code de la page Web tel que cela vous est présenté ci-dessous.

Effectuer la compilation du projet et placez-vous en mode vue de votre page Web <index.html>. Voilà, ce que vous devez obtenir.

Codage pour la communication avec la servlet

Nous pouvons maintenant nous intéresser plus précisément de la communication avec la servlet. Lorsque nous cliquons sur le bouton Envoyer, le texte se trouvant dans la zone de saisie doit être envoyé à la servlet. Cette dernière transforme le texte pour le mettre à l'envers et ensuite le renvoit à l'applet. Ce texte est visible et remplace le libellé de l'objet message. C'est donc au moment de l'action sur le bouton que l'ensemble de ces opérations se réalise.

1ere solution - C'est celle qui sera utilisée.

2ème solution - Avec prise en compte de la classe URLConnection

Nous avons ci-dessus la méthode qui correspond à l'action sur le bouton "Envoyer". Toute la communication avec la servlet se fait à ce moment précis. L'applet envoie une requête à l'aide du protocole HTTP par la méthode GET. Il est alors nécessaire que le couple nom/valeur représentant le texte (un seul paramètre) à traiter soit placé directement à la suite de l'URL. La servlet récupère ensuite ce paramètre, traite la demande et renvoie aussitôt le résultat à l'applet qui se propose de l'afficher.

La classe URL que nous décrivons à la suite, permet de s'occuper de l'ensemble de la communication. Elle est capable de gérer le protocole HTTP, de lancer la requête et de récupérer le résultat en ouvrant une connexion adaptée au flux prévu par le type de réponse.

La classe URL

La classe URL représente une adresse URL et fournit une API simple d'accès aux ressources Web, tels que les documents et applications - servlets - disponibles sur les serveurs. Cette classe est très performante puisqu'elle prend en charge différents protocoles : http://, ftp:// et file://.

java.net.URL
URL(String nom); Crée un objet URL à partir d'une chaîne décrivant une URL absolue.
URL(URL base, String nom); Crée un objet URL relatif. Lorsque la chaîne nom décrit une URL absolue, l'URL de base est ignorée. Sinon, elle est interprétée comme un répertoire relatif à l'URL de base.
URL(URL protocole, String hôte, String fichier); Crée un objet URL en séparant le protocole du nom de l'hôte et du fichier à lire.
URL getDocumentBase(); Récupère l'URL de la page Web HTML contenant l'applet. Cela permet de référencer indirectement une servlet faisant partie de la même application Web.
String getFile();
String getHost();
String getPort();
String getProtocol();
String
getRef(); 
Ces méthodes retournent les différentes parties de l'URL spécifiée par l'objet URL.
InputStream openStream();

Cette méthode crée implicitement la connexion avec la ressource distante en envoyant la requête désignée par l'URL et ouvre un flux en lecture afin de permettre la récupération de la réponse.

Dans cette classe URL, il n'existe pas de méthode permettant d'ouvrir un flux en mode d'écriture. Si nous prévoyons d'utiliser la méthode POST du protocole HTTP, il sera nécessaire de prendre la méthode openConnection() ci-dessous et de créer un objet de la classe URLConnection. Cette classe, plus sophistiquée, dispose d'un ensemble de méthodes qui permet de prévoir tous les cas de figure et de travailler plus finement avec l'URL.

URLConnection openConnection(); Renvoie un objet URLConnection. A un niveau légèrement plus complexe, un objet URLConnection peut être extrait d'un objet URL donné. La classe URLConnection fournit des méthodes supplémentaires qui vous permettent de travailler de manière plus sophistiquée avec les URL. (Ce sujet sera abordé avec la méthode POST).

Un objet URL gère toutes les informations se trouvant dans une chaîne d'URL et fournit des méthodes permettant de récupérer l'élément identifié. Nous pouvons construire un objet URL à partir d'une chaîne de désignation d'une URL, ou de ses composants :

URL maPage = new URL("http://truc.bidule.fr/index.html");
URL maPage = new URL("http", "truc.bidule.fr", "index.html");
URL maPage = new URL(applet.getDocumentBase(), nomServletALancer);

A ce moment, l'objet URL ne contient que des données concernant son emplacement et la façon d'y accéder. Aucune connexion au serveur n'a étté établie. Nous pouvons ultérieurement examiner les composants de la classe URL avec les méthodes getProtocol(), getHost(), et getFile().

Lorsqu'un objet URL est créé, ses spécifications sont analysées pour identifier le protocole. Si le protocole n'a aucune signification ou si Java ne peut trouver un gestionnaire de protocole correspondant, le constructeur URL lève une exception MalformedURLException. Un gestionnaire de protocole est une classe Java qui implémente les protocoles de communication permettant d'accéder à la ressource de l'URL. Par exemple, en présence du protocole HTTP dans une URL, Java se prépare à utiliser le gestionnaire de protocole HTTP pour récupérer les documents du serveur spécifié.

Pour récupérer la réponse à la requête délivrée par l'URL, vous devez utiliser la méthode openStream(). Elle renvoie un flux d'entrée de type InputStream à partir duquel il est possible de transiter tout type d'information en chaînant avec des flux de plus haut niveau, comme c'est le cas dans notre exemple.

Pour en savoir plus sur les flux.

Attention, c'est au moment de l'appel de cette méthode openStream() que la connexion avec la ressource distante s'effectue. C'est à ce moment là, que la requête est envoyée. La réponse est aussitôt renvoyée en gardant la même connexion.

La classe URLEncoder

Dans le cadre de la méthode GET du protocole HTTP, vous devez préciser les paramètres à la suite de la chaîne représentant l'URL en respectant la syntaxe prévue pour cela. Il faut, par exemple, arriver à envoyer l'URL suivante :

http://localhost:8080/ServletInversion?message=Bonjour%20%85%20tous

La syntaxe générale de l'URL correspondant à la méthode GET est la suivante :

  1. Localisation du site (donc du serveur) : http://localhost:8080/
  2. Programme à lancer côté serveur pour traiter la requête désirée - ici le nom de la servlet: ServletInversion
  3. Un point d'interrogation ? : opérateur pour séparer le programme des paramètres qui vont servir au traitement.
  4. Paramètres qui servent au traitement, chacun est séparé du suivant par l'opérateur &.
  5. Chaque paramètre possède un nom (message) suivi de l'opérateur = suivi ensuite de la valeur (Bonjour%20%85%20tous) que prend ce paramètre.

Vous remarquez que la valeur du paramètre est un peu particulière. Elle correspond en fait à la valeur : Bonjour à tous. Une URL ne doit pas posséder d'espace ou de caractères accentués. Un codage spécial est utilisé pour éliminer ce problème. Chaque lettre posant un problème doit être transformée par le symbole % suivi du code ASCII correspondant exprimé en hexadécimal.

Heureusement, Le langage Java dispose d'une classe URLEncoder qui effectue automatiquement cette opération par l'intermédiaire de la méthode statique encode. Cette méthode dispose de deux arguements. Le premier correspond à la chaîne à traiter, le deuxième correspond au type d'encodage à réaliser. Pour la gestion des caractères français, vous devez spécifier la chaîne : "ISO-8859-1".

Vous devez utiliser cette méthode pour chacune des valeurs qui posent problèmes (et éventuellement pour le nom des paramètres si vous décidez d'utiliser les caractères accentués). Vous ne pouvez pas utiliser cette méthode pour la chaîne URL au complet, sinon les symboles : =, ?, & seraient également encodés.

Cela peut devenir fastidieux si vous devez passer beaucoup de paramètres. Eventuellement, vous pouvez alors utiliser la méthode POST du protocole HTTP.

Conclusion : Nous avons passé pas mal de temps à décrire les différentes classes mis en jeu. Toutefois, le codage reste vraiment simple. Très peu de lignes sont écrites. Toute la gestion du protocole HTTP est totalement encapsulé par la classe URL.

Construction de la servlet ServletInversion

Il ne reste plus maintenant qu'à fabriquer notre servlet en utilisant l'expert que vous appellerez ServletInversion.

Attention, sélectionnez bien la méthode doGet, puisque c'est la méthode GET qui a été choisie dans l'applet.

Attention également. Il faut que le nom spécifié dans la rubrique "Modèle d'URL" corresponde parfaitement à l'appel de la servlet proposé par l'applet au moment de la construction de l'URL.

URL url = new URL(getDocumentBase(), "ServletInversion?message="+ codageValeur);

Le codage de la servlet ServletInversion est extrêmement simple. Il suffit d'utiliser respectivement les objets déjà créés request et response que nous connaisons déjà.

Le premier objet request encapsule tout le protocole HTTP, décode automatiquement les différents paramètres proposés par la requête et permet de récupérer la valeur du paramètre passé dans l'URL grâce à la méthode getParameter.

L'objet response permet de rester en communication avec le client - applet - qui a sollicité la requête, et permet donc de renvoyer le résultat en utilisant le flux qui correspond à l'échange prévu (ici une chaîne de caractère). Comme pour l'applet, les flux utilisés sont des flux spécialisés pour le texte.

Déploiement et test

Tout est prêt. Il ne reste plus qu'à compiler l'ensemble de votre projet et de faire en sorte que votre application Web soit reconnue par le serveur Tomcat afin que vous puissiez la tester à l'aide de votre navigateur. Vous devez faire appel au "Gestionnaire d'applications Web Tomcat" pour que votre application Web soit reconnue par Tomcat.

ou bien

Après le lancement de votre application Web, vous pouvez utiliser votre applet comme il vous semble. Elle correspondra si nécessaire avec la servlet présente dans le serveur Web Tomcat afin d'effectuer les différents traitements sollicités par cette dernière.

Conclusion : Très souvent, la durée de vie d'une servlet est très courte. C'est le cas ici, puisque la servlet est créée uniquement au moment où l'utilisateur clique sur le bouton "Envoyer". La servlet reçoit le message, exécute tout ce qu'elle doit faire et ensuite renvoie le résultat vers l'applet. Une fois que tout est terminé, la servlet meurt d'elle même. Pendant ce court laps de temps, beaucoup d'objets sont créés. Ils sont tous bien adaptés à la situation.

 

Choix du chapitre Communication Applet-Servlet avec échange de textes par la méthode POST

Nous allons reprendre exactement le même sujet d'expérience. La seule différence concerne la méthode d'appel au niveau de la requête proposée par l'applet. Cette fois-ci, nous allons utiliser la méthode POST du protocole HTTP.

Cette fois-ci, nous n'allons pas perdre de temps avec toutes les explications requises pour mettre en oeuvre le projet ainsi que l'application Web. Je vous invite juste à prendre comme nom InversionPost, à la fois pour le projet ainsi que pour l'application Web. Nous allons nous intéresser uniquement aux codes source respectifs.

AppletInversion

Nous avons ci-dessus la méthode qui correspond à l'action sur le bouton "Envoyer". Je rappelle que toute la communication avec la servlet se fait à ce moment précis. Nous nous intéressons uniquement sur ce codage puisque c'est uniquement là que subsiste les différences. Nous avons quelques changements par rapport à l'applet du chapitre précédent.

Il faut se rappeler que la méthode POST du protocole HTTP envoie les valeurs des paramètres dans le corps même de la requête et non via l'URL. De cette façon, aucune valeur n'apparaît dans l'URL. Cette dernière reste fixe quelles que soient les options choisies par l'internaute.

Du coup, la fabrication de l'objet de type URL devient plus simple à implémenter puisque nous n'avons plus à placer les différents paramètres à la suite de la chaîne de caractère représentant l'URL. Nous n'avons plus à nous préoccuper de la classe URLEncoder. Toutefois, la classe URL ne permet pas d'établir une connexion en mode écriture. C'est logique puisque normalement, en mode classique - c'est-à-dire par la méthode GET - toute la requête est implémentée directement dans l'adresse URL.

La classe URLConnection

Nous devons utiliser une autre alternative. Il existe la classe URLConnection qui propose un contrôle plus poussé que celui qui est disponible avec les méthodes plus simples de la classe URL. En effet, cette classe est capable de connaître le type MIME du contenu de l'information envoyée ou reçue. Elle peut faire en sorte d'enlever de l'historique du navigateur l'URL que nous envoyons. Elle permet d'envoyer des requêtes une fois la connexion établie (mode POST), etc.

java.net.URLConnection
void setDoInput(boolean validation); Si validation vaut true, l'utilisateur peut recevoir des données de cette URLConnection. Le comportement par défaut d'une URLConnexion est de pouvoir recevoir les données.

void setDoOutput(boolean validation);

Si validation vaut true, l'utilisateur peut envoyer des données sur cette URLConnection. Dans ce cas de figure, cela correspond à l'utilisation de la méthode POST pour le serveur HTTP.
void setUseCaches(boolean validation); Si validation vaut true, le système demande au navigateur de mettre les données de l'URL en mémoire temporaire. Dans le cas contraire, l'URL demandée ne fera jamais parti de l'historique du navigateur.
String getContentType( ); Renvoie le type MIME du contenu, comme text/plain, text/html, image/gif, application/x-java-serialized-object, etc.
InputStream getInputStream(); Récupère le flot de données à lire depuis le serveur Web. C'est par l'intermédiaire de ce flux que nous récupérons la réponse.
OutputStream getOutputStream(); Récupère le flot de données à envoyer vers le serveur Web. C'est au travers de ce flux que nous envoyons les différents paramètres prévus pour établir notre requête. Cela correspond à l'Utilisation de la méthode POST du protocole HTTP à condition que la méthode setDoOutput ait été validée.

Nous pouvons obtenir un objet de type URLConnection à partir de la méthode openConnection() de la classe URL. A partir de là, il faut tout de suite indiquer que nous allons envoyer une information en sortie au travers de la méthode setDoOutput(). Cette information correspond au paramètre de la requête. Il faut donc mettre en oeuvre un flux qui permettra effectivement d'envoyer le paramètre.

La gestion des flux ne se fait plus par la classe URL. C'est la classe URLConnection qui maintenant s'occupe de tout. A l'aide de cette classe URLConnection, et au travers de ses méthodes respectives, getOutputStream() et getInputStream() nous pouvons construire tous les types de flux que nous désirons.

Il est à noter que nous pouvons choisir n'importe quel type d'information à la fois en entrée et en sortie. Nous pouvons effectivement travailler avec du texte, mais rien n'empêche d'utiliser directement des objets comme moyen d'échange. Puisque nous utilisons la méthode POST du protocole HTTP et grâce à cette classe URLConnection, nous avons un peu plus de souplesse, surtout en ce qui concerne la requête.

Lorsque nous consultons le code et si nous enlevons la partie rouge, nous obtenons le même type d'écriture que pour les sockets. C'est juste le type de serveur qui change.

ServletInversion

Attention : pensez bien à prendre la méthode doPost de la servlet pour qu'elle soit bien en correspondance avec la méthode POST du protocole HTTP.
.

Nous retrouvons pratiquement le même codage que la servlet précédente. La seule différence vient de l'acquisition du paramètre de la requête. Cette fois-ci, le paramètre ne se trouve plus à la suite de l'URL mais dans l'en-tête de la requête. Toutefois, ce n'est guère plus compliqué. Il suffit juste d'ouvrir un flux correspondant au type de paramètre, ici de type BufferedReader, toujours par l'intermédiaire de l'objet request.

Conclusion : Le codage de la méthode POST nous donne quelques lignes de codes supplémentaires (et encore, tout dépend du nombre de paramètres à passer - problème lié à la classe URLEncoder). Toutefois, nous obtenons plus de souplesse au niveau de la requête. Par ailleurs, nous pouvons faire des réglages plus précis à l'aide de la classe URLConnection. D'ailleurs, cette dernière peut parfaitement être utilisée avec la méthode GET.

 

Choix du chapitre Communication Applet-Servlet, le résultat du traitement est un objet

Nous reprenons le même sujet. La requête est toujours le même texte à envoyer, alors que la réponse est cette fois-ci un objet. Cet objet n'est absolument pas nécessaire. C'est juste pour établir le principe de communication avec des objets.

Pour la requête, nous avons le choix entre la méthode GET et la méthode POST du protocole HTTP. Pour ce chapitre, je vais utiliser la méthode GET. Si nous avions à transférer également un objet depuis l'applet, la question ne se poserait pas. Vu que la requête est constituée d'autre chose que du texte, nous serions obligés de prendre la méthode POST.

Pour ce chapitre également, je ne vais analyser uniquement que les codes sources. Toute la partie projet ainsi que l'application Web ne seront pas expliqués. Je vous invite juste à prendre comme nom InversionGetObjet, à la fois pour le projet ainsi que pour l'application Web.

La classe Chaine

Je commence tout de suite par l'objet qui sert d'échange (réponse à la requête) entre la servlet et l'applet. Il s'agit de la classe Chaine qui conserve le texte à traiter à la fois dans le sens normal, ainsi qu'avec l'inversion des lettres. D'ailleurs, dès que nous construisons l'objet, l'inversion est proposée automatiquement. Nous pouvons également proposer ultérieurement un nouveau texte qui sera lui aussi automatiquement inversé.

Souvenez-vous que dès que vous devez propager un objet sur le réseau, vous devez le rendre sérialisable. C'est d'ailleurs, la seule précaution à prendre.
.

AppletInversion

Nous connaissons tous les ingrédiants. Pour la réponse, au lieu de prendre un objet flux de type BufferedReader, il suffit de prendre à la place un objet flux de type ObjectInputStream. Par contre, le fait de prendre ce flux impose de gérer l'exception ClassNotFoundException qui va avec.

ServletInversion

Le codage de la servlet est encore plus court puisque tout le traitement relatif à l'inversion se trouve dans l'objet de type Chaîne.

  1. Nous récupérons d'abord le paramètre issu de la requête.
  2. Nous fabriquons l'objet Chaine à partir de ce paramètre
  3. et nous renvoyons cet objet vers l'applet.

Communiquer par objet est un grand atout de Java. La mise en oeuvre est vraiment simplicime. N'hésitez pas à vous en servir. Ce serait dommage de ne pas en profiter. Pour envoyer un objet depuis l'applet, il suffit de prendre un flux de type ObjectOutputStream (et d'utiliser la méthode POST du protocole HTTP).

 

Choix des chapitres Architecture trois-tiers

Nous avons déjà travaillé avec des sockets, et la question qui peut se poser est de se demander s'il est possible depuis Internet d'accéder à un service quelconque sur un ordinateur autre que le serveur du réseau local (sous-entendu, un service autre que le service Web). Malheureusement et aussi heureusement, le pare-feu empêche la communication directe. Il est bien sûr indispensable de se protéger de l'extérieur et c'est la première des priorités.

Pour en savoir plus sur les sockets

Il existe pourtant une solution. Lorsqu'un client distant veut accéder à un service situé sur un ordinateur quelconque de notre réseau local, et si bien sûr l'administrateur du réseau est d'accord, nous pouvons passer par le tube HTTP classique, et ainsi faire appel au serveur Web (le pare-feu autorise l'utilisation du port 80 ou 8080). Cela signifie que nous passons par l'intermédiaire d'une servlet. Celle-ci, pour ce cas de figure, joue le rôle d'interface et propose alors une communication par socket pour se connecter au service proposé 1234 sur l'autre ordinateur présent sur le réseau local. De ce fait, indirectement, nous contournons le pare-feu.

 

Choix du chapitre Communication Applet - Servlet - Socket

Pour mettre en oeuvre ce genre de procédé, il est possible pour l'ordinateur client de lancer une application ou d'utiliser une page Web contenant une applet. Nous allons étudier la deuxième approche. Notre projet consistera à réaliser exactement la même chose que précédemment, toutefois le service d'inversion de chaîne de caractères ServiceInversion se trouve sur un autre ordinateur que le serveur Web Tomcat et le numéro de port de ce service sera le numéro 1234. Je suis conscient que ce programme ne sert à rien, mais j'utilise toujours la même démarche qui consiste à prendre des exemples les plus simples possibles afin de maîtriser rapidement le concept.

Construction du projet

Normalement, nous avons deux ordinateurs en jeu. D'une part, le serveur d'inversion de message, d'autre part, le serveur Web. Il faudrait donc deux projets, un pour chaque ordinateur. Pour simplifier, le service 1234 sera en fait placé sur le même ordinateur que le service Web. De toute façon, le principe est identique. Par ailleurs, cela me permet d'utiliser un seul projet.

Encore une fois, nous allons uniquement consulter les codes respectifs sans faire référence à toute la mise en place du projet de l'application Web et de l'application concernant le service d'inversion de message. Nommez juste votre projet et votre application Web ServletSocket.

Classe Transmission

L'échange entre l'applet et la servlet ne se fait qu'au travers d'un objet sérialisé de type Transmission. Lorsque nous allons cliquer sur le bouton "Envoyer", nous allons effectivement envoyer à la servlet un objet Transmission qui représente le texte se trouvant dans la zone de saisie avec en plus le numéro du service à solliciter qui réalisera effectivement le traitement d'inversion.

Codage de l'applet pour entrer en communication avec la servlet

Dans la méthode qui correspond à l'action du clic sur le bouton "Envoyer", nous proposons la connexion avec la servlet à la suite de quoi, nous envoyons et réceptionons un objet de type Transmission. Puisque nous communiquons uniquement qu'au travers d'un objet sérialisé, nous sommes obligés d'utiliser la méthode POST du protocole HTTP. Si tout c'est bien passé au niveau de la servlet, le message renvoyé est visualisé sur la partie principale de l'applet, sinon la zone de saisie comporte l'erreur du disfonctionnement.

Construction de la servlet ServletSocket

 

Attention : Sélectionnez bien la méthode doPost, puisque c'est la méthode post qui a été choisie dans l'applet.
.

Dès que la servlet reçoit la requête sous forme d'un objet de type Transmission issue de l'applet, elle tente de se connecter au serveur du réseau local identifié par le numéro du service proposé par l'applet au travers de cet objet Transmission, et envoie juste le texte à traiter. La servlet attend ensuite la réponse du serveur qui doit lui renvoyer le résultat également sous forme de texte, ce dernier devant être inversé. Une fois que la réponse est obtenue, la servlet se propose de propager ce résultat en direction de l'applet mais en le remettant en forme, c'est-à-dire en le recomposant au travers d'un objet de type Transmission.

Au passage, si la connexion n'a pas pu s'établir avec le service ServiceInversion, un objet de type Transmission est tout de même envoyé vers l'applet. Cet objet est configuré pour indiquer qu'une erreur s'est produite avec le message correspondant au type d'erreur.

Construction du service ServiceInversion "Inversion de texte"

Il nous reste plus qu'à mettre en oeuvre le service ServiceInversion qui permettra de récupérer un texte sur le réseau afin de proposer son inversion avec un renvoi immédiat vers l'expéditeur.

Il faut bien comprendre que c'est un service, ce qui signifie que c'est un programme classique qui fonctionnera constamment en tâche de fond. Il faut donc penser à générer la méthode principale.

Il faut prévoir une configuration d'exécution pour lancer uniquement ce service, indépendamment de l'application Web représentée à la fois par : l'applet, la page Web et la servlet.

Il faut d'abord mettre en place le service représenté par son numéro de port 1234, et attendre qu'un client se connecte. Dans notre configuration, c'est la servlet qui devient client. Lorsqu'effectivement une requête est envoyée depuis la servlet, le service récupère le message, fait le traitement demandé, c'est-à-dire propose l'inversion du texte. Dès que ce traitement est réalisé, ce nouveau texte est renvoyé à la servlet en réponse à sa requête. Pendant toute cette opération, la connexion est restée active. C'est d'ailleurs le serveur qui propose de la rompre en arrêtant directement le service associé. Ceci dit, le service est de nouveau relancé pour attendre une nouvelle requête éventuelle et ceci indéfiniment.

Il est possible de lancer le service ServiceInversion une seule fois, c'est à dire de placer la ligne de code relative à la création du service en dehors de la boucle while. A ce moment là, on demande tout simplement une nouvelle connexion à chaque nouvelle requête issue de la servlet, en pensant à clore en fin de boucle la dernière établie lorsque la réponse a finie d'être envoyée.

Analyse de l'ensemble de la communication à la fois sur Internet et sur le réseau local

Encore une fois, la durée de vie de la servlet est très courte. Elle est créée uniquement au moment où l'utilisateur clique sur le bouton "Envoyer". La servlet reçoit l'objet Transmission de l'applet, tente une connexion par socket avec le service 1234. Lorsque la connexion est établie, elle envoie le texte à traiter au service et attend le résultat de ce dernier. Lorsque effectivement le résultat est renvoyé, la servlet fabrique un nouvel objet Transmission et le renvoie vers l'applet. La servlet ayant réalisée son travail, elle meurt d'elle même. En fait, l'ensemble de ce scénario prend très peu de temps.

Dans le schéma ci-dessus, je présente une architecture avec trois ordinateurs. Dans notre code par contre, puisque nous disposons d'un seul projet, il n'existe que deux ordinateurs, le client et le serveur Web avec deux services utilisés, savoir : le service Web Tomcat avec le port 8080, et le service ServeurInversion avec le port 1234. Pour retrouver l'architecture trois tiers, il faut alors construire deux projets : un dans le serveur Web, et un autre dans le serveur InversionMessage qui comportera uniquement la classe ServiceInversion. Ensuite, au sein de la servlet, il faut ouvrir une socket vers InversionMessage au lieu de localhost, comme suit :

Socket connexion = new Socket("InversionMessage", numéroPort);

 

Choix du chapitre Communication entre une application classique et une servlet

Jusqu'à présent, nous avons systématiquement utilisé un navigateur pour réaliser nos traitements. La communication avec le serveur Web se faisait par l'intermédiaire de l'applet qui jouait le rôle d'interface graphique. Le traitement au niveau du serveur Web était alors effectué par une servlet adaptée.

Il est tout à fait possible d'utiliser directement une application fenêtrée classique à la place du navigateur. La communication avec la servlet se fait exactement de la même façon, c'est-à-dire, en utilisant le protocole HTTP. Il suffit tout simplement, comme pour l'applet, d'utiliser les classes qui encapsulent ce protocole, savoir : URL, URLConnection, URLEncoder.

Il existe, tout de même, une petite différence entre les deux techniques. Puisque l'application fenêtrée n'est pas intégrée dans l'application Web, vous devez donner l'adresse absolue du site Web pour atteindre la servlet et non plus relativement comme c'était le cas avec l'applet.

Nous allons reprendre le même exercice que le premier que nous avons réalisé, c'est-à-dire en établissant un dialogue que sous forme de texte et en utilisant la méthode GET du protocole HTTP. Pour ce chapitre, seule l'applet (avec sa page Web) est remplacée par l'application équivalente.

Il faudra mettre en place un point d'exécution pour l'application classique indépendamment de la mise en oeuvre de l'application Web constituée de la servlet ServletInversion.

La servlet ServletInversion

En fait, cette servlet est rigoureusement identique au premier chapitre puisque cette dernière répond, tout simplement, à une requête du protocole HTTP par la méthode GET sans se préoccuper de savoir qui en fait la demande. Cela fonctionne donc aussi bien pour une applet que pour une application fenêtrée. Le tout c'est que le protocole HTTP soit respecté. Pour souvenir, voici le code (sauf pour le paquetage) :

L'application fenêtrée Application

 

Application.java
package applicationservlet;

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;

public class Application extends JFrame implements ActionListener {
  private JLabel message = new JLabel("Bienvenue !");
  private JTextField saisie = new JTextField("Bienvenue !");
  private JButton envoyer = new JButton("Envoyer");
  private JPanel panneau = new JPanel();

  public void actionPerformed(ActionEvent e) {
    try {
      String adresse = "http://localhost:8080/ApplicationServlet/"; // adresse absolue
      String codageValeur = URLEncoder.encode(saisie.getText(), "ISO-8859-1");
      URL url = new URL(adresse+"ServletInversion?message=" + codageValeur);
      BufferedReader réponse = new BufferedReader (new InputStreamReader(url.openStream()));
      message.setText(réponse.readLine());
    }
    catch (IOException erreur) { message.setText("Erreur de communication"); }
  } 
  public Application() {
    message.setForeground(Color.RED);
    message.setHorizontalAlignment(message.CENTER);
    message.setFont(new java.awt.Font("Dialog", 3, 24));
    saisie.setColumns(15);
    envoyer.addActionListener(this);
    panneau.setBackground(Color.BLUE);
    panneau.add(saisie);
    panneau.add(envoyer);
    this.setTitle("Communication application-servlet");
    this.setBounds(100, 100, 320, 200);
    this.getContentPane().setBackground(Color.ORANGE);
    this.getContentPane().add(message, BorderLayout.CENTER);
    this.getContentPane().add(panneau, BorderLayout.SOUTH);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }
  public static void main(String[] args) {
    new Application().show();
  }
}
Application.java

Dans la partie traitement de l'événement associé à l'action sur le bouton "Envoyer" représenté par la méthode actionPerformed, nous retrouvons le code que nous avions déjà implémenté dans l'applet. Seule la première ligne a été rajouté, pour préciser l'adresse absolue du service Web afin de localiser correctement la servlet qui va effectivement rendre ce service.

A vous de choisir l'IHM que vous désirez, soit l'applet en utilisant donc un navigateur, soit une application fenêtrée. L'avantage de la première solution, c'est que l'ensemble de la structure forme un tout qui s'appelle justement application Web. Ensuite à l'aide du navigateur, vous pouvez passer d'une application Web à une autre en "navigant".