IFT-21133
Programmation en Java.
Énoncé du TP3
Objectifs:
- Manipuler des classes abstraites et concrètes.
- Comprendre les mécanismes fondamentaux de l'héritage tels que le remplacement
de méthodes.
- Définir une hiérarchie de classes héritant d'une classe abstraite.
- Utiliser l'API JDBC pour se connecter à une base de données distante.
- Apprendre à jouer des sons.
- Utiliser les threads.
- Utiliser l'API java.io pour créer un client de socket.
Note importante :
Vous devez absolument télécharger la présente version du TP.
Si vous mélangez vos classes du TP2 avec celle-ci , le TP3 ne marchera pas.
Vous devez donc archiver votre TP2 et le ranger dans un coin de votre ordinateur,
sans oulier de détruire les classes.
Le TP3 n'est pas très long mais possède certains aspects techniques.
M Patate
Généralités:
Ce troisième travaille consiste à améliorer notre M Patate. Nous allons lui permettre d'aller chercher des accessoires sur Internet.
Il ira chercher les noms des accessoires sur un serveur de base de données et ira chercher les accessoires correspondant à ces noms
auprès de 2 serveurs de sockets. Ensuite nous ajouterons des accessoires sonores et animés pour ajouter une petite touche de mouvement
à l'ensemble.
Rappel : Un M Patate est un jeu qui consiste à poser des accessoires sur
le dessin d'une pomme de terre. Les accessoires ressemblent à des yeux, des bouches, des oreilles, etc. A la fin, votre patate
ressemble à un M Patate.
Dans la première version du TP, M Patate chargeait localement les accesoires et les fonds (il fallait que les fonds et les accessoires soient sur la machine de l'application). Dans cette version, nous allons aller chercher ces données sur Internet de deux manières différentes.
Premièrement, un serveur de base de données va nous donner la liste des fonds et des accessoires disponibles.
(Les méthodes getFondsListe et getAccessoiresListe devront donc se connecter à une base de données).
Deuxièmement, une fois que nous aurons la liste des noms d'accessoires disponibles,
nous demanderons les objets java portant ce nom à des serveurs de sockets.
(N.B. Un serveur de sockets est un serveur par lequel on communique à l'aide de sockets).
Il y a deux types d'objets que nous récupérerons sur le réseau : les fonds et les accessoires.
Pour ce TP, vous aurez impérativement besoin des classes de driver JDBC d'Oracle.
(Vous n'avez pas besoin de dézipper les classes d'Oracle, en aucun cas. Tout ce que vous devez faire est de les mettre dans le même
répertoire que celui qui contient votre version démo).
Pour vous aider à réaliser le travail, vous diposez d'une ébauche du TP (version linux)
(version windows) ainsi que de la javadoc de la solution
Vous pouvez télécharger une version fonctionnelle de M Patate.
Pour lancer le programme, tapez "java -jar patato-demo.jar ift-linux1.ift.ulaval.ca".
(le chargement est long, si vous avez une connexion lente à Internet, reportez vous à la FAQ du TP ).
Comme le TP nécessite l'utilisation du réseau, nous avons pensé que certainEs d'entre vous pourraient etre pénaliséEs par
la lenteur de leur connexion réseau. Pour cette raison, nous mettons également à votre disposition le serveur de sockets du TP. Vous trouverez dans la FAQ du TP, comment utiliser ces programmes.
Argument de ligne de commande
Le TP nécessite désormais un argument de ligne de commande pour pouvoir fonctionner correctement.
Cet argument spécifie le nom de l'hôte du serveur de sockets que vous désirez utiliser pour récupérer les fonds et les accessoires.
Par exemple, si vous utilisez le serveur de sockets situé à l'université, la ligne de commande sera :
- pour lancer la démo: "java -jar patato-demo.jar ift-linux1.ift.ulaval.ca".
- pour lancer votre TP: "java patato.Main ift-linux1.ift.ulaval.ca".
Si, au contraire, vous avez installé le serveur de socket sur votre machine (cf FAQ), la ligne de commande sera :
- pour lancer la démo: "java -jar patato-demo.jar localhost".
- pour lancer votre TP: "java patato.Main localhost".
(localhost signifie "ma machine", sur certains psuedo-systèmes d'exploitation, le mot localhost ne marchera pas, dans ce cas, utilisez votre adresse IP).
Sans argument sur la ligne de commande, vous obtiendrez une erreur!
Architecture du TP
Le TP est composé de trois packages (presque 4). Chacun de ses packages regroupe des classes proches par leurs fonctionnalités.
Explication des packages :
- le package patato.ui regroupe les classes d'interfaces graphiques (celles qui font qqchose à l'écran).
Ces classes sont principalement la classe MainFrame et Screen. MainFrame est la classe qui va contenir l'interface personne-machine de votre TP,
les boutons et autres composants graphiques, c'est la fenêtre principale de votre application. Screen est une classe très particulière, c'est l'écran du jeu de M Patate. Elle représente un composant graphique spécialisé dans l'affichage des M Patates (A titre d'exemple de ce qu'est un composant graphique, dîtes-vous qu'un bouton est un composant graphique spécialisé dans l'affichage d'un zone clickable avec un texte dessus).
- le package patato.engine regroupe les classes dîtes d'accès aux données. Pour réaliser notre M Patate, nous aurons besoin d'images et de sons, qui représenteront M Patate, ces accessoires, etc. Les classes du package engine permettent de lire ces données, de créer nos accessoires.
C'est essentiellement dans ce package que nous allons travaillé dans le TP3.
- le package patato.data regroupe les classes qui vont représenter nos données, elles vont fournir une représentation java des accessoires, etc.
Le package propose une hiérarchie de classes pour les accessoires, celle-ci possède une classe mère (abstraite) : patato.data.Accessoire.
De cette classe dérivent plusieurs classes concrètes :ImageAccessoire (une classe qui affiche des accessoires à partir d'images),
DessinAccessoire (qui représente des accessoires simples, dessinés à l'aide des fonctions graphiques de java).
- Le "presque package" patato, qui ne contient que la classe patato.Main, classe qui lancera l'application.
Votre TP devra pouvoir être lancé à partir de cette classe.
Sur le schéma, vous pourrez voir les relations entre ces différentes classes.
Dans le TP3, nous allons travailler sur 3 fichiers : AccessoireCreatorJDBCSocket.java, AnimatedAccessoire.java, SoundAccessoire.java.
Dans l'état actuel, le TP3 ne fonctionne pas mais compile parfaitement.
Informations concernant la base de données et les connexions réseau.
Pour ce TP, vous aurez besoin de vous connecter à une base de données située sur l'un des ordinateurs de l'université,
voici quelques informations qui vous permettront de vous y connecter :
- La base de données est accessible via l'URL "jdbc:oracle:thin:@vega.ift.ulaval.ca:1521:sbd".
- La driver oracle nécessaire pour se connecter à la base est représenté par la classe : "oracle.jdbc.driver.OracleDriver".
- Le nom d'utilisateur pour ce TP est "java", le mot de passe est "java".
- La base de données possède deux tables : "Fond" et "Accessoire"
,
ces deux tables ne comprennent qu'une seule colonne, de type String et de nom "NOM".
Ce sont ces deux tables qui contiennent respectivement le nom des fonds (backgroundIcon) et Accessoires disponibles.
De plus, vous devrez vous connecter à 2 serveurs de sockets. Ces 2 serveurs ne sont pas interchangeables, l'un d'entre eux
vous permettra de récupérer des fonds d'écran et l'autre des accessoires .
Les 2 serveurs sont programmés pour répondre à un meme protocole : il faut leur envoyer le nom de l'objet désiré (suivi d'un retour chariot = '\n' )
et ils émettront en retour l'objet désiré. L'envoi de texte peut se faire avec un PrintStream, la lecture des objets doit se faire avec un ObjectInputStream.
- Le serveur de fonds d'écran est situé sur l'hôte ift-linux1.ift.ulaval.ca, au port 5500.
- Le serveur d'accessoires est situé sur l'hôte ift-linux1.ift.ulaval.ca, au port 5501.
Notez que le serveur redémarre automatiquement toutes les heures paires( minuit, 2h, 4h,...).
Notez également qu'une socket ne peut être ouverte que pour une durée de 15 minutes, après quoi la
socket est éliminée afin de ne pas surcharger le serveur.
Ce que vous devez faire
Vous devrez commentez votre code de deux manières : des commentaires "normaux" à l'intérieur des méthodes pour expliquer ce que vous faîtes,
ainsi que des commentaires javadoc (annexe G du livre de Deitel & Deitel).
L'ébauche du TP compile dans l'état actuel. Le TP a été conçu pour vous permettre d'atteindre trois buts, ces trois buts sont indépendants,
vous les réaliser dans l'ordre que vous voulez.
- Compléter la classe patato.engine.AccessoireJDBCSocket.
- Ajouter des accessoires sonores et animés à M Patate.
- Répondre aux questions.
- Dans la classe patato.engine.AccessoireJDBCSocket, vous devez :
- Modifier le constructeur de la classe :
le constructeur devra obtenir une connexion à la base de données et un Statement depuis la connexion.
(i.e. Construisiez un objet connexion et un objet statement à partir de cette connexion.)
Les objets Connection et Statement obtenus seront respectivement affectés aux données membres connect et statement de la classe.
- Modifier la méthode
public String[] getFondsListe()
de telle sorte que cette classe se connecte à la base de données,
et récupère les enregistrements de la table "Fond". Cette table ne possède qu'une seule colonne de type String.
Une fois les enregistrements lus dans la table, la méthode les retournera sous la forme d'un String[].
- Modifier la méthode
public ImageIcon getFond( String name )
afin qu'elle renvoie l'ImageIcon associé au nom passé en paramètre.
Cette méthode devra
- établir une connexion (socket) avec l'un des 3 serveurs de socket du TP.( le serveur de fonds)
- lui envoyer le string passé en paramètre SUIVI D'UN RETOUR CHARIOT (\n).
( par exemple, à l'aide d'un PrintStream ou encore d'un PrintWriter).
- lire l'objet qui sera envoyé par le serveur à l'aide d'un objectInputStream.
- fermer la socket.
- renvoyer l'objet lu en tant qu'objet de la classe ImageIcon.
- Modifier la méthode
public String[] getAccessoiresListe()
de telle sorte que cette classe se connecte à la base de données,
et récupère les enregistrements de la table "Accessoire". Cette table ne possède qu'une seule colonne de type String.
Une fois les enregistrements lus dans la table, la méthode les retournera sous la forme d'un String[].
Comme vous pouvez le voir, il existe déjà quelques instructions dans cette méthode,
tout ce que vous avez à faire est de placer les String que vous lisez depuis la base de données dans l'objet
vector "temp" qui existe déjà dans la méthode.
Ne décommentez pas les deux instructions commentées tout de suite, nous verrons cela plus tard.
- Modifier la méthode
public Accessoire createAccessoire( String name )
afin qu'elle renvoie l'Accessoire associé au nom passé en paramètre.
Comme vous pouvez le voir, il existe déjà quelques instructions dans cette méthode,
tout ce que vous devez faire est de remplir la méthode après le commentaire : "à modifier" de telle sorte
que vous affecterez à la variable locale "result" l'objet que vous aurez lu sur le réseau.
Ne décommentez pas les deux instructions commentées tout de suite, nous verrons cela plus tard.
Cette méthode devra
- établir une connexion (socket) avec l'un des 3 serveurs de socket du TP.( le serveur d'accessoires)
- lui envoyer le string passé en paramètre SUIVI D'UN RETOUR CHARIOT (\n). ( par exemple, à l'aide d'un PrintStream ).
- lire l'objet qui sera envoyé par le serveur à l'aide d'un objectOutputStream.
- fermer la socket.
- renvoyer l'objet lu en tant qu'objet de la classe Accessoire.
- Ecrire les classes patato.data.AnimatedAccessoire et patato.data.SoundAccessoire .
Ces deux classes sont des nouvelles classes filles de patato.data.Accessoire.
Complétez d'abord les deux classes, nous verrons ensuite de quelle manière les intégrer au TP.
- La classe patato.data.AnimatedAccessoire représente des Accessoires animés. Le principe de l'animation est simple :
au lieu d'afficher toujours la meme image à l'écran pour représenter l'accessoire , nous allons, à intervalles réguliers,
changer l'image. La succssion rapide des images donnera l'impression d'un mouvement.
Voici quelques conseils pour la réaliser :
- Elle hérite de patato.data.ImageAccessoire et implémente l'interface Runnable.
- La classe possèdera une donnée membre privée "icons" de type ImageIcon[] ainsi que des méthodes d'accès publiques à cette donnée
membre :
public ImageIcon[] getIcons()
et public void setIcons(ImageIcon[] v)
.
- Elle devra posséder une donnée membre de type int, appelée "count", intialisée à 0.
- Dans la méthode
run
de votre classe, vous écrirez une boucle infinie. Dans cette boucle,
faites dormir le thread courant 100ms puis incérementer count en vous assurant qu'il ne dépasse pas la taille
de la donnée membre "icons", s'il dépasse, on le remet à 0.
- Ensuite, nous allons redéfinir la méthode getIcon de la classe ImageAccessoire,
notre méthode renverra l'icon situé à l'index "count" de notre tableau "icons". De cette manière, lorsque
la méthode paint que nous héritons de la classe ImageAccessoire appelera getIcon , nous lui renverrons une image
différente en fonction du temps.
- En dernier lieu, dans le constructeur de notre classe, nous allons faire démarrer un thread dont le runnable
sera l'instance que nous sommes en train de construire. Ce thread pourra être une donnée membre de la classe.
- La classe patato.data.SoundAccessoire représente des Accessoires sonores. Cette classe n'a pas un grand intérêt
par rapport au cours, elle vous permet simplement d'apprendre à jouer un son en java.
Voici quelques conseils pour la réaliser :
- Elle hérite de patato.data.ImageAccessoire .
- Elle possèdera une donnée membre de type int : "count".
- La classe possèdera une donnée membre privée "clip" de AudioClip ainsi que des méthodes d'accès publiques à cette donnée
membre :
public AudioClip getClip()
et public void setClip(AudioClip v)
.
- Vous devrez ensuite redéfinir la méthode paint héritée de ImageAccessoire.
La nouvelle méthode commencera par un appel à la méthode paint de la classe mère.
Ensuite, vous incrémenterez "count". Si count vaut 30, vous remettrez count à 0 et jouerez le "clip" à l'aide de la méthode
clip.play();
- Pour finir, nous allons activer les nouveaux accessoires dans patato.engine.AccessoireJDBCSocket.
Comme il est impossible de faire passer ces deux nouvelles classes par le réseau, nous
allons les charger localement. Ainsi, certains accessoires seront chargés depuis Internet, d'autres
seront chargés localement.
Pour ce faire, décommenter le code :
- "//temp.add( ACCESSOIRE_PAPILLON1 );" dans "public String[] getAccessoiresListe()"
- "//temp.add( ACCESSOIRE_MONTRE1 );" dans public String[] getAccessoiresListe()
- "/* if( name.equals( ACCESSOIRE_MONTRE1 ) )" jusqu'à "else" dans "public Accessoire createAccessoire( String name )"
- Répondre aux questions :
-
Il existe plusieurs moyens d'empêcher ou de limiter l'instanciation des objets d'une classe par une autre classe.
On peut, par exemple, rendre cette classe abstraite.
En regardant attentivement le code de la classe AccessoireCreator ou de AccessoireCreatorJDBC,
donnez un autre moyen de limiter l'instanciation des objets d'une classe par une autre classe.
-
Pourquoi ScreenMouseHanlder possède t'elle une méthode
public void mouseMoved alors que celle-ci ne fait rien?
-
Pourquoi la classe Accessoire implémente-t-elle
l'interface java.io.Serializable ?
Vous avez fini votre TP.
Ce que vous devez remettre :
- Votre code source. Votre programme doit fonctionner correctement avec le jdk1.3
- Il est inutile d'inclure les classes de vos TP, car ceux-ci sont automatiquement recompilés avant la correction.
- Ce code doit être commenté selon la norme Javadoc (Rappel: le fait d'utiliser javadoc ne signifie pas qu'il ne faut plus commenter le code normalement...) . Vous devez commenter uniquement les classes ou méthodes que vous avez crées, mais vous devrez générer la documentation html de toutes les classes du TP.
-
La documentation Javadoc que vous aurez générée pour tous les packages(les documentations de classes doivent être navigables entre elles).
- un fichier texte (au format txt, i.e. PAS un fichier word ) qui contiendra toutes les indications que vous jugez pertinentes pour le correcteur afin qu'il évalue votre travail de la manière la plus juste possible.
Ce fichier contiendra notamment les informations suivantes : votre nom, votre prénom, votre matricule et la section à laquelle vous appartenez.
De plus, il devra contenir vos réponses aux questions posées.
Il pourra également contenir toutes les améliorations que vous avez apportées au TP, qui reflète un travail réel, que le correcteur devra évaluer.
Vous devez envoyer votre travail compressé dans une archive (respectant la hiérarchie de répertoires de vos fichiers sources)par courriel l' adresse du cours(ift-21133@ift.ulaval.ca).
Elle doit avoir un nom de la forme tp3-nom-prenom-matricule-section(A ou Z) . Le nom de l'archive ne doit contenir aucun caractère accentué, espace ou _ (underscore) .
Exemple : Si Mme Jeanne Tremblay (95423657) de la section A rend son travail, il devra s'appeller : tp3-Tremblay-Jeanne-95423657-sectionA.(zip ou tgz).
Les copies ne respectant pas ce format ne seront pas acceptées ou seront pénalisées.
Dernière mise à jour 23/06/2001