Java EE : TP 02.03 et 04.03

Exercice 0.

Deux de vos exercices de la semaine dernière (pour certains, plus...) n'ont pas été terminés. Je vous prie de vous en occuper. Ne travaillez pas sur le suivant, mais lisez le sujet et commencez à assimiler l'idée, planifier la stratégie, etc.
J'ai changée d'idée de devoir, à l'origine basée sur un service Web géographique, avec une passerelle Java ↔ Python. Des dispositifs nécessaires dépendent des versions de Python et des plates-formes, et avec toutes ces variantes pas si faciles à installer et configurer, on aurait des problèmes en permanence... La version courante est plus simple.

ATTENTION ! Le texte ci-dessus n'est pas forcément fini et complet. Si vous me posez des questions pertinentes en général, je pourrai enrichir l'énoncé par d'autres informations, consignes, références, exemples, etc. Cela ne signifie pas que vous devez attendre ces informations !


Exercice 1.   Votre dernier devoir obligatoire

Une application de visualisation (graphique scientifique) à l'aide de Python/Matplotlib.

1. Le sujet.

L'idée générale est :

Quelques détails

A.

Je ne discuterai Matplotlib, 20 minutes de lecture doit suffire si vous avez oublié la commande plot(...). Ce qui peut vous intéresser est la fonction eval("expression_texte") qui évalue une expression Python dans l'environnement global, par ex. x=8; eval("x*3") retourne 24.
Aussi, exec(" commandes ") exécute des commandes Python, par ex. exec("y=9+x") ne retourne rien, mais y devient égal à 17.

B.

Les seuls éléments qui peuvent vous causer des ennuis, sont :


Les deux derniers points demandent une réflexion car les données transmises sont binaires. En principe ceci n'est pas nécesssaire, dans le contexte de ce devoir, il est facile de créer par Matplotlib une image en format SVG, qui est textuel ; le Service n'a rien d'autre à faire que d'emballer le SVG fait par Python, et le passer au client tel quel dans la page-réponse. Mais je demande explicitement le transfert des images binaires, PNG, éventuellement JPG. C'est pour votre entraînement, donc je n'accepterai pas les SVG... Rappelez-vous de codage Base64. Apache Commons is your friend. Vous trouverez ici des codecs, par ex. dans Codec : Base64, qui sert à transmettre les images codées en chaînes via Web, dans Exec : des utilitaires pour exécuter les processus extérieurs, etc.

Python vous permet de sauvegarder les images (savefig de Matplotlib) non pas comme des fichiers sur le disque, mais comme des "fichiers virtuels", des flots StringIO et BytesIO. Lisez la doc.

Je vous donne donc quelques consignes-exemples, mais SVP, travaillez vous-mêmes les détails.

C.

Voici un programme Python (pyprog.py) communiquant. Il affiche une image, et un texte sur un terminal.

import sys
cc=input()
print("Hello "+cc) # Cela affichera "Hello votre excellence."
sys.stdout.flush()
from pylab import *
x=linspace(0,20,300); y=sin(2*x)/(1+x)
plot(x,y); show()
La variable cc n'est pas affectée par l'utilisateur, mais transmise par un programme Java. Le programme ci-dessus est lancé par le suivant :
package extpro;
import java.io.*;
public class Extpro {
   public static void main(String[] args) throws Exception {
        Process proc = Runtime.getRuntime().exec("Python /.../pyprog.py");
        InputStream ips = proc.getInputStream();
        OutputStream ops = proc.getOutputStream();
        String output = "votre excellence.";
        PrintStream ps = new PrintStream(ops);
        ps.print(output); ps.close();
        
        String line;
        BufferedReader bri = new BufferedReader
           (new InputStreamReader(proc.getInputStream()));
        while ((line = bri.readLine()) != null) {
            System.out.println("** "+line); }
        bri.close();
        System.out.flush();
   } }
Vous (les peu nombreux présents) avez vu le lancement du notepad en cours. C'est le même principe.

D.

