Les sessions constituant déjà un gros morceau à elles seules, dans cette étape du fil rouge vous n'allez pas manipuler de cookies. Et croyez-moi, même sans ça vous avez du pain sur la planche !
Objectifs
Fonctionnalités
Vous allez devoir effectuer une modification importante, qui va impacter presque tout votre code existant : je vous demande dans cette étape d'enregistrer en session les clients et commandes créés par un utilisateur. Cela pourrait très bien être un jeu d'enfants, si je ne vous demandais rien d'autre derrière… Mais ne rêvez pas, vous n'êtes pas ici pour vous tourner les pouces !
Enregistrement en session
Pour commencer, comme je viens de vous l'annoncer, vous allez devoir enregistrer en session les clients et commandes créés par un utilisateur. Ainsi, les informations saisies par l'utilisateur ne seront plus perdues après validation d'un formulaire de création !
Liste récapitulative des clients et commandes créés
Deuxièmement, vous allez devoir créer deux nouvelles pages :
- listerClients.jsp, qui listera les clients créés par l'utilisateur ;
- listerCommandes.jsp, qui listera les commandes créées par l'utilisateur.
Vous les placerez bien entendu sous /WEB-INF tout comme leurs consœurs, Vous en profiterez pour mettre à jour la page menu.jsp en y ajoutant deux liens vers les nouvelles servlets gérant ces deux pages fraîchement créées.
Un formulaire de création de commande intelligent
Troisièmement, et cette fois il va falloir réfléchir davantage, je vous demande de modifier le formulaire de création de commandes. Maintenant que votre application est capable d'enregistrer les clients créés par l'utilisateur, vous allez lui donner un choix lorsqu'il crée une commande :
- si la commande qu'il veut créer concerne un nouveau client, alors affichez-lui les champs permettant la saisie des informations du nouveau client, comme vous le faisiez déjà auparavant ;
- si la commande qu'il veut créer concerne un client déjà existant, alors affichez-lui une liste déroulante des clients existants, lui permettant de choisir son client et lui évitant ainsi de saisir à nouveau ces informations.
Système de suppression des clients et commandes
Quatrièmement, vous allez devoir mettre en place un système permettant la suppression d'un client ou d'une commande enregistrée dans la session. Vous allez ensuite devoir compléter vos pages listerClients.jsp et listerCommandes.jsp pour qu'elles affichent à côté de chaque client et commande un lien vers ce système, permettant la suppression de l'entité correspondante.
Gestion de l'encodage UTF-8 des données
Cinquièmement, vous allez appliquer le filtre d'encodage de Tomcat à votre projet, afin de rendre votre application capable de gérer n'importe quelle donnée UTF-8.
Enfin, vous devrez vous préparer une tasse un thermos de café ou de thé bien fort, parce qu'avec tout ce travail, vous n'êtes pas couchés !
Exemples de rendus
Voici aux figures suivantes quelques exemples de rendu. Liste des clients créés au cours de la session, ici avec quatre clients.
Liste des commandes lorsqu'aucune commande n'a été créée au cours de la session :
Formulaire de création d'une commande lorsque la case "Nouveau client : Oui" est cochée :
Formulaire de création d'une commande lorsque la case "Nouveau client : Non" est cochée :
Liste des commandes lorsque deux commandes ont été créées au cours de la session :
Conseils
Enregistrement en session
Concernant l'aspect technique de cette problématique, vous avez toutes les informations dans le chapitre sur ce sujet : il vous suffit de récupérer la session en cours depuis l'objet requête, et d'y mettre en place des attributs. Concernant la mise en place dans ce cas précis par contre, il y a une question que vous allez devoir vous poser : quel type d'attributs enregistrer en session ? Autrement dit, comment stocker les clients et commandes ? C'est une bonne question. Essayez d'y réfléchir par vous-mêmes avant de lire le conseil qui suit…
Ici, ce qui vous intéresse, c'est d'enregistrer les clients et les commandes créés. Une liste de clients et une liste de commandes pourraient donc a priori faire l'affaire, mais retrouver quelque chose dans une liste, ce n'est pas simple… Pourtant, vous aimeriez bien pouvoir identifier facilement un client ou une commande dans ces listes. Pour cette raison, une Map
semble la solution adaptée. Oui, mais comment organiser cette Map
? Les objets Client et Commande seront bien entendu les valeurs, mais qu'est-ce qui va bien pouvoir servir de clé ? Il y a tout un tas de solutions possibles, mais je vous conseille pour le moment de mettre en place la moins contraignante : considérez que le nom permet d'identifier de manière unique un client, et que la date permet d'identifier de manière unique une commande. Cela implique que votre application ne permettra pas de créer deux commandes au même instant, ni de créer deux clients portant le même nom. Ce n'est pas génial comme comportement, mais pour le moment votre application ne gère toujours pas les données, donc ça ne vous pose absolument aucun problème ! Vous aurez tout le loisir de régler ce petit souci dans l'étape 6 du fil rouge !
Bref, je vous conseille donc de placer en session une Map<String, Client>
contenant les clients identifiés par leur nom, et une Map<String, Commande>
contenant les commandes identifiées par leur date.
Liste récapitulative des clients et commandes créés
Deux pages JSP accédant directement aux attributs stockés en session suffisent ici. Puisque vous allez les placer sous /WEB-INF, elles ne seront pas accessibles directement par leur URL et vous devrez mettre en place des servlets en amont, qui se chargeront de leur retransmettre les requêtes reçues. Vous pouvez par exemple les appeler ListeClients et ListeCommandes, et vous n'oublierez pas de les déclarer dans votre fichier web.xml.
Dans chacune de ces JSP, le plus simple est de générer un tableau HTML qui affichera ligne par ligne les clients ou commandes créés (voir les exemples de rendus). Pour cela, il vous suffit de parcourir les Map
enregistrées en tant qu'attributs de session à l'aide de la balise de boucle JSTL <c:forEach>
. Relisez le passage du cours sur la JSTL si vous avez oublié comment itérer sur une collection, et relisez la correction de l'exercice sur la JSTL Core si vous avez oublié comment atteindre les clés et valeurs d'une Map
depuis une EL ! Dans le corps de cette boucle, vous placerez les balises HTML nécessaires à la création des lignes du tableau HTML, contenant les entrées de la Map
des clients ou des commandes.
En bonus, pour aérer la lecture du tableau final dans le navigateur, vous pouvez utiliser un compteur au sein de votre boucle pour alterner la couleur de fond d'une ligne à l'autre. Cela se fait par exemple en testant simplement si l'indice de parcours de la boucle est pair ou impair.
Second bonus, vous pouvez mettre en place un test vérifiant si les objets présents en sessions existent ou non, via par exemple la balise <c:choose>
: si non, alors vous pouvez par exemple afficher un message signalant qu'aucun client ou aucune commande n'existe (voir les exemples de rendus).
Un formulaire de création de commande intelligent
En ce qui concerne cette modification, vous allez devoir réfléchir un peu à la solution à mettre en place : comment donner un choix à l'utilisateur ? Si vous regardez les exemples de rendus que je vous ai donnés ci-dessus, vous verrez que j'ai mis en place deux simples boutons de type <input type="radio" />
:
- au clic sur "Oui", la première partie du formulaire classique s'affiche ;
- au clic sur "Non", un nouveau champ
<select>
listant les clients existants remplace la première partie du formulaire !
Bien entendu, vous n'êtes pas forcés d'utiliser ce moyen ! Si vous souhaitez que votre apprentissage soit efficace, alors vous devez réfléchir par vous-mêmes à cette petite problématique et lui trouver une solution adaptée sans mon aide. Ce petit exercice de conception donnera du fil à retordre à vos neurones et vous fera prendre encore un peu plus d'aisance avec le Java EE !
En outre, la solution que je propose ici est un peu évoluée, car elle implique un petit morceau de code Javascript pour permettre la modification du formulaire au clic sur un bouton radio. Si vous ne la sentez pas, prenez le temps et pensez à un autre système plus simple et peut-être moins évolué graphiquement qui permettrait à l'utilisateur de choisir entre une liste des clients existants et un formulaire classique comme vous l'affichiez par défaut auparavant. Ne vous découragez pas, testez et réussissez !
Note : une telle modification du formulaire va bien évidemment impliquer une modification de l'objet métier qui y est associé, c'est-à-dire CreationCommandeForm. En effet, puisque vous proposez la réutilisation d'un client existant à l'utilisateur dans le formulaire, vous devrez faire en sorte dans votre objet métier de ne valider les informations clients que si un nouveau client a été créé, et simplement récupérer l'objet Client existant si l'utilisateur choisit un ancien client dans la liste !
Système de suppression des clients et commandes
Pour terminer, il vous suffit ici de créer deux servlets, dédiées chacune à la suppression d'un client et d'une commande de la Map
présente en session. Vous contacterez ces servlets via de simples liens HTML depuis vos pages listerClients.jsp ou listerCommandes.jsp ; il faudra donc y implémenter la méthode doGet()
. Ces liens contiendront alors, soit un nom de client, soit une date de commande en tant que paramètre d'URL, et les servlets se chargeront alors de retirer l'entrée correspondante de la Map
des clients ou des commandes, grâce à la méthode remove()
.
Dans les exemples de rendus ci-dessus, les croix rouges affichées en fin de chaque ligne des tableaux sont des liens vers les servlets de suppression respectives, que vous pouvez par exemple nommer SuppressionClient et SuppressionCommande.
Gestion de l'encodage UTF-8 des données
Rien de particulier à vous conseiller ici, il suffit simplement de recopier la déclaration du filtre de Tomcat dans le web.xml du projet, et le tour est joué !
Correction
Cette fois, la longueur du sujet n'est pas trompeuse : le travail que vous devez fournir est bien important ! Posez-vous calmement les bonnes questions, faites l'analogie avec ce que vous avez appris dans les chapitres de cours et n'oubliez pas les bases que vous avez découvertes auparavant (création d'une servlet, modification du fichier web.xml, utilisation de la JSTL, etc.). Comme toujours, ce n'est pas la seule manière de faire, le principal est que votre solution respecte les consignes que je vous ai données !
Pour que cette correction soit entièrement fonctionnelle, vous devrez inclure la bibliothèque jQuery dans le répertoire /inc de votre projet, ainsi que le fichier image utilisé pour illustrer le bouton de suppression.
Voici les deux fichiers à télécharger :
Le code des vues
Ajout des deux nouveaux liens dans la page menu.jsp :
1 2 3 4 5 6 7 8 | <%@ page pageEncoding="UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <div id="menu"> <p><a href="<c:url value="/creationClient"/>">Créer un nouveau client</a></p> <p><a href="<c:url value="/creationCommande"/>">Créer une nouvelle commande</a></p> <p><a href="<c:url value="/listeClients"/>">Voir les clients existants</a></p> <p><a href="<c:url value="/listeCommandes"/>">Voir les commandes existantes</a></p> </div> |
/inc/menu.jsp
Modification du formulaire de création d'une commande :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | <%@ page pageEncoding="UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Création d'une commande</title> <link type="text/css" rel="stylesheet" href="<c:url value="/inc/style.css"/>" /> </head> <body> <c:import url="/inc/menu.jsp" /> <div> <form method="post" action="<c:url value="/creationCommande"/>"> <fieldset> <legend>Informations client</legend> <%-- Si et seulement si la Map des clients en session n'est pas vide, alors on propose un choix à l'utilisateur --%> <c:if test="${ !empty sessionScope.clients }"> <label for="choixNouveauClient">Nouveau client ? <span class="requis">*</span></label> <input type="radio" id="choixNouveauClient" name="choixNouveauClient" value="nouveauClient" checked /> Oui <input type="radio" id="choixNouveauClient" name="choixNouveauClient" value="ancienClient" /> Non <br/><br /> </c:if> <c:set var="client" value="${ commande.client }" scope="request" /> <div id="nouveauClient"> <c:import url="/inc/inc_client_form.jsp" /> </div> <%-- Si et seulement si la Map des clients en session n'est pas vide, alors on crée la liste déroulante --%> <c:if test="${ !empty sessionScope.clients }"> <div id="ancienClient"> <select name="listeClients" id="listeClients"> <option value="">Choisissez un client...</option> <%-- Boucle sur la map des clients --%> <c:forEach items="${ sessionScope.clients }" var="mapClients"> <%-- L'expression EL ${mapClients.value} permet de cibler l'objet Client stocké en tant que valeur dans la Map, et on cible ensuite simplement ses propriétés nom et prenom comme on le ferait avec n'importe quel bean. --%> <option value="${ mapClients.value.nom }">${ mapClients.value.prenom } ${ mapClients.value.nom }</option> </c:forEach> </select> </div> </c:if> </fieldset> <fieldset> <legend>Informations commande</legend> <label for="dateCommande">Date <span class="requis">*</span></label> <input type="text" id="v" name="dateCommande" value="<c:out value="${commande.date}"/>" size="30" maxlength="30" disabled /> <span class="erreur">${form.erreurs['dateCommande']}</span> <br /> <label for="montantCommande">Montant <span class="requis">*</span></label> <input type="text" id="montantCommande" name="montantCommande" value="<c:out value="${commande.montant}"/>" size="30" maxlength="30" /> <span class="erreur">${form.erreurs['montantCommande']}</span> <br /> <label for="modePaiementCommande">Mode de paiement <span class="requis">*</span></label> <input type="text" id="modePaiementCommande" name="modePaiementCommande" value="<c:out value="${commande.modePaiement}"/>" size="30" maxlength="30" /> <span class="erreur">${form.erreurs['modePaiementCommande']}</span> <br /> <label for="statutPaiementCommande">Statut du paiement</label> <input type="text" id="statutPaiementCommande" name="statutPaiementCommande" value="<c:out value="${commande.statutPaiement}"/>" size="30" maxlength="30" /> <span class="erreur">${form.erreurs['statutPaiementCommande']}</span> <br /> <label for="modeLivraisonCommande">Mode de livraison <span class="requis">*</span></label> <input type="text" id="modeLivraisonCommande" name="modeLivraisonCommande" value="<c:out value="${commande.modeLivraison}"/>" size="30" maxlength="30" /> <span class="erreur">${form.erreurs['modeLivraisonCommande']}</span> <br /> <label for="statutLivraisonCommande">Statut de la livraison</label> <input type="text" id="statutLivraisonCommande" name="statutLivraisonCommande" value="<c:out value="${commande.statutLivraison}"/>" size="30" maxlength="30" /> <span class="erreur">${form.erreurs['statutLivraisonCommande']}</span> <br /> <p class="info">${ form.resultat }</p> </fieldset> <input type="submit" value="Valider" /> <input type="reset" value="Remettre à zéro" /> <br /> </form> </div> <%-- Inclusion de la bibliothèque jQuery. Vous trouverez des cours sur JavaScript et jQuery aux adresses suivantes : - http://www.siteduzero.com/tutoriel-3-309961-dynamisez-vos-sites-web-avec-javascript.html - http://www.siteduzero.com/tutoriel-3-659477-un-site-web-dynamique-avec-jquery.html Si vous ne souhaitez pas télécharger et ajouter jQuery à votre projet, vous pouvez utiliser la version fournie directement en ligne par Google : <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script> --%> <script src="<c:url value="/inc/jquery.js"/>"></script> <%-- Petite fonction jQuery permettant le remplacement de la première partie du formulaire par la liste déroulante, au clic sur le bouton radio. --%> <script> jQuery(document).ready(function(){ /* 1 - Au lancement de la page, on cache le bloc d'éléments du formulaire correspondant aux clients existants */ $("div#ancienClient").hide(); /* 2 - Au clic sur un des deux boutons radio "choixNouveauClient", on affiche le bloc d'éléments correspondant (nouveau ou ancien client) */ jQuery('input[name=choixNouveauClient]:radio').click(function(){ $("div#nouveauClient").hide(); $("div#ancienClient").hide(); var divId = jQuery(this).val(); $("div#"+divId).show(); }); }); </script> </body> </html> |
/WEB-INF/creerCommande.jsp
Ajout des styles CSS des éléments des tableaux :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ... /* Tableaux -------------------------------------------------------------------------------------*/ table{ border-collapse: collapse; } tr.pair{ background-color: #efefef; } tr.impair{ background-color: #fff; } th{ color: #0568CD; border: 1px solid #0568CD; padding: 5px; } th.action{ border: 1px solid #900; color: #900; } td{ border: 1px solid #ddd; padding: 5px; } td.action{ text-align: center; } |
/inc/style.css
Création des pages listant les clients et commandes créés :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <%@ page pageEncoding="UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Liste des clients existants</title> <link type="text/css" rel="stylesheet" href="<c:url value="/inc/style.css"/>" /> </head> <body> <c:import url="/inc/menu.jsp" /> <div id="corps"> <c:choose> <%-- Si aucun client n'existe en session, affichage d'un message par défaut. --%> <c:when test="${ empty sessionScope.clients }"> <p class="erreur">Aucun client enregistré.</p> </c:when> <%-- Sinon, affichage du tableau. --%> <c:otherwise> <table> <tr> <th>Nom</th> <th>Prénom</th> <th>Adresse</th> <th>Téléphone</th> <th>Email</th> <th class="action">Action</th> </tr> <%-- Parcours de la Map des clients en session, et utilisation de l'objet varStatus. --%> <c:forEach items="${ sessionScope.clients }" var="mapClients" varStatus="boucle"> <%-- Simple test de parité sur l'index de parcours, pour alterner la couleur de fond de chaque ligne du tableau. --%> <tr class="${boucle.index % 2 == 0 ? 'pair' : 'impair'}"> <%-- Affichage des propriétés du bean Client, qui est stocké en tant que valeur de l'entrée courante de la map --%> <td><c:out value="${ mapClients.value.nom }"/></td> <td><c:out value="${ mapClients.value.prenom }"/></td> <td><c:out value="${ mapClients.value.adresse }"/></td> <td><c:out value="${ mapClients.value.telephone }"/></td> <td><c:out value="${ mapClients.value.email }"/></td> <%-- Lien vers la servlet de suppression, avec passage du nom du client - c'est-à-dire la clé de la Map - en paramètre grâce à la balise <c:param/>. --%> <td class="action"> <a href="<c:url value="/suppressionClient"><c:param name="nomClient" value="${ mapClients.key }" /></c:url>"> <img src="<c:url value="/inc/supprimer.png"/>" alt="Supprimer" /> </a> </td> </tr> </c:forEach> </table> </c:otherwise> </c:choose> </div> </body> </html> |
/WEB-INF/listerClients.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | <%@ page pageEncoding="UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Liste des commandes existantes</title> <link type="text/css" rel="stylesheet" href="<c:url value="/inc/style.css"/>" /> </head> <body> <c:import url="/inc/menu.jsp" /> <div id="corps"> <c:choose> <%-- Si aucune commande n'existe en session, affichage d'un message par défaut. --%> <c:when test="${ empty sessionScope.commandes }"> <p class="erreur">Aucune commande enregistrée.</p> </c:when> <%-- Sinon, affichage du tableau. --%> <c:otherwise> <table> <tr> <th>Client</th> <th>Date</th> <th>Montant</th> <th>Mode de paiement</th> <th>Statut de paiement</th> <th>Mode de livraison</th> <th>Statut de livraison</th> <th class="action">Action</th> </tr> <%-- Parcours de la Map des commandes en session, et utilisation de l'objet varStatus. --%> <c:forEach items="${ sessionScope.commandes }" var="mapCommandes" varStatus="boucle"> <%-- Simple test de parité sur l'index de parcours, pour alterner la couleur de fond de chaque ligne du tableau. --%> <tr class="${boucle.index % 2 == 0 ? 'pair' : 'impair'}"> <%-- Affichage des propriétés du bean Commande, qui est stocké en tant que valeur de l'entrée courante de la map --%> <td><c:out value="${ mapCommandes.value.client.prenom } ${ mapCommandes.value.client.nom }"/></td> <td><c:out value="${ mapCommandes.value.date }"/></td> <td><c:out value="${ mapCommandes.value.montant }"/></td> <td><c:out value="${ mapCommandes.value.modePaiement }"/></td> <td><c:out value="${ mapCommandes.value.statutPaiement }"/></td> <td><c:out value="${ mapCommandes.value.modeLivraison }"/></td> <td><c:out value="${ mapCommandes.value.statutLivraison }"/></td> <%-- Lien vers la servlet de suppression, avec passage de la date de la commande - c'est-à-dire la clé de la Map - en paramètre grâce à la balise <c:param/>. --%> <td class="action"> <a href="<c:url value="/suppressionCommande"><c:param name="dateCommande" value="${ mapCommandes.key }" /></c:url>"> <img src="<c:url value="/inc/supprimer.png"/>" alt="Supprimer" /> </a> </td> </tr> </c:forEach> </table> </c:otherwise> </c:choose> </div> </body> </html> |
/WEB-INF/listerCommandes.jsp
Le code des servlets
Ajout des quatre servlets de suppression et de listage dans le fichier web.xml :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | <?xml version="1.0" encoding="UTF-8"?> <web-app> <filter> <filter-name>Set Character Encoding</filter-name> <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>ignore</param-name> <param-value>false</param-value> </init-param> </filter> <filter-mapping> <filter-name>Set Character Encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>CreationClient</servlet-name> <servlet-class>com.sdzee.tp.servlets.CreationClient</servlet-class> </servlet> <servlet> <servlet-name>ListeClients</servlet-name> <servlet-class>com.sdzee.tp.servlets.ListeClients</servlet-class> </servlet> <servlet> <servlet-name>SuppressionClient</servlet-name> <servlet-class>com.sdzee.tp.servlets.SuppressionClient</servlet-class> </servlet> <servlet> <servlet-name>CreationCommande</servlet-name> <servlet-class>com.sdzee.tp.servlets.CreationCommande</servlet-class> </servlet> <servlet> <servlet-name>ListeCommandes</servlet-name> <servlet-class>com.sdzee.tp.servlets.ListeCommandes</servlet-class> </servlet> <servlet> <servlet-name>SuppressionCommande</servlet-name> <servlet-class>com.sdzee.tp.servlets.SuppressionCommande</servlet-class> </servlet> <servlet-mapping> <servlet-name>CreationClient</servlet-name> <url-pattern>/creationClient</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ListeClients</servlet-name> <url-pattern>/listeClients</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>SuppressionClient</servlet-name> <url-pattern>/suppressionClient</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>CreationCommande</servlet-name> <url-pattern>/creationCommande</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ListeCommandes</servlet-name> <url-pattern>/listeCommandes</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>SuppressionCommande</servlet-name> <url-pattern>/suppressionCommande</url-pattern> </servlet-mapping> </web-app> |
/WEB-INF/web.xml
Création des servlets de listage :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.sdzee.tp.servlets; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ListeClients extends HttpServlet { public static final String ATT_CLIENT = "client"; public static final String ATT_FORM = "form"; public static final String VUE = "/WEB-INF/listerClients.jsp"; public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { /* À la réception d'une requête GET, affichage de la liste des clients */ this.getServletContext().getRequestDispatcher( VUE ).forward( request, response ); } } |
com.sdzee.tp.servlets.ListeClients
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.sdzee.tp.servlets; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ListeCommandes extends HttpServlet { public static final String ATT_COMMANDE = "commande"; public static final String ATT_FORM = "form"; public static final String VUE = "/WEB-INF/listerCommandes.jsp"; public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { /* À la réception d'une requête GET, affichage de la liste des commandes */ this.getServletContext().getRequestDispatcher( VUE ).forward( request, response ); } } |
com.sdzee.tp.servlets.ListeClients
Création des servlets de suppression :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | package com.sdzee.tp.servlets; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.sdzee.tp.beans.Client; public class SuppressionClient extends HttpServlet { public static final String PARAM_NOM_CLIENT = "nomClient"; public static final String SESSION_CLIENTS = "clients"; public static final String VUE = "/listeClients"; public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { /* Récupération du paramètre */ String nomClient = getValeurParametre( request, PARAM_NOM_CLIENT ); /* Récupération de la Map des clients enregistrés en session */ HttpSession session = request.getSession(); Map<String, Client> clients = (HashMap<String, Client>) session.getAttribute( SESSION_CLIENTS ); /* Si le nom du client et la Map des clients ne sont pas vides */ if ( nomClient != null && clients != null ) { /* Alors suppression du client de la Map */ clients.remove( nomClient ); /* Et remplacement de l'ancienne Map en session par la nouvelle */ session.setAttribute( SESSION_CLIENTS, clients ); } /* Redirection vers la fiche récapitulative */ response.sendRedirect( request.getContextPath() + VUE ); } /* * Méthode utilitaire qui retourne null si un paramètre est vide, et son * contenu sinon. */ private static String getValeurParametre( HttpServletRequest request, String nomChamp ) { String valeur = request.getParameter( nomChamp ); if ( valeur == null || valeur.trim().length() == 0 ) { return null; } else { return valeur; } } } |
com.sdzee.tp.servlets.SuppressionClient
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | package com.sdzee.tp.servlets; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.sdzee.tp.beans.Commande; public class SuppressionCommande extends HttpServlet { public static final String PARAM_DATE_COMMANDE = "dateCommande"; public static final String SESSION_COMMANDES = "commandes"; public static final String VUE = "/listeCommandes"; public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { /* Récupération du paramètre */ String dateCommande = getValeurParametre( request, PARAM_DATE_COMMANDE ); /* Récupération de la Map des commandes enregistrées en session */ HttpSession session = request.getSession(); Map<String, Commande> commandes = (HashMap<String, Commande>) session.getAttribute( SESSION_COMMANDES ); /* Si la date de la commande et la Map des commandes ne sont pas vides */ if ( dateCommande != null && commandes != null ) { /* Alors suppression de la commande de la Map */ commandes.remove( dateCommande ); /* Et remplacement de l'ancienne Map en session par la nouvelle */ session.setAttribute( SESSION_COMMANDES, commandes ); } /* Redirection vers la fiche récapitulative */ response.sendRedirect( request.getContextPath() + VUE ); } /* * Méthode utilitaire qui retourne null si un paramètre est vide, et son * contenu sinon. */ private static String getValeurParametre( HttpServletRequest request, String nomChamp ) { String valeur = request.getParameter( nomChamp ); if ( valeur == null || valeur.trim().length() == 0 ) { return null; } else { return valeur; } } } |
com.sdzee.tp.servlets.SuppressionCommande
Modification des servlets existantes pour l'enregistrement en session :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | package com.sdzee.tp.servlets; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.sdzee.tp.beans.Client; import com.sdzee.tp.forms.CreationClientForm; public class CreationClient extends HttpServlet { public static final String ATT_CLIENT = "client"; public static final String ATT_FORM = "form"; public static final String SESSION_CLIENTS = "clients"; public static final String VUE_SUCCES = "/WEB-INF/afficherClient.jsp"; public static final String VUE_FORM = "/WEB-INF/creerClient.jsp"; public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { /* À la réception d'une requête GET, simple affichage du formulaire */ this.getServletContext().getRequestDispatcher( VUE_FORM ).forward( request, response ); } public void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { /* Préparation de l'objet formulaire */ CreationClientForm form = new CreationClientForm(); /* Traitement de la requête et récupération du bean en résultant */ Client client = form.creerClient( request ); /* Ajout du bean et de l'objet métier à l'objet requête */ request.setAttribute( ATT_CLIENT, client ); request.setAttribute( ATT_FORM, form ); /* Si aucune erreur */ if ( form.getErreurs().isEmpty() ) { /* Alors récupération de la map des clients dans la session */ HttpSession session = request.getSession(); Map<String, Client> clients = (HashMap<String, Client>) session.getAttribute( SESSION_CLIENTS ); /* Si aucune map n'existe, alors initialisation d'une nouvelle map */ if ( clients == null ) { clients = new HashMap<String, Client>(); } /* Puis ajout du client courant dans la map */ clients.put( client.getNom(), client ); /* Et enfin (ré)enregistrement de la map en session */ session.setAttribute( SESSION_CLIENTS, clients ); /* Affichage de la fiche récapitulative */ this.getServletContext().getRequestDispatcher( VUE_SUCCES ).forward( request, response ); } else { /* Sinon, ré-affichage du formulaire de création avec les erreurs */ this.getServletContext().getRequestDispatcher( VUE_FORM ).forward( request, response ); } } } |
com.sdzee.tp.servlets.CreationClient
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | package com.sdzee.tp.servlets; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.sdzee.tp.beans.Client; import com.sdzee.tp.beans.Commande; import com.sdzee.tp.forms.CreationCommandeForm; public class CreationCommande extends HttpServlet { public static final String ATT_COMMANDE = "commande"; public static final String ATT_FORM = "form"; public static final String SESSION_CLIENTS = "clients"; public static final String SESSION_COMMANDES = "commandes"; public static final String VUE_SUCCES = "/WEB-INF/afficherCommande.jsp"; public static final String VUE_FORM = "/WEB-INF/creerCommande.jsp"; public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { /* À la réception d'une requête GET, simple affichage du formulaire */ this.getServletContext().getRequestDispatcher( VUE_FORM ).forward( request, response ); } public void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { /* Préparation de l'objet formulaire */ CreationCommandeForm form = new CreationCommandeForm(); /* Traitement de la requête et récupération du bean en résultant */ Commande commande = form.creerCommande( request ); /* Ajout du bean et de l'objet métier à l'objet requête */ request.setAttribute( ATT_COMMANDE, commande ); request.setAttribute( ATT_FORM, form ); /* Si aucune erreur */ if ( form.getErreurs().isEmpty() ) { /* Alors récupération de la map des clients dans la session */ HttpSession session = request.getSession(); Map<String, Client> clients = (HashMap<String, Client>) session.getAttribute( SESSION_CLIENTS ); /* Si aucune map n'existe, alors initialisation d'une nouvelle map */ if ( clients == null ) { clients = new HashMap<String, Client>(); } /* Puis ajout du client de la commande courante dans la map */ clients.put( commande.getClient().getNom(), commande.getClient() ); /* Et enfin (ré)enregistrement de la map en session */ session.setAttribute( SESSION_CLIENTS, clients ); /* Ensuite récupération de la map des commandes dans la session */ Map<String, Commande> commandes = (HashMap<String, Commande>) session.getAttribute( SESSION_COMMANDES ); /* Si aucune map n'existe, alors initialisation d'une nouvelle map */ if ( commandes == null ) { commandes = new HashMap<String, Commande>(); } /* Puis ajout de la commande courante dans la map */ commandes.put( commande.getDate(), commande ); /* Et enfin (ré)enregistrement de la map en session */ session.setAttribute( SESSION_COMMANDES, commandes ); /* Affichage de la fiche récapitulative */ this.getServletContext().getRequestDispatcher( VUE_SUCCES ).forward( request, response ); } else { /* Sinon, ré-affichage du formulaire de création avec les erreurs */ this.getServletContext().getRequestDispatcher( VUE_FORM ).forward( request, response ); } } } |
com.sdzee.tp.servlets.CreationCommande
Le code des objets métiers
Modification de l'objet gérant la création d'une commande :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | package com.sdzee.tp.forms; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import com.sdzee.tp.beans.Client; import com.sdzee.tp.beans.Commande; public final class CreationCommandeForm { private static final String CHAMP_CHOIX_CLIENT = "choixNouveauClient"; private static final String CHAMP_LISTE_CLIENTS = "listeClients"; private static final String CHAMP_DATE = "dateCommande"; private static final String CHAMP_MONTANT = "montantCommande"; private static final String CHAMP_MODE_PAIEMENT = "modePaiementCommande"; private static final String CHAMP_STATUT_PAIEMENT = "statutPaiementCommande"; private static final String CHAMP_MODE_LIVRAISON = "modeLivraisonCommande"; private static final String CHAMP_STATUT_LIVRAISON = "statutLivraisonCommande"; private static final String ANCIEN_CLIENT = "ancienClient"; private static final String SESSION_CLIENTS = "clients"; private static final String FORMAT_DATE = "dd/MM/yyyy HH:mm:ss"; private String resultat; private Map<String, String> erreurs = new HashMap<String, String>(); public Map<String, String> getErreurs() { return erreurs; } public String getResultat() { return resultat; } public Commande creerCommande( HttpServletRequest request ) { Client client; /* * Si l'utilisateur choisit un client déjà existant, pas de validation à * effectuer */ String choixNouveauClient = getValeurChamp( request, CHAMP_CHOIX_CLIENT ); if ( ANCIEN_CLIENT.equals( choixNouveauClient ) ) { /* Récupération du nom du client choisi */ String nomAncienClient = getValeurChamp( request, CHAMP_LISTE_CLIENTS ); /* Récupération de l'objet client correspondant dans la session */ HttpSession session = request.getSession(); client = ( (Map<String, Client>) session.getAttribute( SESSION_CLIENTS ) ).get( nomAncienClient ); } else { /* * Sinon on garde l'ancien mode, pour la validation des champs. * * L'objet métier pour valider la création d'un client existe déjà, * il est donc déconseillé de dupliquer ici son contenu ! À la * place, il suffit de passer la requête courante à l'objet métier * existant et de récupérer l'objet Client créé. */ CreationClientForm clientForm = new CreationClientForm(); client = clientForm.creerClient( request ); /* * Et très important, il ne faut pas oublier de récupérer le contenu * de la map d'erreur créée par l'objet métier CreationClientForm * dans la map d'erreurs courante, actuellement vide. */ erreurs = clientForm.getErreurs(); } /* * Ensuite, il suffit de procéder normalement avec le reste des champs * spécifiques à une commande. */ /* * Récupération et conversion de la date en String selon le format * choisi. */ DateTime dt = new DateTime(); DateTimeFormatter formatter = DateTimeFormat.forPattern( FORMAT_DATE ); String date = dt.toString( formatter ); String montant = getValeurChamp( request, CHAMP_MONTANT ); String modePaiement = getValeurChamp( request, CHAMP_MODE_PAIEMENT ); String statutPaiement = getValeurChamp( request, CHAMP_STATUT_PAIEMENT ); String modeLivraison = getValeurChamp( request, CHAMP_MODE_LIVRAISON ); String statutLivraison = getValeurChamp( request, CHAMP_STATUT_LIVRAISON ); Commande commande = new Commande(); commande.setClient( client ); double valeurMontant = -1; try { valeurMontant = validationMontant( montant ); } catch ( Exception e ) { setErreur( CHAMP_MONTANT, e.getMessage() ); } commande.setMontant( valeurMontant ); commande.setDate( date ); try { validationModePaiement( modePaiement ); } catch ( Exception e ) { setErreur( CHAMP_MODE_PAIEMENT, e.getMessage() ); } commande.setModePaiement( modePaiement ); try { validationStatutPaiement( statutPaiement ); } catch ( Exception e ) { setErreur( CHAMP_STATUT_PAIEMENT, e.getMessage() ); } commande.setStatutPaiement( statutPaiement ); try { validationModeLivraison( modeLivraison ); } catch ( Exception e ) { setErreur( CHAMP_MODE_LIVRAISON, e.getMessage() ); } commande.setModeLivraison( modeLivraison ); try { validationStatutLivraison( statutLivraison ); } catch ( Exception e ) { setErreur( CHAMP_STATUT_LIVRAISON, e.getMessage() ); } commande.setStatutLivraison( statutLivraison ); if ( erreurs.isEmpty() ) { resultat = "Succès de la création de la commande."; } else { resultat = "Échec de la création de la commande."; } return commande; } private double validationMontant( String montant ) throws Exception { double temp; if ( montant != null ) { try { temp = Double.parseDouble( montant ); if ( temp < 0 ) { throw new Exception( "Le montant doit être un nombre positif." ); } } catch ( NumberFormatException e ) { temp = -1; throw new Exception( "Le montant doit être un nombre." ); } } else { temp = -1; throw new Exception( "Merci d'entrer un montant." ); } return temp; } private void validationModePaiement( String modePaiement ) throws Exception { if ( modePaiement != null ) { if ( modePaiement.length() < 2 ) { throw new Exception( "Le mode de paiement doit contenir au moins 2 caractères." ); } } else { throw new Exception( "Merci d'entrer un mode de paiement." ); } } private void validationStatutPaiement( String statutPaiement ) throws Exception { if ( statutPaiement != null && statutPaiement.length() < 2 ) { throw new Exception( "Le statut de paiement doit contenir au moins 2 caractères." ); } } private void validationModeLivraison( String modeLivraison ) throws Exception { if ( modeLivraison != null ) { if ( modeLivraison.length() < 2 ) { throw new Exception( "Le mode de livraison doit contenir au moins 2 caractères." ); } } else { throw new Exception( "Merci d'entrer un mode de livraison." ); } } private void validationStatutLivraison( String statutLivraison ) throws Exception { if ( statutLivraison != null && statutLivraison.length() < 2 ) { throw new Exception( "Le statut de livraison doit contenir au moins 2 caractères." ); } } /* * Ajoute un message correspondant au champ spécifié à la map des erreurs. */ private void setErreur( String champ, String message ) { erreurs.put( champ, message ); } /* * Méthode utilitaire qui retourne null si un champ est vide, et son contenu * sinon. */ private static String getValeurChamp( HttpServletRequest request, String nomChamp ) { String valeur = request.getParameter( nomChamp ); if ( valeur == null || valeur.trim().length() == 0 ) { return null; } else { return valeur; } } } |
com.sdzee.tp.forms.CreationCommandeForm