Exercice 3 - Amélioration de l'application⚓︎
1. Développement de la V2.0⚓︎
Nous allons donc maintenant rajouter l'implémentation de la méthode doPost
dans notre servlet pour gérer cette requête :
-
Dans la classe
StoreServlet
, ouvrir le menu :material-mouse:Sources > Override/Implement Methods...
, et surcharger la méthodedoPost
deHttpServlet
.Astuce : surcharge rapide
Pour surcharger une méthode, on peut également écrire le début de son nom, ici le début de
doPost
, et appuyer sur Ctrl+Entrée pour faire de l'autocomplétion. On obtient le même résultat, mais plus rapidement. -
Comme pour la méthode
doGet
, renommer les paramètres enrequest
etresponse
respectivement. -
Dans cette méthode, nous allons récupérer les données saisies par l'utilisateur depuis le formulaire HTML. Ces données sont en paramètre de la requête HTTP, que la méthode utilisée soit GET ou POST. Nous allons donc faire
request.getParameter(<attribut_name>)
.☕ Code Java - Méthode doPost - 1/4 1 2 3
String penNumber = request.getParameter("penNb");//(1)! String feltNumber = ...; String rubberNumber = ...;
- Le nom du paramètre, ici
penNb
, doit correspondre à l'attributname
de la balise<input type="*">
du formulaire HTML.
- Le nom du paramètre, ici
-
Ces données saisies par l'utilisateur doivent être "envoyées" au modèle. Dans cette méthode, on rajoute donc :
☕ Code Java - Méthode doPost - 2/4 1 2 3 4 5
CartBean cart = new CartBean(); cart.setPenNumber(Integer.parseInt(penNumber));//(1)! ... ...
- Les objets récupérés en paramètre de la requête sont des
String
. Ici, il faut donc le transformer enInteger
.
- Les objets récupérés en paramètre de la requête sont des
-
Ensuite, on appelle la couche métier, pour mettre à jour les données du panier (les 3 RG) en fonction de ce que l'utilisateur a sélectionné. Pour cela, il va nous falloir une instance de la classe implémentant l'interface
StoreBusiness
. On pourrait l'instancier ici, mais on aurait alors une nouvelle instance à chaque appel de la Servlet, ce qui serait inutile. On va donc instancier cette classe une seule fois, à l'initialisation de la Servlet. La méthodevoid init() throws ServletException
sert à cela.Dans la classe
StoreServlet
, ajouter une propriété privée, qui ne sera instanciée qu'une seule fois :☕ Code Javaprivate StoreBusiness storeBusiness; @Override public void init() throws ServletException { this.storeBusiness = new StoreBusinessImpl();//(1)! }
-
C'est ici qu'on indique quelle classe implémente notre interface.
Pour l'instant, nous indiquons "en dur" quelle classe implémente l'interface. Nous verrons bientôt comment indiquer cela dans un fichier de configuration, afin de pouvoir changer d'implémentation sans avoir à toucher au code.
Enfin, dans la méthode
doPost
, on peut maintenant appeler la couche métier :☕ Code Java - Méthode doPost - 3/4 1
cart = this.storeBusiness.computePrices(cart);
-
-
Enfin, on redirige l'utilisateur vers la bonne vue :
☕ Code Java - Méthode doPost - 4/4 1 2
RequestDispatcher dispatcher = request.getRequestDispatcher("store.jsp"); dispatcher.forward(request, response);
2. Test de la V2.0⚓︎
En testant à nouveau (pour cela, il suffit de redémarrer le serveur), on constate maintenant :
- Qu'au premier affichage, le nombre de chaque article est vide, et qu'il y a une erreur si on ne met pas des nombres partout ...
- Qu'il ne se passe rien si on saisit des nombres partout et qu'on cliquer sur
Valider ...
3. Développement de la V2.1⚓︎
Nous allons commencer par traiter le deuxième problème.
Le comportement observé est en fait normal. Le modèle (ici, le bean CartBean
) n'est pas "envoyé" à la vue par le contrôleur.
➡️ Pour cela, nous allons l'ajouter dans la requête. À la fin de la méthode doPost
de la servlet, juste avant l'appel du RequestDispatcher
, il faut ajouter :
☕ Code Java - StoreServlet.doPost | |
---|---|
1 |
|
setAttribute
permet d'ajouter un attribut à la requête (à ne pas confondre avec un paramètre).
Le premier paramètre,"USER_CART"
est la clef : c'est ce qui va nous permettre de récupérer le bean dans la vue.
Le deuxième paramètre,cart
, est le bean.
Le bean est maintenant envoyé à la vue, il faut le récupérer avec le méthode HttpRequest.getAttribute()
. On rajoute le code correspondant juste avant la balise <!DOCTYPE html>
:
Java Server Page | |
---|---|
1 2 3 |
|
- Les balises
<% %>
permettent d'ajouter des scriptlet, c'est-à-dire du code Java à l'intérieur du code HTML.
La classe Java CartBean
doit être importée dans la JSP. Il suffit d'utiliser l'auto-complétion (Ctrl+Space), lorsqu'on écrit CartBean, et l'import va être ajouté automatiquement tout en haut du fichier :
Java Server Page | |
---|---|
1 |
|
- Ceci s'appelle une directive.
On peut maintenant afficher les informations présentes dans le bean et calculées par la couche métier. Nous allons modifier la partie "Récapitulatif du panier" en ajoutant les appels au bean :
Java Server Page | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
- Le code Java entre
<%= %>
s'appelle une expression. Cela permet d'afficher la valeur de l'expression.
Le code<%=variable %>
est équivalent à<% out.println(variable) %>
, il affiche le contenu devariable
.
4. Test de la V2.1⚓︎
Si on teste à nouveau notre application, on a maintenant une erreur au premier affichage 😫 :
Cela vient du fait qu'au premier affichage, dans le scriptlet dans la JSP, on récupère dans la requête un objet que nous n'avons pas encore placé ... On obtient donc un null
, d'où l'erreur :
java.lang.NullPointerException: Cannot invoke "fr.univtours.polytech.boutique.model.CartBean.getCartPrice()" because "cart" is null
5. Développement de la V2.2⚓︎
Il y a plusieurs façons de gérer cette erreur. Ce que nous allons faire, c'est de placer un objet CartBean
vide (mais pas null
) dans la requête au premier affichage, c'est-à-dire dans la méthode doGet
. On a donc maintenant :
☕ Code Java | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
- On créée un objet vide, mais pas
null
. - Il y a maintenant un objet dans la requête au premier affichage.
6. Test de la V2.2⚓︎
Le premier affichage fonctionne désormais. Il nous reste à mieux initialiser notre formulaire, notamment pour ne plus avoir d'erreur lorsqu'on clique sur
7. Développement de la V2.3⚓︎
Le problème vient du fait qu'on "caste" une chaîne de caractère vide en Integer
... Une façon de ne plus avoir ce problème est d'initialiser tous les champs du bean CartBean
à 0 (on supprime ainsi également l'affichage des null dans la partie panier) :
☕ Code Java - classe CartBean | |
---|---|
1 2 3 4 5 6 |
|
Enfin, dans la vue, il faut récupérer les nombres d'articles sélectionnés. Pour cela, il faut ajouter l'attribut value
aux balises HTML <input type="number">
. Cela permet d'avoir une valeur par défaut, qui va être celle stockée dans le bean présent dans la requête. Dans 📄store.jsp
, la partie Liste des produits devient donc :
📄 store.jsp | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|