Votre serveur Java et votre programme Python marchent sur la même machine, ce qui facilite la communication, mais on peut facilement établir la communication un peu plus distribuée. Pourquoi ne pas exploiter les sockets? Vous m'avez dit explicitement que l'on vous les a enseignés. Profitez-en. Voici, à titre d'exemple, deux programmes Python qui communiquent via sockets.

import socket as so
port=44445
sk = so.socket(so.AF_INET, so.SOCK_STREAM)
sk.connect(("localhost", port))
sk.sendall(b"Belle marquise")
sk.close()
import socket as so
port=44445
sk = so.socket(so.AF_INET, so.SOCK_STREAM)
sk.bind(("", port)); sk.listen(1)
conn, addr = sk.accept()
data = conn.recv(1024)
print(data.decode())
sk.close()

N'oubliez pas qu'il faut d'abord lancer le serveur, ce programme qui se met à l'écoute. Avec les sockets Java, débrouillez-vous, une vingtaine de minutes suffira. La communication sera bi-directionnelle, assez symétrique, et les rôles "serveur" et "client" seront conventionnels. Si le "lecteur" Python agit comme serveur, et ajoute à la fin :

conn.sendall(bytes("Vous désirez, Monsieur?","utf-8"))
conn.close()
alors le programme Java qui écrit quelque chose et qui reçoit la réponse, peut avoir la forme suivante :
package tsock;
import java.io.*;
import java.net.Socket;

public class TSock {
  public static void main(String[] args) throws Exception {
   Socket sk = new Socket("localhost", 44445);
   PrintWriter out =
      new PrintWriter(sk.getOutputStream(), true);
   BufferedReader in = new BufferedReader(
      new InputStreamReader(sk.getInputStream()));
   out.println("To beep or not to beep...");
   String inputLine = in.readLine();
   System.out.println(inputLine); // La réponse du "serveur"
  }   
}

La déclaration "throws Exception" est une solution assez négligeante du problème d'échec du programme main. Un professionnel aurait protégé les détails avec "try", et ajouté des diagnostics spécifiques. Mais je voulais être simpliste. Le reste est à vous. Si vous posez des questions, je pourrai répondre, si je constate que la fouille de la documentation standard pose des problèmes. Si vous ne posez pas des questions...

Quelques modalités

Vous travaillerez individuellement, pas de binômes.

Répétons : pour la réalisation d'un programme Web qui récupère les commandes et envoie un graphe scientifique, on n'a pas besoin d'un service Web. On peut le faire avec de très simples JSP, ou sans Java du tout. Ces "pseudo-solutions" seront rejetées sommairement, vous devez faire un Service Web, et lancer la "moulinette" Python. Vous avez le droit d'utiliser JSP, bien sûr et aussi JSTL, beans, et toute autre chose. La qualité de la solution compte. L'originalité compte. Un bon design de l'interface (client) compte. Une bonne documentation compte (un mini-rapport est plus qu'envisageable), et les sources doivent contenir un minimum de documentation. (Devoir rendu sans sources ne vaut strictement rien).

Une réaction raisonnable aux erreurs de la part du client s'impose. Le programme qui "bombe" sans dire pourquoi, sera considéré comme presque inacceptable (une note faible, même si tout le reste fonctionne). L'utilisateur pourra essayer de tracer "2*xsin(2+))" ou une autre abomination, et votre programme n'a pas le droit de rendre l'âme à cause de mauvaises données.

La date-butoir sera établie un peu plus tard, vraisemblablement il faudra rendre le devoir en fin de la session d'examens. Ceci dit : vous savez que j'essaie avec ma meilleure volonté de répondre à toutes vos questions et de vous aider dans le débogage de vos programmes. Mais trop, c'est trop. Hier, le 29.02.2016, une journée après la date butoir de votre dernier exercice, un de vous s'est réveillé, et il m'a dit qu'il n'arrivait pas à trouver sur le disque sa propre base de données Derby (qui n'est rien d'autre qu'un répertoire portant le nom de la BD). On a réglé cela à l'amiable, mais je ne peux continuer comme ça. Si je constate que certains ont gaspillé le mois de mars, et en avril ils me poseront des questions suggérant qu'ils n'ont rien fait, il leur faudra chercher un autre dépanneur.



Solutions (peut-être).

Retour
Semaine suivante