Application Struts pas à pas avec Eclipse (Web Tools Platform) et Tomcat

Régis POUILLER

Cet article a pour objectif de présenter étape par étape la création d'une application web avec le framework Struts, l'environnement de développement Eclipse et le serveur Tomcat.

- Titre : Application Struts pas à pas avec Eclipse (Web Tools Platform) et Tomcat

- Auteur : Régis POUILLER

- Parution : 1 avril 2009

- Mise à jour : 2 avril 2009

- Licence : Copyright ® 2008 Régis POUILLER. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. INTRODUCTION

- II. AUTRES RESSOURCES SUR DEVELOPPEZ.COM

- III. INSTALLATION DES OUTILS

- III-A. Installation de la JRE

- III-B. Installation de Tomcat

- III-C. Installation d'Eclipse

- IV. "BONJOUR LE MONDE"

- IV-A. Etape 1 : Création de l'aplication dans Eclipse

- IV-B. Etape 2 : JSP "Bonjour le monde"

- IV-B-1. Création d'un dossier "pages"

- IV-B-2. Création de la JSP "bonjour.jsp"

- IV-B-3. Déploiement de l'application

- IV-C. Etape 3 : Utilisation de Struts dans la JSP "Bonjour le monde"

- IV-C-1. Intégration des librairies Struts

- IV-C-2. Création d'un fichier d'internationalisation "Resources.properties"

- IV-C-3. Création d'un fichier de configuration Struts "struts-config.xml"

- IV-C-4. Modification du fichier "web.xml"

- IV-C-5. Modification de la JSP "bonjour.jsp"

- IV-C-6. Déploiement de l'application

- IV-D. Fonctionnement de l'ensemble

- V. AFFICHAGE DE DONNEES EN BASE

- V-A. Etape 4 : Création de la base de données

- V-A-1. Installation et lancement de HSQLDB

- V-A-2. Création de la table "LISTECOURSES"

- V-A-3. Insertion des données

- V-A-4. Vérification

- V-B. Etape 5 : Développement de l'affichage

- V-B-1. Déclaration de la ressource dans "web.xml"

- V-B-2. Création de la classe de bean

- V-B-3. Création de la classe de bean de retour de la DAO

- V-B-4. Création de la classe DAO accédant à la base de données

- V-B-5. Création de la classe Action d'affichage

- V-B-6. Création de la JSP d'affichage de la liste de courses

- V-B-7. Création de la JSP d'erreur

- V-B-8. Modification du fichier d'internationalisation

- V-B-9. Modification du fichier de configuration "struts-config.xml"

- V-C. Etape 6 : Configuration de Tomcat

- V-C-1. Déclaration de la ressource JDBC dans le serveur

- V-C-2. Déclaration du lien de la ressource

- V-C-3. Copie de la librairie HSQLDB dans les librairies Tomcat

- V-C-4. Déploiement de l'application

- V-D. Fonctionnement de l'ensemble

- VI. CREATION DE DONNEES EN BASE

- VI-A. Etape 7 : Création d'enregistrements dans la base de données

- VI-A-1. Modification de la classe DAO

- VI-A-2. Création de la classe Action de création

- VI-A-3. Création d'un nouveau fichier d'internationalisation

- VI-A-4. Création d'un nouveau fichier de configuration "struts-config-creation.xml"

- VI-A-5. Modification du fichier "web.xml"

- VI-A-6. Création de la JSP de création

- VI-A-7. Création du fichier de validation "validation-creation.xml"

- VI-A-8. Modification du fichier de configuration "struts-config.xml"

- VI-A-9. Déploiement de l'application

- VI-A-11. Vérification

- VI-B. Fonctionnement de l'ensemble

- VII. SUPPRESSION DE DONNEES EN BASE

- VII-A. Etape 8 : Suppression d'enregistrements dans la base de données

- VII-A-1. Modification de la classe DAO

- VII-A-2. Création de la classe Action de suppression

- VII-A-3. Création d'un nouveau fichier d'internationalisation

- VII-A-4. Création d'un nouveau fichier de configuration "struts-config-suppression.xml"

- VII-A-5. Modification du fichier "web.xml"

- VII-A-6. Création de la JSP de suppression

- VII-A-7. Déploiement de l'application

- VII-A-8. Vérification

- VII-B. Fonctionnement de l'ensemble

- VIII. MODIFICATION DE DONNEES EN BASE

- VIII-A. Etape 9 : Modification d'enregistrements dans la base de données

- VIII-A-1. Intégration de la librairie Commons Collections

- VIII-A-2. Création de la classe de bean

- VIII-A-3. Modification de la classe DAO

- VIII-A-4. Création de la classe de formulaire

- VIII-A-5. Modification du fichier d'internationalisation

- VIII-A-6. Création de la classe Action d'affichage

- VIII-A-7. Création de la classe Action de modification

- VIII-A-8. Création du fichier d'internationalisation

- VIII-A-9. Création du fichier de configuration "struts-config-modification.xml"

- VIII-A-10. Modification du fichier "web.xml"

- VIII-A-11. Création de la JSP de modification

- VIII-A-12. Déploiement de l'application

- VIII-A-13. Vérification

- VIII-B. Fonctionnement de l'ensemble

- IX. UNIFICATION DE L'APPLICATION PAR UN MENU

- IX-A. Etape 10 : Création d'un menu

- IX-A-1. Modification du fichier d'internationalisation

- IX-A-2. Création de la JSP "squelette"

- IX-A-3. Création du fichier de définition des tiles

- IX-A-4. Modification du fichier de configuration "struts-config.xml"

- IX-A-5. Modification de la JSP d'erreur

- IX-A-6. Modification de la JSP d'affichage

- IX-A-7. Modification de la JSP de création

- IX-A-8. Modification de la JSP de suppression

- IX-A-9. Modification de la JSP de modification

- IX-A-10. Modification du fichier de configuration "struts-config.xml"

- IX-A-11. Modification du fichier de configuration "struts-config-creation.xml"

- IX-A-12. Modification du fichier de configuration "struts-config-suppression.xml"

- IX-A-13. Modification du fichier de configuration "struts-config-modification.xml"

- IX-A-14. Modification du fichier "web.xml"

- IX-A-15. Déploiement de l'application

- IX-A-16. Vérification

- IX-B. Fonctionnement de l'ensemble

- X. REMERCIEMENTS

- XI. SOURCES DU PROJET A CHAQUE ETAPE

I - INTRODUCTION

Cet article va présenter étape par étape la réalisation d'une application web simple. Les différentes étapes sont :

- Installation des outils : la JRE, Tomcat, Eclipse et Web Tools Platform

- Développement d'une page web affichant "Bonjour le monde" : création du projet, création d'une JSP simple affichant le message, déploiement de l'application et modification de la JSP simple avec Struts

- Développement d'une page web affichant les valeurs d'une base de données : création de la base, paramétrage de la ressource JDBC dans Tomcat

- Développement d'une page web permettant de créer des valeurs en base de données

- Développement d'une page web permettant de supprimer des valeurs en base de données

- Développement d'une page web permettant de modifier des valeurs en base de données

- Unification de ces pages afin d'en faire une application web regroupant ces fonctionnalités

Ces étapes sont l'occasion d'approcher diverses techniques : Web Tools Platform avec Eclipse, Paramètrage et utilisation de ressources JNDI, Struts (taglibs, action, formulaire avec validation dans un fichier XML ou dans le code Java, mapping, tiles) et Internationalisation.

Pour une compréhension aisée de cet article, il est conseillé d'avoir quelques connaissances en Java, HTML/Javascript et SQL/Base de données.

Pour la réalisation de cet article les version des outils sont :

- Java Runtime Environment : 5.0 Update 17

- Tomcat : 6.0.18

- Eclipse : developpement Java EE 3.4 Ganymede SR2

- Struts : 1.3.10 (Full Distribution) ou (Library : pour le tutoriel, seules les librairies sont nécessaires)

- HSQLDB : 1.8.0.10

- Commons Collections : 3.2.1

La plupart des images de l'article sont une partie d'une autre image. Pour accéder à l'image complète, il suffit de cliquer sur l'image de l'article.

Un discussion a été ouverte pour la publication de cet article, pour les commentaires. [ Commentez ]

II - AUTRES RESSOURCES SUR DEVELOPPEZ.COM

FAQ Struts

Création d'une première application Struts avec Eclipse par stessy delcroix

Développement web avec Java, Eclipse et Tomcat par Serge Tahé

Introduction au framework Struts par Mickael BARON

Le Framework Struts par Metoss

III - INSTALLATION DES OUTILS

III-A - Installation de la JRE

Lancer l'exécutable d'installation ("jre-1_5_0_17-windows-i586-p.exe").

Choisir "Installation type - Toutes les fonctions recommandées sont installées.". Puis cliquer sur "Accepter >".

L'installation se déroule. A la fin, cliquer sur "Terminer".

III-B - Installation de Tomcat

Lancer l'executable d'installation ("apache-tomcat-6.0.18.exe"). Puis cliquer sur "Next >".

Validation des termes de la licence : Cliquer sur "I Agree".

Choix du type d'installation : choisir le type d'installation "Normal". Puis cliquer sur "Next >".

Choix du dossier d'installation de Tomcat : cliquer sur "Next >".

Choix du port de tomcat et du compte administrateur : on peut cliquer directement sur "Next >". Mais par sécurité, je conseillerais de saisir un compte administrateur différent de celui par défaut (surtout si l'ordinateur est connecté à internet). En cas d'oubli des paramètres du compte, ils sont en clair dans le fichier "C:\Program Files\Apache Software Foundation\Tomcat 6.0\conf\tomcat-users.xml".

Sélection du dossier d'installation de la JRE : normalement, le programme d'installtion le trouve tout seul, sinon le saisir. Cliquer sur "Install".

Décocher "Show Readme". Puis cliquer sur "Finish".

Vérifier que Tomcat est bien installé en testant la "Page Racine" de Tomcat.

Stopper Tomcat (il sera lancé directement depuis Eclipse). Faire un clic droit sur le Monitor Tomcat dans la Systray. Puis cliquer sur "Stop service".

III-C - Installation d'Eclipse

Décompresser le fichier "eclipse-jee-ganymede-SR2-win32.zip" dans le dossier "Program Files". On obtient un dossier "eclipse".

Lancer l'executable "eclipse.exe" contenu dans le dossier "eclipse".

Choisir un workspace (il s'agit du dossier qui contiendra les projets). Cocher "Use this as default and do not ask again". Puis, cliquer sur "OK".

Fermer l'onglet "Welcome".

Faire un clic droit sur la vue "Servers". Choisir "New"/"Server".

Déplier "Apache". Choisir "Tomcat v6.0 Server". Puis, cliquer sur "Next >".

Sélectionner le chemin d'installation de Tomcat. Sélectionner la JRE correspondant à celle précédemment installée. Puis, cliquer sur "Finish".

IV - "BONJOUR LE MONDE"

IV-A - Etape 1 : Création de l'aplication dans Eclipse

Faire un clic droit sur la vue "Project Explorer". Choisir "New"/"Dynamic Web Project".

Saisir "MonApplication" dans "Project name". Puis cliquer sur "Finish".

IV-B - Etape 2 : JSP "Bonjour le monde"

L'objectif du chapitre est de modifier l'application avec une JSP qui affiche "Bonjour le monde".

IV-B-1 - Création d'un dossier "pages"

Cliquer sur le dossier "WebContent". Faire un clic droit. Choisir "New"/"Folder".

Saisir "pages" dans "Folder name". Puis, cliquer sur "Finish".

IV-B-2 - Création de la JSP "bonjour.jsp"

Cliquer sur le nouveau dossier "pages". Faire un clic droit. Choisir "New"/"JSP".

Saisir "bonjour.jsp" dans "File name". Puis, cliquer sur "Finish".

Saisir le code suivant dans "bonjour.jsp" :

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<html>
<head>
<title>Bonjour</title>
</head>
<body>
Bonjour le monde.
</body>
</html>

IV-B-3 - Déploiement de l'application

Sélectionner le serveur Tomcat dans la vue "Servers". Faire un clic droit sur le serveur Tomcat. Puis sélectionner "Add and remove Projects...".

Sélectionner l'application. Cliquer sur "Add >". Puis, cliquer sur "Finish".

Sélectionner le serveur Tomcat dans la vue "Servers". Faire un clic droit sur le serveur Tomcat. Puis sélectionner "Start".

Ouvrir un navigateur web à l'adresse : http://localhost:8080/MonApplication/pages/bonjour.jsp.

IV-C - Etape 3 : Utilisation de Struts dans la JSP "Bonjour le monde"

L'objectif du chapitre est de modifier l'application avec Struts.

IV-C-1 - Intégration des librairies Struts

Décompresser, selon le fichier téléchargé, les librairies de "struts-1.3.10-all.zip" (version Full Distribution) ou "struts-1.3.10-lib.zip" (version Library) dans "WEB-INF/lib", afin d'obtenir :

IV-C-2 - Création d'un fichier d'internationalisation "Resources.properties"

Faire un clic droit sur "Java Resources: src". Choisir "New"/"Other...".

Déplier "General". Choisir "File". Puis cliquer sur "Next >".

Sélectionner le dossier "src". Saisir "Resources.properties" dans "File name". Puis cliquer sur "Finish".

Remplir le fichier "Resources.properties" (faire CTRL+S pour sauver) avec :

titre.bonjour=Bonjour
libelle.bonjour.lemonde=Bonjour le monde.

IV-C-3 - Création d'un fichier de configuration Struts "struts-config.xml"

Faire un clic droit sur "WebContent"/"WEB-INF". Choisir "New"/"File".

Saisir "struts-config.xml" dans "File name". Puis cliquer sur "Finish".

Cliquer sur l'onglet "Source" de la vue du fichier. Remplir le fichier "struts-config.xml" avec :

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_3.dtd">

<struts-config>

<!-- ========== Ressources de definitions de messages =========================== -->
<message-resources parameter="Resources" />

</struts-config>

IV-C-4 - Modification du fichier "web.xml"

Remplir le fichier "web.xml" contenu dans "WebContent"/"WEB-INF" avec :

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">

<display-name>MonApplication</display-name>

<!-- Configuration de l'action servlet -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

</web-app>

IV-C-5 - Modification de la JSP "bonjour.jsp"

Saisir le code suivant dans "bonjour.jsp" contenu dans "WebContent"/"pages" :

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
<html:html>
<head>
<title><bean:message key="titre.bonjour"/></title>
</head>
<body>
<bean:message key="libelle.bonjour.lemonde"/>
</body>
</html:html>

IV-C-6 - Déploiement de l'application

Le déploiement automatique des ressources qui ne sont pas des JSP met le serveur à l'état "Restart". Si le serveur est à l'état "Restart" (Il faut qu'il soit à l'état "Synchronized") : Sélectionner le serveur Tomcat dans la vue "Servers". Faire un clic droit sur le serveur Tomcat. Puis sélectionner "Restart".

Ouvrir un navigateur web à l'adresse : http://localhost:8080/MonApplication/pages/bonjour.jsp.

IV-D - Fonctionnement de l'ensemble

Au démarrage de l'application, le fichier "web.xml" indique qu'un instance de "org.apache.struts.action.ActionServlet" doit être chargée. Le fichier indique également que l'instance est initialisée avec le fichier de configuration "/WEB-INF/struts-config.xml".

Le fichier de configuration "struts-config.xml" indique que le fichier "Resources.properties" est le fichier de ressource de message par défaut. Le chemin du fichier définit dans "parameter" correspond à son emplacement dans le classpath.

Lors de l'appel de la JSP, les taglibs sont exécutées. Les taglibs "bean:message" affichent le message, contenu dans le fichier de ressources de message par défaut, correspondant à la clé ("key").

V - AFFICHAGE DE DONNEES EN BASE

V-A - Etape 4 : Création de la base de données

V-A-1 - Installation et lancement de HSQLDB

Décompresser le fichier "hsqldb_1_8_0_10.zip" à la racine du disque C.

Lancer le manager de HSQLDB grâce à la commande ""C:\Program Files\Java\jre1.5.0_17\bin\java" -classpath c:\hsqldb\lib\hsqldb.jar org.hsqldb.util.DatabaseManager".

Saisir "maBase" dans "Setting Name", "HSQL Database Engine Standalone" dans "Type", "jdbc:hsqldb:file:C:\hsqldb\data\maBase" dans "URL". Cliquer sur "OK".

V-A-2 - Création de la table "LISTECOURSES"

Saisir la requête :

CREATE TABLE LISTECOURSES(IDOBJET INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY,  LIBELLE VARCHAR, QUANTITE INTEGER);

Cliquer sur "Execute".

Aller dans le menu "View". Cliquer sur "Refresh Tree", afin que la nouvelle table apparaisse dans l'arbre à gauche. Cliquer sur "Execute".

V-A-3 - Insertion des données

Saisir la requête :

INSERT INTO LISTECOURSES(LIBELLE, QUANTITE) VALUES('Banane', 3);
INSERT INTO LISTECOURSES(LIBELLE, QUANTITE) VALUES('Sucre blanc', 75);
INSERT INTO LISTECOURSES(LIBELLE, QUANTITE) VALUES('Oeuf', 1);
INSERT INTO LISTECOURSES(LIBELLE, QUANTITE) VALUES('Levure', 1);
INSERT INTO LISTECOURSES(LIBELLE, QUANTITE) VALUES('Sel', 1);
INSERT INTO LISTECOURSES(LIBELLE, QUANTITE) VALUES('Farine', 150);
INSERT INTO LISTECOURSES(LIBELLE, QUANTITE) VALUES('Beurre', 70);

Cliquer sur "Execute".

Aller dans le menu "Options". Cliquer sur "Commit".

Fermer le manager HSQLDB.

V-A-4 - Vérification

Lancer le manager de HSQLDB grâce à la commande "C:\Program Files\Java\jre1.5.0_16\bin\java" -classpath c:\hsqldb\lib\hsqldb.jar org.hsqldb.util.DatabaseManager".

Choisir "maBase" dans "Recent". Cliquer sur "OK".

Saisir la requête :

SELECT * FROM LISTECOURSES;

Cliquer sur "Execute".

V-B - Etape 5 : Développement de l'affichage

V-B-1 - Déclaration de la ressource dans "web.xml"

Ajouter la déclaration de l'utilisation par l'application de la ressource dans le fichier "web.xml".

<!-- Action Servlet Mapping -->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

<!-- Declaration de l'utilisation de la ressource JDBC -->
<resource-ref>
<description>Ressource JDBC de l'application</description>
<res-ref-name>jdbc/dsMonApplication</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

V-B-2 - Création de la classe de bean

Faire clic droit sur "Java Resources: src". Choisir "New"/"Class".

Saisir "com.developpez.rpouiller.monapplication" dans "Package", "ElementCourseBean" dans "Name". Cliquer sur "Finish".

Saisir le code suivant pour le bean.

package com.developpez.rpouiller.monapplication;

import java.io.Serializable;

public class ElementCourseBean implements Serializable {

private static final long serialVersionUID = 58409687792501803L;

private Long idObjet;
private String libelle;
private Integer quantite;

public Long getIdObjet() {
return idObjet;
}

public void setIdObjet(Long idObjet) {
this.idObjet = idObjet;
}

public String getLibelle() {
return libelle;
}

public void setLibelle(String libelle) {
this.libelle = libelle;
}

public Integer getQuantite() {
return quantite;
}

public void setQuantite(Integer quantite) {
this.quantite = quantite;
}
}

V-B-3 - Création de la classe de bean de retour de la DAO

Créer une classe "RetourRechercherBean" dans le package "com.developpez.rpouiller.monapplication".

Saisir le code suivant pour le bean.

package com.developpez.rpouiller.monapplication;

import java.io.Serializable;
import java.util.List;

public class RetourRechercherBean implements Serializable {

private static final long serialVersionUID = 1050432583446929484L;

private String erreur;
private List<ElementCourseBean> listeCourses;

public String getErreur() {
return erreur;
}

public void setErreur(String erreur) {
this.erreur = erreur;
}

public List<ElementCourseBean> getListeCourses() {
return listeCourses;
}

public void setListeCourses(List<ElementCourseBean> listeCourses) {
this.listeCourses = listeCourses;
}
}

V-B-4 - Création de la classe DAO accédant à la base de données

Créer une classe "ListeCoursesDAO" dans le package "com.developpez.rpouiller.monapplication".

Saisir le code suivant pour la DAO.

package com.developpez.rpouiller.monapplication;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class ListeCoursesDAO {

private final static String NOM_RESOURCE_JDBC = "java:comp/env/jdbc/dsMonApplication";

/**
* Retourne la liste des courses stockées dans la base.
* @return La liste des courses/erreurs.
*/
public RetourRechercherBean rechercherElementsCourses() {
final RetourRechercherBean lRetourRechercher = new RetourRechercherBean();

try {
final Context lContext = new InitialContext();
final DataSource lDataSource = (DataSource) lContext.lookup(NOM_RESOURCE_JDBC);

final List<ElementCourseBean> lListeCourses = new LinkedList<ElementCourseBean>();

final Connection lConnection  = lDataSource.getConnection();
final Statement lStatement = lConnection.createStatement();
final ResultSet lResultSet = lStatement.executeQuery("SELECT * FROM LISTECOURSES");

while (lResultSet.next()) {
final ElementCourseBean lElementCourse = new ElementCourseBean();

final Long lIdObjet = lResultSet.getLong("IDOBJET");
final String lLibelle = lResultSet.getString("LIBELLE");
final Integer lQuantite = lResultSet.getInt("QUANTITE");

lElementCourse.setIdObjet(lIdObjet);
lElementCourse.setLibelle(lLibelle);
lElementCourse.setQuantite(lQuantite);

lListeCourses.add(lElementCourse);
}

lRetourRechercher.setListeCourses(lListeCourses);
} catch (NamingException e) {
// Trace l'erreur dans la log du serveur
e.printStackTrace();
// Stocke l'erreur dans le retour
lRetourRechercher.setErreur("NamingException : " + e.getMessage());
} catch (SQLException e) {
// Trace l'erreur dans la log du serveur
e.printStackTrace();
// Stocke l'erreur dans le retour
lRetourRechercher.setErreur("SQLException : " + e.getMessage());
}

return lRetourRechercher;
}
}

V-B-5 - Création de la classe Action d'affichage

Créer une classe "AfficherListeCoursesAction" dans le package "com.developpez.rpouiller.monapplication".

Saisir le code suivant pour l'action.

package com.developpez.rpouiller.monapplication;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.Globals;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

public class AfficherListeCoursesAction extends Action {

public ActionForward execute(final ActionMapping pMapping,
ActionForm pForm, final HttpServletRequest pRequete,
final HttpServletResponse pReponse) {

// Récupère les informations dans la base
final ListeCoursesDAO lListeCoursesDAO = new ListeCoursesDAO();
final RetourRechercherBean lRetourRechercher = lListeCoursesDAO.rechercherElementsCourses();

if(lRetourRechercher.getErreur() == null) {
// Stocke les informations dans la requête
pRequete.setAttribute("LISTE_COURSES", lRetourRechercher.getListeCourses());
// S'il n'y a pas d'erreurs, on retourne le forward "succes"
return pMapping.findForward("succes");
}
else {
final ActionMessages lErreurs = getErrors(pRequete);
final ActionMessage lActionMessage = new ActionMessage(lRetourRechercher.getErreur(), false);
lErreurs.add(Globals.ERROR_KEY, lActionMessage);
saveErrors(pRequete, lErreurs);
// S'il y a des erreurs, on retourne le forward "erreur"
return pMapping.findForward("erreur");
}
}
}

V-B-6 - Création de la JSP d'affichage de la liste de courses

Créer une nouvelle JSP "listeCourses.jsp" dans "pages".

Saisir le code suivant pour la JSP.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
<%@ taglib prefix="logic" uri="http://struts.apache.org/tags-logic" %>
<html:html>
<head>
<title><bean:message key="titre.listecourses"/></title>
</head>
<body>
<table border="1">
<thead>
<tr>
<th><bean:message key="colonne.identifiant"/></th>
<th><bean:message key="colonne.libelle"/></th>
<th><bean:message key="colonne.quantite"/></th>
</tr>
</thead>
<tbody>
<logic:iterate id="elementCourse" name="LISTE_COURSES" type="com.developpez.rpouiller.monapplication.ElementCourseBean">
<tr>
<td><bean:write name="elementCourse" property="idObjet"/></td>
<td><bean:write name="elementCourse" property="libelle"/></td>
<td><bean:write name="elementCourse" property="quantite"/></td>
</tr>
</logic:iterate>
</tbody>
</table>
</body>
</html:html>

V-B-7 - Création de la JSP d'erreur

Créer une nouvelle JSP "erreur.jsp" dans "pages".

Saisir le code suivant pour la JSP.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
<html:html>
<head>
<title><bean:message key="titre.erreur"/></title>
</head>
<body>
<html:errors/><br/>
</body>
</html:html>

V-B-8 - Modification du fichier d'internationalisation

Ajouter les lignes suivantes dans le fichier "Resources.properties".

titre.listecourses=Liste de courses
colonne.identifiant=IDOBJET
colonne.libelle=LIBELLE
colonne.quantite=QUANTITE

titre.erreur=Erreur

V-B-9 - Modification du fichier de configuration "struts-config.xml"

Ajouter les lignes suivantes dans le fichier "struts-config.xml" (les lignes doivent être avant la déclaration du fichier d'internationalisation).

<!-- ========== Mapping des actions ============================== -->
<action-mappings>

<!-- Indique la correspondance entre une action sous forme d'URL (ici /AfficherListeCourses.do),
une classe (ici com.developpez.rpouiller.monapplication.AfficherListeCoursesAction) -->
<action    path      = "/AfficherListeCourses"
type      = "com.developpez.rpouiller.monapplication.AfficherListeCoursesAction">

<forward name="succes" path="/pages/listeCourses.jsp"  />
<forward name="erreur" path="/pages/erreur.jsp"  />
</action>
</action-mappings>

V-C - Etape 6 : Configuration de Tomcat

V-C-1 - Déclaration de la ressource JDBC dans le serveur

Ouvrir le fichier "server.xml" du serveur Tomcat (paramétrage accessible depuis Eclipse).

Ajouter la déclaration de la ressource JNDI dans les ressources globales (partie "GlobalNamingResources").

<Resource auth="Container" driverClassName="org.hsqldb.jdbcDriver"
maxActive="100" maxIdle="30" maxWait="10000" name="jdbc/dsMaBase"
password="" type="javax.sql.DataSource" url="jdbc:hsqldb:file:C:\hsqldb\data\maBase"
username="sa" />

V-C-2 - Déclaration du lien de la ressource

Ouvrir le fichier "context.xml" du serveur Tomcat (paramétrage accessible depuis Eclipse).

Ajouter la déclaration du lien entre de la ressource globale et la déclaration dans l'application.

<ResourceLink name="jdbc/dsMonApplication" global="jdbc/dsMaBase"
type="javax.sql.DataSource" />

V-C-3 - Copie de la librairie HSQLDB dans les librairies Tomcat

Copier la librairie "hsqldb.jar" depuis le zip "hsqldb_1_8_0_10.zip" dans les librairies de Tomcat ("C:\Program Files\Apache Software Foundation\Tomcat 6.0\lib").

V-C-4 - Déploiement de l'application

Si le serveur est à l'état "Restart" (Il faut qu'il soit à l'état "Synchronized") : Sélectionner le serveur Tomcat dans la vue "Servers". Faire un clic droit sur le serveur Tomcat. Puis sélectionner "Restart".

Ouvrir un navigateur web à l'adresse : http://localhost:8080/MonApplication/AfficherListeCourses.do.

Si l'application est en erreur, comme dans l'image. Il faut redémarrer Eclipse. Et une fois Eclipse redémarré, redémarrer le serveur Tomcat.

V-D - Fonctionnement de l'ensemble

Au démarrage du serveur Tomcat, le fichier "server.xml" déclare une ressource JDBC globale avec ses paramètres de connexion.

Le fichier "context.xml" définit un mappage entre une ressource JDBC déclarée dans une application et la ressource JDBC globale.

Au démarrage de l'application, le fichier "web.xml" indique que les urls finissant par ".do" sont mappées vers la servlet "org.apache.struts.action.ActionServlet". Le fichier indique également que l'application utilise la ressource JDBC "jdbc/dsMonApplication"

Le fichier de configuration "struts-config.xml" déclare une action "com.developpez.rpouiller.monapplication.AfficherListeCoursesAction". Cette action peut être suivie lors de son exécution de deux JSP ("/pages/listeCourses.jsp" ou "/pages/erreur.jsp") selon la direction décidée dans l'action.

Lors de l'appel "http://localhost:8080/MonApplication/AfficherListeCourses.do", la servlet "org.apache.struts.action.ActionServlet" est exécutée (url terminée par ".do"). Elle utilise le mapping des actions contenues dans "struts-config.xml", pour appeler l'action "com.developpez.rpouiller.monapplication.AfficherListeCoursesAction".

L'action appelle la DAO afin d'obtenir la liste des enregistrements contenus en base. Elle stocke la liste des enregistrements dans la "requête". Si tout s'est bien passé, elle demande de forwarder vers le mapping "succes" ("/pages/listeCourses.jsp"). Ou en cas d'erreur, elle demande de forwarder vers le mapping "erreur" ("/pages/erreur.jsp").

La DAO "ListeCoursesDAO" utilise la ressource JDBC pour accéder à la base. Elle fournit une méthode retournant les informations contenues dans la table "LISTECOURSES".

La JSP "/pages/listeCourses.jsp" affiche un tableau avec les valeurs contenues dans la requête. Le tag "logic:iterate" effectue une boucle sur les élément de la liste des courses qui a été stockée dans la requête sous le nom "LISTE_COURSES". A chaque itération, l'élément courant de la liste possède le nom "elementCourse" et est de classe "com.developpez.rpouiller.monapplication.ElementCourseBean". Chaque tag "bean:write" affiche une propriété (property) de l'élément courant.

La JSP "/pages/erreur.jsp" affiche les erreurs stockées dans la requête. Le tag "html:errors" affiche les erreurs qui ont été ajoutées dans la requête par la classe d'affichage.

VI - CREATION DE DONNEES EN BASE

VI-A - Etape 7 : Création d'enregistrements dans la base de données

VI-A-1 - Modification de la classe DAO

Ajouter la méthode "creerElementCourse" dans la classe "ListeCoursesDAO".

/**
* Crée un nouvel élément dans la liste des courses
* @param pLibelle Libellé du nouvel élément
* @param pQuantite Quantité du nouvel élément
* @return Erreur s'il y a lieu
*/
public String creerElementCourse(final String pLibelle, final Integer pQuantite) {
try {
final Context lContext = new InitialContext();
final DataSource lDataSource = (DataSource) lContext.lookup(NOM_RESOURCE_JDBC);
final Connection lConnection  = lDataSource.getConnection();

// Insertion du nouvel enregistrement
final PreparedStatement lPreparedStatementCreation =
lConnection.prepareStatement("INSERT INTO LISTECOURSES(LIBELLE, QUANTITE) VALUES(?, ?)");
lPreparedStatementCreation.setString(1, pLibelle);
lPreparedStatementCreation.setInt(2, pQuantite);
lPreparedStatementCreation.executeUpdate();

return null;
} catch (NamingException e) {
return "NamingException : " + e.getMessage();
} catch (SQLException e) {
return "SQLException : " + e.getMessage();
}
}

Faire un clic droit dans le source. Choisir "Source"/"Organize Imports".

VI-A-2 - Création de la classe Action de création

Créer une classe "CreerElementCoursesAction" dans le package "com.developpez.rpouiller.monapplication".

Saisir le code suivant pour l'action.

package com.developpez.rpouiller.monapplication;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.Globals;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.validator.DynaValidatorActionForm;

public class CreerElementCoursesAction extends Action {

public ActionForward execute(final ActionMapping pMapping,
ActionForm pForm, final HttpServletRequest pRequete,
final HttpServletResponse pReponse) {

// Récupère les informations du formulaire
final DynaValidatorActionForm lForm = (DynaValidatorActionForm)pForm;
final String lLibelle = lForm.getString("libelle");
final Integer lQuantite = new Integer(lForm.getString("quantite"));

// Création en base du nouvel enregistrement
final ListeCoursesDAO lListeCoursesDAO = new ListeCoursesDAO();
final String lErreur = lListeCoursesDAO.creerElementCourse(lLibelle, lQuantite);

if(lErreur == null) {
// S'il n'y a pas d'erreurs, on retourne le forward "succes"
return pMapping.findForward("succes");
}
else {
final ActionMessages lErreurs = getErrors(pRequete);
final ActionMessage lActionMessage = new ActionMessage(lErreur, false);
lErreurs.add(Globals.ERROR_KEY, lActionMessage);
saveErrors(pRequete, lErreurs);
// S'il y a des erreurs, on retourne le forward "erreur"
return pMapping.findForward("erreur");
}
}
}

VI-A-3 - Création d'un nouveau fichier d'internationalisation

Créer un nouveau fichier d'internationalisation dans le dossier "src"/"com"/"developpez"/"rpouiller"/"monapplication" sous le nom "ResourcesCreation.properties".

Remplir le fichier "ResourcesCreation.properties" avec :

titre.creation.elementcourses=Création d'élément de la liste de courses
creation.elementcourses.libelle.libelle=Libellé
creation.elementcourses.libelle.quantite=Quantité

creation.libelle.error.required=Le libellé est nécessaire.
creation.quantité.error.required=La quantité est nécessaire.
creation.quantité.error.integer=La quantité doit être numérique.

VI-A-4 - Création d'un nouveau fichier de configuration "struts-config-creation.xml"

Créer un fichier XML "struts-config-creation.xml" dans "WebContent/WEB-INF".

Remplir le fichier "struts-config-creation.xml" avec :

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_3.dtd">

<struts-config>

<!-- ========== Formulaire ============================== -->
<form-beans>
<form-bean name="creationForm" type="org.apache.struts.validator.DynaValidatorActionForm">

<form-property name="libelle"     type="java.lang.String" />
<form-property name="quantite"     type="java.lang.String" />

</form-bean>
</form-beans>

<!-- ========== Mapping des actions ============================== -->
<action-mappings>

<action    path      = "/AfficherCreationElementCourses"
name      = "creationForm"
type      = "com.developpez.rpouiller.monapplication.AfficherListeCoursesAction"
scope     = "request"
validate  = "false"
attribute = "bean">

<forward name="succes" path="/pages/creation.jsp"  />
<forward name="erreur" path="/pages/erreur.jsp"  />
</action>

<action    path      = "/CreerCreationElementCourses"
name      = "creationForm"
type      = "com.developpez.rpouiller.monapplication.CreerElementCoursesAction"
scope     = "request"
validate  = "true"
attribute = "bean"
input     = "/AfficherCreationElementCourses.do">

<forward name="succes" path="/AfficherCreationElementCourses.do"  />
<forward name="erreur" path="/pages/erreur.jsp"  />
</action>
</action-mappings>

<!-- ========== Ressources de definitions de messages =========================== -->
<message-resources parameter="com.developpez.rpouiller.monapplication.ResourcesCreation" key="creation" />

</struts-config>

VI-A-5 - Modification du fichier "web.xml"

Modidier la déclaration du paramétrage de la servlet "org.apache.struts.action.ActionServlet" dans le fichier "web.xml".

<!-- Configuration de l'action servlet -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>
/WEB-INF/struts-config.xml,
/WEB-INF/struts-config-creation.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

VI-A-6 - Création de la JSP de création

Créer une JSP "creation.jsp" dans "pages".

Remplir "creation.jsp" avec :

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
<%@ taglib prefix="logic" uri="http://struts.apache.org/tags-logic" %>
<%@ taglib prefix="nested" uri="http://struts.apache.org/tags-nested" %>
<html:html>
<head>
<title><bean:message key="titre.creation.elementcourses" bundle="creation"/></title>
</head>
<body>
<b><i><html:errors/></i></b><br/>
<html:form action="/CreerCreationElementCourses.do">
<bean:message key="creation.elementcourses.libelle.libelle" bundle="creation"/>
<nested:text property="libelle"/><br>
<bean:message key="creation.elementcourses.libelle.quantite" bundle="creation"/>
<nested:text property="quantite"/><br>
<html:submit/>
</html:form>
<table border="1">
<thead>
<tr>
<th><bean:message key="colonne.identifiant"/></th>
<th><bean:message key="colonne.libelle"/></th>
<th><bean:message key="colonne.quantite"/></th>
</tr>
</thead>
<tbody>
<logic:iterate id="elementCourse" name="LISTE_COURSES" type="com.developpez.rpouiller.monapplication.ElementCourseBean">
<tr>
<td><bean:write name="elementCourse" property="idObjet"/></td>
<td><bean:write name="elementCourse" property="libelle"/></td>
<td><bean:write name="elementCourse" property="quantite"/></td>
</tr>
</logic:iterate>
</tbody>
</table>
</body>
</html:html>

VI-A-7 - Création du fichier de validation "validation-creation.xml"

Créer un fichier XML "validation-creation.xml" dans "WebContent/WEB-INF".

Remplir le fichier avec :

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE form-validation PUBLIC
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
"http://jakarta.apache.org/commons/dtds/validator_1_3_0.dtd">

<form-validation>

<formset>
<form name="/CreerCreationElementCourses">
<!-- Contraintes sur le champ libelle : obligatoire -->
<field property="libelle" depends="required">
<msg name="required" key="creation.libelle.error.required" bundle="creation"/>
</field>
<!-- Contraintes sur le champ quantite : obligatoire et numerique -->
<field property="quantite" depends="required, integer">
<msg name="required" key="creation.quantité.error.required" bundle="creation"/>
<msg name="integer" key="creation.quantité.error.integer" bundle="creation"/>
</field>
</form>
</formset>

</form-validation>

VI-A-8 - Modification du fichier de configuration "struts-config.xml"

Rajouter la déclaration des validations dans "struts-config.xml" après la déclaration des ressources de messages :

<!-- ========== Validation des formulaires =========================== -->
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/org/apache/struts/validator/validator-rules.xml,
/WEB-INF/validation-creation.xml" />
</plug-in>

VI-A-9 - Déploiement de l'application

Si le serveur est à l'état "Restart" (Il faut qu'il soit à l'état "Synchronized") : Sélectionner le serveur Tomcat dans la vue "Servers". Faire un clic droit sur le serveur Tomcat. Puis sélectionner "Restart".

Ouvrir un navigateur web à l'adresse : http://localhost:8080/MonApplication/AfficherCreationElementCourses.do.

VI-A-11 - Vérification

L'application doit vérifier que les champs "libelle" et "quantite" sont renseignés.

L'application doit vérifier que le champ "quantite" est bien numérique.

L'application doit stocker le nouvel enregistrement et l'afficher ensuite.

VI-B - Fonctionnement de l'ensemble

Au démarrage de l'application, la modification du fichier "web.xml" indique que la servlet "org.apache.struts.action.ActionServlet" est initialisée par deux fichiers de configuration.

La modification effectuée dans "struts-config.xml" indique les fichiers de validation de formulaire. Le fichier "validator-rules.xml" est contenue dans la librairie "struts-core-1.3.8.jar". Le chemin correspond au chemin dans le classpath.

Le fichier "validation-creation.xml" indique les conditions de validation du formulaire (champs obligatoires, numériques, etc...) et les messages correspondants aux erreurs de validation.

Le fichier "struts-config-creation.xml" déclare deux actions (une d'affichage et une de création) et un formulaire. Ces deux actions ont le même formulaire. Mais, seule l'action de création nécessite une validation du formulaire.

Lors de l'appel "http://localhost:8080/MonApplication/AfficherCreationElementCourses.do", la servlet "org.apache.struts.action.ActionServlet" est exécutée (url terminée par ".do"). Elle utilise le mapping des actions contenues dans "struts-config-creation.xml", pour appeler l'action "com.developpez.rpouiller.monapplication.AfficherListeCoursesAction".

L'action appelle la DAO afin d'obtenir la liste des enregistrements contenus en base. Elle stocke la liste des enregistrements dans la "requête". Si tout s'est bien passé, elle demande de forwarder vers le mapping "succes" ("/pages/creation.jsp"). Ou en cas d'erreur, elle demande de forwarder vers le mapping "erreur" ("/pages/erreur.jsp").

La DAO "ListeCoursesDAO" utilise la ressource JDBC pour accéder à la base. Elle fournit une méthode retournant les informations contenues dans la table "LISTECOURSES".

La JSP "/pages/creation.jsp" affiche un formulaire de création et un tableau avec les valeurs contenues dans la requête. Le tag "nested:text" permet de saisir une propriété du formulaire (déclarée dans le fichier "struts-config-creation.xml"). Le tag "html:submit" correspond au bouton "Submit".

La JSP "/pages/erreur.jsp" affiche les erreurs stockées dans la requête.

Lors du clic sur le bouton "Submit", le formulaire est soumis au serveur Tomcat.

Le formulaire est tout d'abord validé par les critères définis dans "validation-creation.xml". Les deux champs sont indiqués obligatoires ("required") et le champ "quantite" est également indiqué numérique ("integer").

En cas d'erreur dans la validation, les messages d'erreur sont stockés dans la requête et l'application forwarde vers l'action d'affichage, soit celle spécifiée dans l'attribut input du mapping.

En cas de validation réussie, l'action de création "com.developpez.rpouiller.monapplication.CreerElementCoursesAction" est exécutée. Elle récupère le libellé et la quantité depuis le formulaire. Elle demande à la DAO de créer un nouvel enregistrement. Si tout s'est bien passé, elle demande de forwarder vers le mapping "succes" (action d'affichage). Ou en cas d'erreur, elle demande de forwarder vers le mapping "erreur" ("/pages/erreur.jsp").

La méthode "creerElementCourse" de la DAO "ListeCoursesDAO" crée un nouvel enregistrement dans la table "LISTECOURSES".

VII - SUPPRESSION DE DONNEES EN BASE

VII-A - Etape 8 : Suppression d'enregistrements dans la base de données

VII-A-1 - Modification de la classe DAO

Ajouter la méthode "supprimerElementCourse" dans la classe "ListeCoursesDAO".

/**
* Supprime un nouvel élément dans la liste des courses
* @param pIdObjet Identifiant de l'élément
* @return Erreur s'il y a lieu
*/
public String supprimerElementCourse(final Long pIdObjet) {
try {
final Context lContext = new InitialContext();
final DataSource lDataSource = (DataSource) lContext.lookup(NOM_RESOURCE_JDBC);
final Connection lConnection  = lDataSource.getConnection();

// Insertion du nouvel enregistrement
final PreparedStatement lPreparedStatementCreation =
lConnection.prepareStatement("DELETE FROM LISTECOURSES WHERE IDOBJET = ?");
lPreparedStatementCreation.setLong(1, pIdObjet);
lPreparedStatementCreation.executeUpdate();

return null;
} catch (NamingException e) {
return "NamingException : " + e.getMessage();
} catch (SQLException e) {
return "SQLException : " + e.getMessage();
}
}

VII-A-2 - Création de la classe Action de suppression

Créer une classe "SupprimerElementCoursesAction" dans le package "com.developpez.rpouiller.monapplication".

Saisir le code suivant pour l'action.

package com.developpez.rpouiller.monapplication;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.Globals;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.validator.DynaValidatorActionForm;

public class SupprimerElementCoursesAction extends Action {

public ActionForward execute(final ActionMapping pMapping,
ActionForm pForm, final HttpServletRequest pRequete,
final HttpServletResponse pReponse) {

// Récupère l'identifiant de l'élément dans le formulaire
final DynaValidatorActionForm lForm = (DynaValidatorActionForm)pForm;
final Long lIdObjet = new Long(lForm.getString("idobjet"));

// Suppression en base de l'enregistrement
final ListeCoursesDAO lListeCoursesDAO = new ListeCoursesDAO();
final String lErreur = lListeCoursesDAO.supprimerElementCourse(lIdObjet);

if(lErreur == null) {
// S'il n'y a pas d'erreurs, on retourne le forward "succes"
return pMapping.findForward("succes");
}
else {
final ActionMessages lErreurs = getErrors(pRequete);
final ActionMessage lActionMessage = new ActionMessage(lErreur, false);
lErreurs.add(Globals.ERROR_KEY, lActionMessage);
saveErrors(pRequete, lErreurs);
// S'il y a des erreurs, on retourne le forward "erreur"
return pMapping.findForward("erreur");
}
}
}

VII-A-3 - Création d'un nouveau fichier d'internationalisation

Créer un nouveau fichier d'internationalisation dans le dossier "src"/"com"/"developpez"/"rpouiller"/"monapplication" sous le nom "ResourcesSuppression.properties".

Remplir le fichier "ResourcesSuppression.properties" avec :

titre.suppression.elementcourses=Suppression d'élément de la liste de courses
suppression.supprimer.libelle=Supprimer

VII-A-4 - Création d'un nouveau fichier de configuration "struts-config-suppression.xml"

Créer un fichier XML "struts-config-suppression.xml" dans "WebContent/WEB-INF".

Remplir le fichier "struts-config-suppression.xml" avec :

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_3.dtd">

<struts-config>

<!-- ========== Formulaire ============================== -->
<form-beans>
<form-bean name="suppressionForm" type="org.apache.struts.validator.DynaValidatorActionForm">

<form-property name="idobjet"     type="java.lang.String" />

</form-bean>
</form-beans>

<!-- ========== Mapping des actions ============================== -->
<action-mappings>

<action    path      = "/AfficherSuppressionElementCourses"
name      = "suppressionForm"
type      = "com.developpez.rpouiller.monapplication.AfficherListeCoursesAction"
scope     = "request"
validate  = "false"
attribute = "bean">

<forward name="succes" path="/pages/suppression.jsp"  />
<forward name="erreur" path="/pages/erreur.jsp"  />
</action>

<action    path      = "/SupprimerSuppressionElementCourses"
name      = "suppressionForm"
type      = "com.developpez.rpouiller.monapplication.SupprimerElementCoursesAction"
scope     = "request"
validate  = "false"
attribute = "bean">

<forward name="succes" path="/AfficherSuppressionElementCourses.do"  />
<forward name="erreur" path="/pages/erreur.jsp"  />
</action>
</action-mappings>

<!-- ========== Ressources de definitions de messages =========================== -->
<message-resources parameter="com.developpez.rpouiller.monapplication.ResourcesSuppression" key="suppression" />

</struts-config>

VII-A-5 - Modification du fichier "web.xml"

Modidier la déclaration du paramétrage de la servlet "org.apache.struts.action.ActionServlet" dans le fichier "web.xml".

<!-- Configuration de l'action servlet -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>
/WEB-INF/struts-config.xml,
/WEB-INF/struts-config-creation.xml,
/WEB-INF/struts-config-suppression.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

VII-A-6 - Création de la JSP de suppression

Créer une JSP "suppression.jsp" dans "pages".

Remplir "suppression.jsp" avec :

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
<%@ taglib prefix="logic" uri="http://struts.apache.org/tags-logic" %>
<%@ taglib prefix="nested" uri="http://struts.apache.org/tags-nested" %>
<html:html>
<head>
<title><bean:message key="titre.suppression.elementcourses" bundle="suppression"/></title>
</head>
<body>
<html:form action="/SupprimerSuppressionElementCourses.do">
<nested:hidden styleId="idobjet" property="idobjet"/>
<table border="1">
<thead>
<tr>
<th><bean:message key="colonne.identifiant"/></th>
<th><bean:message key="colonne.libelle"/></th>
<th><bean:message key="colonne.quantite"/></th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
<logic:iterate id="elementCourse" name="LISTE_COURSES" type="com.developpez.rpouiller.monapplication.ElementCourseBean">
<tr>
<bean:define id="idObjet" name="elementCourse" property="idObjet"/>
<td><bean:write name="elementCourse" property="idObjet"/></td>
<td><bean:write name="elementCourse" property="libelle"/></td>
<td><bean:write name="elementCourse" property="quantite"/></td>
<td>
<a href="#" onclick="document.getElementById('idobjet').value = ${idObjet}; document.forms[0].submit();">
<bean:message key="suppression.supprimer.libelle" bundle="suppression"/>
</a>
</td>
</tr>
</logic:iterate>
</tbody>
</table>
</html:form>
</body>
</html:html>

VII-A-7 - Déploiement de l'application

Si le serveur est à l'état "Restart" (Il faut qu'il soit à l'état "Synchronized") : Sélectionner le serveur Tomcat dans la vue "Servers". Faire un clic droit sur le serveur Tomcat. Puis sélectionner "Restart".

Ouvrir un navigateur web à l'adresse : http://localhost:8080/MonApplication/AfficherSuppressionElementCourses.do.

VII-A-8 - Vérification

Lorsque l'on clique sur un "supprimer" (le dernier dans ce cas), l'application doit supprimer un enregistrement et l'afficher ensuite.

VII-B - Fonctionnement de l'ensemble

Au démarrage de l'application, la modification du fichier "web.xml" indique que la servlet "org.apache.struts.action.ActionServlet" est initialisée par trois fichiers de configuration.

Le fichier "struts-config-suppression.xml" déclare deux actions (une d'affichage et une de suppression) et un formulaire. Ces deux actions ont le même formulaire.

Lors de l'appel "http://localhost:8080/MonApplication/AfficherSuppressionElementCourses.do", la servlet "org.apache.struts.action.ActionServlet" est exécutée (url terminée par ".do"). Elle utilise le mapping des actions contenues dans "struts-config-suppression.xml", pour appeler l'action "com.developpez.rpouiller.monapplication.AfficherListeCoursesAction".

L'action appelle la DAO afin d'obtenir la liste des enregistrements contenus en base. Elle stocke la liste des enregistrements dans la "requête". Si tout s'est bien passé, elle demande de forwarder vers le mapping "succes" ("/pages/suppression.jsp"). Ou en cas d'erreur, elle demande de forwarder vers le mapping "erreur" ("/pages/erreur.jsp").

La DAO "ListeCoursesDAO" utilise la ressource JDBC pour accéder à la base. Elle fournit une méthode retournant les informations contenues dans la table "LISTECOURSES".

La JSP "/pages/suppression.jsp" affiche un tableau avec les valeurs contenues dans la requête. Chaque ligne du tableau comporte un lien de suppression de l'objet. Ce lien exécute du Javascript qui stocke l'identifiant de l'objet à supprimer dans un champ caché ("nested:hidden"), puis soumet le formulaire.

La JSP "/pages/erreur.jsp" affiche les erreurs stockées dans la requête.

Lors du clic sur le lien "Supprimer", le Javascript associé au lien est exécuté. Un champ du formulaire est mis à jour avec la valeur de l'identifiant de l'objet de la ligne et le formulaire est soumis au serveur Tomcat.

L'action de suppression "com.developpez.rpouiller.monapplication.SupprimerElementCoursesAction" est exécutée. Elle récupère l'identifiant depuis le formulaire. Elle demande à la DAO de supprimer l'enregistrement correspondant. Si tout s'est bien passé, elle demande de forwarder vers le mapping "succes" (action d'affichage). Ou en cas d'erreur, elle demande de forwarder vers le mapping "erreur" ("/pages/erreur.jsp").

La méthode "supprimerElementCourse" de la DAO "ListeCoursesDAO" supprime l'enregistrement dans la table "LISTECOURSES" avec l'identifiant passé en paramètre.

VIII - MODIFICATION DE DONNEES EN BASE

VIII-A - Etape 9 : Modification d'enregistrements dans la base de données

VIII-A-1 - Intégration de la librairie Commons Collections

Décompresser la librairie "commons-collections-3.2.1.jar" de "commons-collections-3.2.1-bin.zip" dans "WEB-INF/lib", afin d'obtenir :

VIII-A-2 - Création de la classe de bean

Créer une classe "ModifElementCourseBean" dans le package "com.developpez.rpouiller.monapplication".

Saisir le code suivant pour le bean.

package com.developpez.rpouiller.monapplication;

import java.io.Serializable;

public class ModifElementCourseBean implements Serializable {

private static final long serialVersionUID = 58409687792501803L;

private Long idObjet;
private String libelle;
private String quantite;

public Long getIdObjet() {
return idObjet;
}

public void setIdObjet(Long idObjet) {
this.idObjet = idObjet;
}

public String getLibelle() {
return libelle;
}

public void setLibelle(String libelle) {
this.libelle = libelle;
}

public String getQuantite() {
return quantite;
}

public void setQuantite(String quantite) {
this.quantite = quantite;
}
}

VIII-A-3 - Modification de la classe DAO

Ajouter la méthode "modifierElementsCourse" dans la classe "ListeCoursesDAO".

/**
* Modifie la liste des éléments passée en paramètre (modification de la quantité seulement)
* @param pListeElements Liste des éléments à modifier
* @return Erreur s'il y a lieu
*/
public String modifierElementsCourse(final List<ModifElementCourseBean> pListeElements) {
try {
final Context lContext = new InitialContext();
final DataSource lDataSource = (DataSource) lContext.lookup(NOM_RESOURCE_JDBC);
final Connection lConnection  = lDataSource.getConnection();

// Modification des enregistrements
for (final ModifElementCourseBean lElement  : pListeElements) {
final PreparedStatement lPreparedStatementCreation =
lConnection.prepareStatement("UPDATE LISTECOURSES SET QUANTITE = ? WHERE IDOBJET = ?");
lPreparedStatementCreation.setInt(1, new Integer(lElement.getQuantite()));
lPreparedStatementCreation.setLong(2, lElement.getIdObjet());
lPreparedStatementCreation.executeUpdate();
}

return null;
} catch (NamingException e) {
return "NamingException : " + e.getMessage();
} catch (SQLException e) {
return "SQLException : " + e.getMessage();
}
}

VIII-A-4 - Création de la classe de formulaire

Créer une classe "ModificationListeCoursesForm" dans le package "com.developpez.rpouiller.monapplication".

Saisir le code suivant pour l'action.

package com.developpez.rpouiller.monapplication;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.Factory;
import org.apache.commons.collections.list.LazyList;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.validator.DynaValidatorActionForm;

public class ModificationListeCoursesForm extends DynaValidatorActionForm {

private static final long serialVersionUID = -8922507342446865665L;

private static ModifElementCourseFactory FACTORY_INSTANCE = new ModifElementCourseFactory();

private static class ModifElementCourseFactory implements Factory {
public Object create() {
return new ModifElementCourseBean();
}
}

@Override
public void reset(ActionMapping pMapping, HttpServletRequest pRequete) {
super.reset(pMapping, pRequete);

final List<ModifElementCourseBean> lListeModification = new LinkedList<ModifElementCourseBean>();
final List<ModifElementCourseBean> lListeModificationLazy = LazyList.decorate(lListeModification, FACTORY_INSTANCE);

set("listeCourses", lListeModificationLazy);
}

@Override
public ActionErrors validate(ActionMapping pMapping, HttpServletRequest pRequete) {
final ActionErrors lActionErrors = super.validate(pMapping, pRequete);

final List<ModifElementCourseBean> lListeModifElementsCourse = (List<ModifElementCourseBean>)get("listeCourses");
final Iterator<ModifElementCourseBean> lIteratorModifElementsCourse = lListeModifElementsCourse.iterator();
while(lIteratorModifElementsCourse.hasNext()) {
final ModifElementCourseBean lElementCourse = lIteratorModifElementsCourse.next();

final Long lIdObjet = lElementCourse.getIdObjet();
final String lQuantite = lElementCourse.getQuantite();

if(lQuantite == null || "".equals(lQuantite)) {
final ActionMessage lActionMessage = new ActionMessage("modification.quantite.nonrenseigne.erreur", lIdObjet);
lActionErrors.add(Globals.ERROR_KEY, lActionMessage);
}
else {
try {
final Integer lQuantiteInt = new Integer(lQuantite);

if(lQuantiteInt <= 0 ) {
final ActionMessage lActionMessage = new ActionMessage("modification.quantite.nonpositif.erreur", lIdObjet);
lActionErrors.add(Globals.ERROR_KEY, lActionMessage);
}
} catch (NumberFormatException e) {
final ActionMessage lActionMessage = new ActionMessage("modification.quantite.nonnumerique.erreur", lIdObjet);
lActionErrors.add(Globals.ERROR_KEY, lActionMessage);
}
}
}

return lActionErrors;
}

}

VIII-A-5 - Modification du fichier d'internationalisation

Ajouter les lignes suivantes dans le fichier "Resources.properties".

modification.quantite.nonrenseigne.erreur=La quantité de l'objet avec l'id {0} n'est pas renseigné.
modification.quantite.nonnumerique.erreur=La quantité de l'objet avec l'id {0} n'est pas au format numérique.
modification.quantite.nonpositif.erreur=La quantité de l'objet avec l'id {0} n'est pas strictement positif.

VIII-A-6 - Création de la classe Action d'affichage

Créer une classe "AfficherModificationListeCoursesAction" dans le package "com.developpez.rpouiller.monapplication".

Saisir le code suivant pour l'action.

package com.developpez.rpouiller.monapplication;

import java.util.LinkedList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.Globals;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

public class AfficherModificationListeCoursesAction extends Action {

public ActionForward execute(final ActionMapping pMapping,
ActionForm pForm, final HttpServletRequest pRequete,
final HttpServletResponse pReponse) {

// Récupère les informations dans la base
final ListeCoursesDAO lListeCoursesDAO = new ListeCoursesDAO();
final RetourRechercherBean lRetourRechercher = lListeCoursesDAO.rechercherElementsCourses();

// Transforme la liste de bean ElementCourseBean en ModifElementCourseBean
final List<ModifElementCourseBean> lListeCoursesConvertie = new LinkedList<ModifElementCourseBean>();
for(final ElementCourseBean lElementCourse : lRetourRechercher.getListeCourses()) {
final ModifElementCourseBean lModifElementCourse = new ModifElementCourseBean();
lModifElementCourse.setIdObjet(lElementCourse.getIdObjet());
lModifElementCourse.setLibelle(lElementCourse.getLibelle());
lModifElementCourse.setQuantite(lElementCourse.getQuantite().toString());
lListeCoursesConvertie.add(lModifElementCourse);
}

// Stocke les informations dans le formulaire
final ModificationListeCoursesForm lForm = (ModificationListeCoursesForm)pForm;
lForm.set("listeCourses", lListeCoursesConvertie);

if(lRetourRechercher.getErreur() == null) {
// S'il n'y a pas d'erreurs, on retourne le forward "succes"
return pMapping.findForward("succes");
}
else {
final ActionMessages lErreurs = getErrors(pRequete);
final ActionMessage lActionMessage = new ActionMessage(lRetourRechercher.getErreur(), false);
lErreurs.add(Globals.ERROR_KEY, lActionMessage);
saveErrors(pRequete, lErreurs);
// S'il y a des erreurs, on retourne le forward "erreur"
return pMapping.findForward("erreur");
}
}
}

VIII-A-7 - Création de la classe Action de modification

Créer une classe "ModifierModificationListeCoursesAction" dans le package "com.developpez.rpouiller.monapplication".

Saisir le code suivant pour l'action.

package com.developpez.rpouiller.monapplication;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.Globals;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

public class ModifierModificationListeCoursesAction extends Action {

public ActionForward execute(final ActionMapping pMapping,
ActionForm pForm, final HttpServletRequest pRequete,
final HttpServletResponse pReponse) {

// Récupère les informations du formulaire
final ModificationListeCoursesForm lForm = (ModificationListeCoursesForm)pForm;
final List<ModifElementCourseBean> lListeCourses = (List<ModifElementCourseBean>)lForm.get("listeCourses");

// Création en base du nouvel enregistrement
final ListeCoursesDAO lListeCoursesDAO = new ListeCoursesDAO();
final String lErreur = lListeCoursesDAO.modifierElementsCourse(lListeCourses);

if(lErreur == null) {
// S'il n'y a pas d'erreurs, on retourne le forward "succes"
return pMapping.findForward("succes");
}
else {
final ActionMessages lErreurs = getErrors(pRequete);
final ActionMessage lActionMessage = new ActionMessage(lErreur, false);
lErreurs.add(Globals.ERROR_KEY, lActionMessage);
saveErrors(pRequete, lErreurs);
// S'il y a des erreurs, on retourne le forward "erreur"
return pMapping.findForward("erreur");
}
}
}

VIII-A-8 - Création du fichier d'internationalisation

Créer un nouveau fichier d'internationalisation dans le dossier "src"/"com"/"developpez"/"rpouiller"/"monapplication" sous le nom "ResourcesModification.properties".

Remplir le fichier "ResourcesModification.properties" avec :

titre.modification.elementcourses=Modification d'élément de la liste de courses

VIII-A-9 - Création du fichier de configuration "struts-config-modification.xml"

Créer un fichier XML "struts-config-modification.xml" dans "WebContent/WEB-INF".

Remplir le fichier "struts-config-modification.xml" avec :

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_3.dtd">

<struts-config>

<!-- ========== Formulaire ============================== -->
<form-beans>
<form-bean name="modificationForm" type="com.developpez.rpouiller.monapplication.ModificationListeCoursesForm">

<form-property name="listeCourses"     type="java.util.List" />

</form-bean>
</form-beans>

<!-- ========== Mapping des actions ============================== -->
<action-mappings>

<action    path      = "/AfficherModificationListeCourses"
name      = "modificationForm"
type      = "com.developpez.rpouiller.monapplication.AfficherModificationListeCoursesAction"
scope     = "request"
validate  = "false"
attribute = "bean">

<forward name="succes" path="/pages/modification.jsp"  />
<forward name="erreur" path="/pages/erreur.jsp"  />
</action>

<action    path      = "/ModifierModificationListeCourses"
name      = "modificationForm"
type      = "com.developpez.rpouiller.monapplication.ModifierModificationListeCoursesAction"
scope     = "request"
validate  = "true"
attribute = "bean"
input     = "/pages/modification.jsp">

<forward name="succes" path="/AfficherModificationListeCourses.do"  />
<forward name="erreur" path="/pages/erreur.jsp"  />
</action>
</action-mappings>

<!-- ========== Ressources de definitions de messages =========================== -->
<message-resources parameter="com.developpez.rpouiller.monapplication.ResourcesModification" key="modification" />

</struts-config>

VIII-A-10 - Modification du fichier "web.xml"

Modidier la déclaration du paramétrage de la servlet "org.apache.struts.action.ActionServlet" dans le fichier "web.xml".

<!-- Configuration de l'action servlet -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>
/WEB-INF/struts-config.xml,
/WEB-INF/struts-config-creation.xml,
/WEB-INF/struts-config-suppression.xml,
/WEB-INF/struts-config-modification.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

VIII-A-11 - Création de la JSP de modification

Créer une JSP "modification.jsp" dans "pages".

Remplir "modification.jsp" avec :

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
<%@ taglib prefix="logic" uri="http://struts.apache.org/tags-logic" %>
<%@ taglib prefix="nested" uri="http://struts.apache.org/tags-nested" %>
<html:html>
<head>
<title><bean:message key="titre.modification.elementcourses" bundle="modification"/></title>
</head>
<body>
<b><i><html:errors/></i></b><br/>
<html:form action="/ModifierModificationListeCourses.do">
<table border="1">
<thead>
<tr>
<th><bean:message key="colonne.identifiant"/></th>
<th><bean:message key="colonne.libelle"/></th>
<th><bean:message key="colonne.quantite"/></th>
</tr>
</thead>
<tbody>
<nested:iterate id="elementCourse" property="listeCourses" type="com.developpez.rpouiller.monapplication.ModifElementCourseBean">
<tr>
<td>
<nested:write property="idObjet"/>
<nested:hidden property="idObjet"/>
</td>
<td>
<nested:write property="libelle"/>
<nested:hidden property="libelle"/>
</td>
<td>
<nested:text property="quantite"/>
</td>
</tr>
</nested:iterate>
</tbody>
</table>
<html:submit/>
</html:form>
</body>
</html:html>

VIII-A-12 - Déploiement de l'application

Si le serveur est à l'état "Restart" (Il faut qu'il soit à l'état "Synchronized") : Sélectionner le serveur Tomcat dans la vue "Servers". Faire un clic droit sur le serveur Tomcat. Puis sélectionner "Restart".

Ouvrir un navigateur web à l'adresse : http://localhost:8080/MonApplication/AfficherModificationListeCourses.do.

VIII-A-13 - Vérification

L'application doit vérifier que les champs "quantite" sont renseignés.

L'application doit vérifier que les champs "quantite" est bien numérique.

L'application doit vérifier que les champs "quantite" est bien strictement positifs.

L'application doit stocker les nouvelles quantités et l'afficher ensuite.

VIII-B - Fonctionnement de l'ensemble

Au démarrage de l'application, la modification du fichier "web.xml" indique que la servlet "org.apache.struts.action.ActionServlet" est initialisée par quatre fichiers de configuration.

Le fichier "struts-config-modification.xml" déclare deux actions (une d'affichage et une de modification) et un formulaire. Ces deux actions ont le même formulaire. Le formulaire correspond à une classe définie dans l'application.

Lors de l'appel "http://localhost:8080/MonApplication/AfficherModificationListeCourses.do", la servlet "org.apache.struts.action.ActionServlet" est exécutée (url terminée par ".do"). Elle utilise le mapping des actions contenues dans "struts-config-modification.xml", pour appeler l'action "com.developpez.rpouiller.monapplication.AfficherModificationListeCoursesAction".

L'action appelle la DAO afin d'obtenir la liste des enregistrements contenus en base. Elle modifie la liste : elle transforme les quantités d'un format numérique vers un format chaine de caratères. Elle stocke la liste modifiée des enregistrements dans le "formulaire". Si tout s'est bien passé, elle demande de forwarder vers le mapping "succes" ("/pages/modification.jsp"). Ou en cas d'erreur, elle demande de forwarder vers le mapping "erreur" ("/pages/erreur.jsp").

La DAO "ListeCoursesDAO" utilise la ressource JDBC pour accéder à la base. Elle fournit une méthode retournant les informations contenues dans la table "LISTECOURSES".

La JSP "/pages/modification.jsp" affiche un tableau avec les valeurs contenues dans le formulaire. Chaque ligne du tableau comporte un champ de saisie pour la quantité. L'identifiant et le libellé de chaque objet est conservé dans le formulaire grâce au tag "nested:hidden". Le tag "nested:write" permet d'afficher ces valeurs. Le tag "nested:text" permet de modifier la quantité de chaque objet.

La JSP "/pages/erreur.jsp" affiche les erreurs stockées dans la requête.

Lors du clic sur le bouton "Submit", le formulaire est soumis au serveur.

Le formulaire "com.developpez.rpouiller.monapplication.ModificationListeCoursesForm" initialise la liste avec une "LazyList" afin de recevoir les informations du formulaire HTML. Ensuite, le formulaire est validé grâce à la méthode de validation définie dans la classe.

En cas d'erreur dans la validation, les messages d'erreur sont stockés dans la requête et l'application forwarde vers l'action d'affichage.

En cas de validation réussie, l'action de modification "com.developpez.rpouiller.monapplication.ModifierModificationListeCoursesAction" est exécutée. Elle récupère la liste des éléments depuis le formulaire. Elle demande à la DAO de modifier les éléments. Si tout s'est bien passé, elle demande de forwarder vers le mapping "succes" (action d'affichage). Ou en cas d'erreur, elle demande de forwarder vers le mapping "erreur" ("/pages/erreur.jsp").

La méthode "modifierElementsCourse" de la DAO "ListeCoursesDAO" modifie les enregistrements dans la table "LISTECOURSES".

IX - UNIFICATION DE L'APPLICATION PAR UN MENU

IX-A - Etape 10 : Création d'un menu

IX-A-1 - Modification du fichier d'internationalisation

Ajouter la ligne suivante dans le fichier "Resources.properties".

titre.application=Application de liste de courses

IX-A-2 - Création de la JSP "squelette"

Créer une JSP "page.jsp" dans "pages".

Remplir "page.jsp" avec :

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="tiles" uri="http://struts.apache.org/tags-tiles" %>
<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
<html:html>
<head>
<title><bean:message key="titre.application"/></title>
</head>
<body>
<table>
<tbody>
<tr>
<td valign="top">
<table>
<tbody>
<tr><td>
<a href="<html:rewrite page="/AfficherListeCourses.do"/>">
<bean:message key="titre.listecourses"/>
</a>
</td></tr>
<tr><td>
<a href="<html:rewrite page="/AfficherCreationElementCourses.do"/>">
<bean:message key="titre.creation.elementcourses" bundle="creation"/>
</a>
</td></tr>
<tr><td>
<a href="<html:rewrite page="/AfficherSuppressionElementCourses.do"/>">
<bean:message key="titre.suppression.elementcourses" bundle="suppression"/>
</a>
</td></tr>
<tr><td>
<a href="<html:rewrite page="/AfficherModificationListeCourses.do"/>">
<bean:message key="titre.modification.elementcourses" bundle="modification"/>
</a>
</td></tr>
</tbody>
</table>
</td>
<td valign="top">
<tiles:insert attribute="principal" />
</td>
</tr>
</tbody>
</table>
</body>
</html:html>

IX-A-3 - Création du fichier de définition des tiles

Créer un fichier XML "tiles-defs.xml" dans "WebContent/WEB-INF".

Remplir le fichier "tiles-defs.xml" avec :

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/tiles-config_1_3.dtd">

<tiles-definitions>

<!--  Définition de la page d'affichage -->
<definition name="page.affichage" template="/pages/page.jsp">
<put name="principal"  value="/pages/listeCourses.jsp" />
</definition>

<!--  Définition de la page de création -->
<definition name="page.creation" template="/pages/page.jsp">
<put name="principal"  value="/pages/creation.jsp" />
</definition>

<!--  Définition de la page de suppression -->
<definition name="page.suppression" template="/pages/page.jsp">
<put name="principal"  value="/pages/suppression.jsp" />
</definition>

<!--  Définition de la page de modification -->
<definition name="page.modification" template="/pages/page.jsp">
<put name="principal"  value="/pages/modification.jsp" />
</definition>

<!--  Définition de la page d'erreur -->
<definition name="page.erreur" template="/pages/page.jsp">
<put name="principal"  value="/pages/erreur.jsp" />
</definition>

</tiles-definitions>

IX-A-4 - Modification du fichier de configuration "struts-config.xml"

Rajouter la déclaration des validations dans "struts-config.xml" après la validation des formulaires :

<!-- ========== Tiles =========================== -->
<plug-in className="org.apache.struts.tiles.TilesPlugin">
<set-property property="definitions-config"
value="/WEB-INF/tiles-defs.xml" />
</plug-in>

IX-A-5 - Modification de la JSP d'erreur

Saisir le code suivant pour la JSP "erreur.jsp".

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>

<html:errors/><br/>

IX-A-6 - Modification de la JSP d'affichage

Saisir le code suivant pour la JSP "listeCourses.jsp".

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
<%@ taglib prefix="logic" uri="http://struts.apache.org/tags-logic" %>

<table border="1">
<thead>
<tr>
<th><bean:message key="colonne.identifiant"/></th>
<th><bean:message key="colonne.libelle"/></th>
<th><bean:message key="colonne.quantite"/></th>
</tr>
</thead>
<tbody>
<logic:iterate id="elementCourse" name="LISTE_COURSES" type="com.developpez.rpouiller.monapplication.ElementCourseBean">
<tr>
<td><bean:write name="elementCourse" property="idObjet"/></td>
<td><bean:write name="elementCourse" property="libelle"/></td>
<td><bean:write name="elementCourse" property="quantite"/></td>
</tr>
</logic:iterate>
</tbody>
</table>

IX-A-7 - Modification de la JSP de création

Saisir le code suivant pour la JSP "creation.jsp".

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
<%@ taglib prefix="logic" uri="http://struts.apache.org/tags-logic" %>
<%@ taglib prefix="nested" uri="http://struts.apache.org/tags-nested" %>

<b><i><html:errors/></i></b><br/>
<html:form action="/CreerCreationElementCourses.do">
<bean:message key="creation.elementcourses.libelle.libelle" bundle="creation"/>
<nested:text property="libelle"/><br>
<bean:message key="creation.elementcourses.libelle.quantite" bundle="creation"/>
<nested:text property="quantite"/><br>
<html:submit/>
</html:form>
<table border="1">
<thead>
<tr>
<th><bean:message key="colonne.identifiant"/></th>
<th><bean:message key="colonne.libelle"/></th>
<th><bean:message key="colonne.quantite"/></th>
</tr>
</thead>
<tbody>
<logic:iterate id="elementCourse" name="LISTE_COURSES" type="com.developpez.rpouiller.monapplication.ElementCourseBean">
<tr>
<td><bean:write name="elementCourse" property="idObjet"/></td>
<td><bean:write name="elementCourse" property="libelle"/></td>
<td><bean:write name="elementCourse" property="quantite"/></td>
</tr>
</logic:iterate>
</tbody>
</table>

IX-A-8 - Modification de la JSP de suppression

Saisir le code suivant pour la JSP "suppression.jsp".

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
<%@ taglib prefix="logic" uri="http://struts.apache.org/tags-logic" %>
<%@ taglib prefix="nested" uri="http://struts.apache.org/tags-nested" %>

<html:form action="/SupprimerSuppressionElementCourses.do">
<nested:hidden styleId="idobjet" property="idobjet"/>
<table border="1">
<thead>
<tr>
<th><bean:message key="colonne.identifiant"/></th>
<th><bean:message key="colonne.libelle"/></th>
<th><bean:message key="colonne.quantite"/></th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
<logic:iterate id="elementCourse" name="LISTE_COURSES" type="com.developpez.rpouiller.monapplication.ElementCourseBean">
<tr>
<bean:define id="idObjet" name="elementCourse" property="idObjet"/>
<td><bean:write name="elementCourse" property="idObjet"/></td>
<td><bean:write name="elementCourse" property="libelle"/></td>
<td><bean:write name="elementCourse" property="quantite"/></td>
<td>
<a href="#" onclick="document.getElementById('idobjet').value = ${idObjet}; document.forms[0].submit();">
<bean:message key="suppression.supprimer.libelle" bundle="suppression"/>
</a>
</td>
</tr>
</logic:iterate>
</tbody>
</table>
</html:form>

IX-A-9 - Modification de la JSP de modification

Saisir le code suivant pour la JSP "modification.jsp".

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
<%@ taglib prefix="logic" uri="http://struts.apache.org/tags-logic" %>
<%@ taglib prefix="nested" uri="http://struts.apache.org/tags-nested" %>

<b><i><html:errors/></i></b><br/>
<html:form action="/ModifierModificationListeCourses.do">
<table border="1">
<thead>
<tr>
<th><bean:message key="colonne.identifiant"/></th>
<th><bean:message key="colonne.libelle"/></th>
<th><bean:message key="colonne.quantite"/></th>
</tr>
</thead>
<tbody>
<nested:iterate id="elementCourse" property="listeCourses" type="com.developpez.rpouiller.monapplication.ModifElementCourseBean">
<tr>
<td>
<nested:write property="idObjet"/>
<nested:hidden property="idObjet"/>
</td>
<td>
<nested:write property="libelle"/>
<nested:hidden property="libelle"/>
</td>
<td>
<nested:text property="quantite"/>
</td>
</tr>
</nested:iterate>
</tbody>
</table>
<html:submit/>
</html:form>

IX-A-10 - Modification du fichier de configuration "struts-config.xml"

Modifier les forwards des actions dans le fichier "struts-config.xml" avec :

<!-- ========== Mapping des actions ============================== -->
<action-mappings>

<!-- Indique la correspondance entre une action sous forme d'URL (ici /AfficherListeCourses.do),
une classe (ici com.developpez.rpouiller.monapplication.AfficherListeCoursesAction) -->
<action    path      = "/AfficherListeCourses"
type      = "com.developpez.rpouiller.monapplication.AfficherListeCoursesAction"
scope     = "request">

<forward name="succes" path="page.affichage"  />
<forward name="erreur" path="page.erreur"  />
</action>
</action-mappings>

IX-A-11 - Modification du fichier de configuration "struts-config-creation.xml"

Modifier les forwards des actions dans le fichier "struts-config-creation.xml" avec :

<!-- ========== Mapping des actions ============================== -->
<action-mappings>

<action    path      = "/AfficherCreationElementCourses"
name      = "creationForm"
type      = "com.developpez.rpouiller.monapplication.AfficherListeCoursesAction"
scope     = "request"
validate  = "false"
attribute = "bean">

<forward name="succes" path="page.creation"  />
<forward name="erreur" path="page.erreur"  />
</action>

<action    path      = "/CreerCreationElementCourses"
name      = "creationForm"
type      = "com.developpez.rpouiller.monapplication.CreerElementCoursesAction"
scope     = "request"
validate  = "true"
attribute = "bean"
input     = "/AfficherCreationElementCourses.do">

<forward name="succes" path="/AfficherCreationElementCourses.do"  />
<forward name="erreur" path="page.erreur"  />
</action>
</action-mappings>

IX-A-12 - Modification du fichier de configuration "struts-config-suppression.xml"

Modifier les forwards des actions dans le fichier "struts-config-suppression.xml" avec :

<!-- ========== Mapping des actions ============================== -->
<action-mappings>

<action    path      = "/AfficherSuppressionElementCourses"
name      = "suppressionForm"
type      = "com.developpez.rpouiller.monapplication.AfficherListeCoursesAction"
scope     = "request"
validate  = "false"
attribute = "bean">

<forward name="succes" path="page.suppression"  />
<forward name="erreur" path="page.erreur"  />
</action>

<action    path      = "/SupprimerSuppressionElementCourses"
name      = "suppressionForm"
type      = "com.developpez.rpouiller.monapplication.SupprimerElementCoursesAction"
scope     = "request"
validate  = "false"
attribute = "bean">

<forward name="succes" path="/AfficherSuppressionElementCourses.do"  />
<forward name="erreur" path="page.erreur"  />
</action>
</action-mappings>

IX-A-13 - Modification du fichier de configuration "struts-config-modification.xml"

Modifier les forwards des actions dans le fichier "struts-config-modification.xml" avec :

<!-- ========== Mapping des actions ============================== -->
<action-mappings>

<action    path      = "/AfficherModificationListeCourses"
name      = "modificationForm"
type      = "com.developpez.rpouiller.monapplication.AfficherModificationListeCoursesAction"
scope     = "request"
validate  = "false"
attribute = "bean">

<forward name="succes" path="page.modification"  />
<forward name="erreur" path="page.erreur"  />
</action>

<action    path      = "/ModifierModificationListeCourses"
name      = "modificationForm"
type      = "com.developpez.rpouiller.monapplication.ModifierModificationListeCoursesAction"
scope     = "request"
validate  = "true"
attribute = "bean"
input     = "/pages/modification.jsp">

<forward name="succes" path="/AfficherModificationListeCourses.do"  />
<forward name="erreur" path="page.erreur"  />
</action>
</action-mappings>

IX-A-14 - Modification du fichier "web.xml"

Ajouter un paramètre d'initialisation à la servlet "org.apache.struts.action.ActionServlet" dans le fichier "struts-config-modification.xml" :

<init-param>
<param-name>chainConfig</param-name>
<param-value>org/apache/struts/tiles/chain-config.xml</param-value>
</init-param>

IX-A-15 - Déploiement de l'application

Si le serveur est à l'état "Restart" (Il faut qu'il soit à l'état "Synchronized") : Sélectionner le serveur Tomcat dans la vue "Servers". Faire un clic droit sur le serveur Tomcat. Puis sélectionner "Restart".

Ouvrir un navigateur web à l'adresse : http://localhost:8080/MonApplication/AfficherListeCourses.do.

IX-A-16 - Vérification

Lorsque l'on clique sur les différents liens du menu, on obtient les différents écrans de l'application.

IX-B - Fonctionnement de l'ensemble

Au démarrage de l'application, la modification du fichier "web.xml" indique que la servlet "org.apache.struts.action.ActionServlet" est doit également gérer des tiles.

Le fichier "struts-config.xml" déclare le plugin de gestion des tiles avec son fichier de configuration.

Le fichier "tiles-defs.xml" déclare les tiles : la JSP squelette "page.jsp" qui comporte le menu et les différents tiles (affichage, création, suppression, modification et erreur). Le tag "tiles:insert" contenu dans "pages.jsp" sera remplacé par le contenu de la JSP définie pour chaque tile dans le fichier "tiles-defs.xml".

Lors de l'appel "http://localhost:8080/MonApplication/AfficherListeCourses.do", tout se déroule comme précédemment, sauf lors du forwarde "succes" ou "erreur". Les forwards sont changés vers des tiles, afin d'obtenir les pages avec le menu commun à toutes les pages.

X - REMERCIEMENTS

Je remercie sincèrement par ordre plus ou moins chronologique :

- www.developpez.com me permettant de publier cet article.

- Nono40 pour ses outils.

- djo.mos pour ses suggestions pertinentes, ses corrections et ses encouragements.

- waeselynck.raphael pour ses encouragements.

- longbeach pour ses corrections et ses encouragements.

- dourouc05 pour sa relecture orthographique rigoureuse.

XI - SOURCES DU PROJET A CHAQUE ETAPE

Sources à l'étape 1(Miroir)

Sources à l'étape 2(Miroir)

Sources à l'étape 3(Miroir)

Sources à l'étape 5(Miroir)

Sources à l'étape 7(Miroir)

Sources à l'étape 8(Miroir)

Sources à l'étape 9(Miroir)

Sources à l'étape 10(Miroir)