Atelier 6 Le Framework Spring

afternoonhandsomelySoftware and s/w Development

Nov 17, 2012 (4 years and 4 months ago)

509 views


Atelier
6


Le Framework Spring
Atelier 6 – Le Framework Spring Page
:
2/26



Installation du module Spring NetBeans
Démarrez NetBeans IDE choisissez : « ToolsUpdate Center ». La fenêtre suivante apparaît :




Sélectionnez l’option « Install Manually Downloaded Modules (.nbm Files) » et appuyez sur “Next”.
Dans la fenêtre qui suit, appuyez sur « Add », parcourez l’arborescence des répertoires pour
sélectionner le fichier « 1175877104650_net-sf-springnetbeans-support.nbm » fourni dans les
ressources du chapitre 6 et appuyez sur « Next ».
Suivez les instructions demandées jusqu’à l’achèvement de l’installation.

Activité1 : SpringIoc Java
Création et préparation du projet
Avant de passer au cœur de l'utilisation de Spring, nous devons créer et configurer un projet
NetBeans. Cette partie est nécessaire pour assurer le bon fonctionnement de l’application.
Nous allons commencer par créer un projet java sous NetBeans, et ce en procédant comme suit :
Dans la barre de menu, choisissez File -> NewProjet -> General  Java Application, la fenêtre
suivante apparaît :

Atelier 6 – Le Framework Spring Page
:
2/26




Choisissez « Java Application » et appuyez sur le bouton « Next ».

Entrez « SpringIocDemo » comme « Project Name », et appuyer sur le bouton « Finish ».
Le projet ainsi créé aura l'arborescence suivante :



Nous allons maintenant ajouter au classpath du projet la librairie Spring :
Faites sur le répertoire « Libraries » du projet « SpringIocDemo » : « Bouton droit  Add Library »
La fenêtre suivante apparaît :

Atelier 6 – Le Framework Spring Page
:
2/26




Sélectionnez la bibliothèque Spring Framework2.0.Puis cliquez sur « AddLibraries ».
L’arborescence du projet apparaît maintenant comme suit :


Remarque :
Dans notre cas, nous aurons besoin uniquement de spring.jar et commons-logging.jar.

Atelier 6 – Le Framework Spring Page
:
2/26



Création des éléments du projet
Nous créons maintenant la classe « Personne » sous le package « domain »:

Cette classe possède un attribut de type String « nom » et les méthodes « set » et « get »
correspondantes :

package springiocdemo;
public class Personne {
private String nom ;
/** Creates a new instance of Personne */
public Personne() {
}
… // getter et stetter
}

Nous allons créer la classe DAO : «PersonneDAO » relative à la classe métier « Personne » sous le
package « dao» :






Atelier 6 – Le Framework Spring Page
:
2/26


La classe PersonneDAO possède une méthode « save » qui prend en paramètre un objet de type
Personne
:

package dao;
import domain.Personne;
public class PersonneDAO {

/** Creates a new instance of PersonneDAO */
public PersonneDAO() {
}
public void save(Personne p){
System.out.println("Exécution de save sur la personne: "+p.getNom());
}
}

On va modifier la classe « Personne » afin de lui attribuer un champ de type « PersonneDAO »et les
méthodes « set » et « set ».
Pour ce faire, ajoutez l’attribut ci-dessous à l’intérieur de la classe « Personne » et générez les getter
et setter:

private PersonneDAO dao ;
… // getter et setter
Nous allons maintenant accorder à Spring le contrôle de l'initialisation du Bean « Personne». Le
fichier de configuration « springconfig.xml » est semblable à celui montré ci-dessous :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- Bean configuration -->
<bean id="personneDAO" class="dao.PersonneDAO">
</bean>
<!-- Bean Classes -->
<bean id="personne" class="domain.Personne">
<property name="nom">
<value>foulen </value>
</property>
<property name="dao">
<ref bean="personneDAO"/>
</property>
</bean>
</beans>

Atelier 6 – Le Framework Spring Page
:
2/26


Test

Afin de mettre en ouvre le design pattern « Ioc », on va créer une classe « Main » contenant la
méthode « main» sous le package « springiocdemo ».Son contenu est le suivant :

package springiocdemo;
import domain.Personne;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Main {
public Main() {
}
public static void main(String[] args) {
ApplicationContext ctx =
new FileSystemXmlApplicationContext("springconfig.xml");
Personne p =(Personne)ctx.getBean("personne");
p.getDao().save(p);
}
}

Pour résoudre les messages « warning » du framework log4j qui permet de logger et de débogger
les applications Java, on va créer un fichier nommé log4j.properties sous le répertoire racine « src »
contenant les lignes suivantes :

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.rootLogger=debug, stdout
log4j.logger.org.hibernate=info
log4j.logger.org.hibernate.SQL=debug
log4j.logger.org.hibernate.type=info
log4j.logger.org.hibernate.tool.hbm2ddl=info
log4j.logger.org.hibernate.cache=info
En exécutant la classe « Main », nous obtenons dans la console ce qui suit :

Exécution de la méthode save sur la personne: foulen
BUILD SUCCESSFUL (total time: 1 second)?

Atelier 6 – Le Framework Spring Page
:
2/26



Activité 3: Application MVC/Hibernate avec Spring
Nous nous proposons de développer une application MVC avec le framework Spring.
Cette application va gérer des personnes, leur création, modification et suppression au niveau de la
base de données.
Commençons d’abord par la création d’un projet sous NetBeans IDE 5.5.1.
Dans le menu File  New Project choisissez Web Application puis cliquez sur next

Donnez un nom à votre application et cliquez sur next :

Cochez la case correspondante à Spring Framework et cliquez sur finish.
Atelier 6 – Le Framework Spring Page
:
2/26



Vous devriez avoir l’arborescence suivante :

L’entité Personne
L’application gère un groupe de personnes. Formellement, celles-ci sont représentées par une classe
Personne :

Nous plaçons notre classe dans le package hibernate/personne puisque nous enregistrerons notre
classe dans la base de données.
Atelier 6 – Le Framework Spring Page
:
2/26


package hibernate.personne;
import java.util.Date;
public class Personne {

private java.lang.Integer Id; // identifiant unique de la personne
private String nom; // Le nom
private String prenom; // Le prénom
private Date dateNaissance; // La date de naissance
private int nbEnfants; // Le nombre d’enfants

// générez les getters - setters
public Personne() { }// constructeur par défaut
// constructeur avec initialisation des champs de la personne
public Personne(java.lang.Integer id, String prenom, String nom, Date
dateNaissance, int nbEnfants) {
setId(id); setNom(nom); setPrenom(prenom);
setDateNaissance(dateNaissance); setNbEnfants(nbEnfants);
}
}

A présent nous allons définir le fichier de mapping hibernate de la classe Personne avec la table
« personnes ». Cliquez sur le package hibernate.personne et faites new Xml Document, nommez le
Personne.hbm et définissez son contenu comme suit :
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="hibernate.personne">
<class name="Personne" table="personnes" >
<meta attribute="sync-DAO">false</meta>
<id name="Id" type="integer" column="num_personne">
<generator class="assigned"/> <!-- La valeur de l’id est définie par l’utilisateur-->
</id>
<property name="nom" column="nom" type="string" not-null="true" length="30"
/>
<property name="prenom" column="prenom" type="string" length="30" />
<property name="dateNaissance" column="date_naissance" type="date" />
<property name="nbEnfants" column="nb_enfants" type="integer" length="30" />
</class>
</hibernate-mapping>


La couche DAO
La couche dao est constituée des classes et interfaces suivantes :
- IDao est l’interface présentée par la couche dao
- DaoImpl est une implémentation de celle-ci et une spécialisation de HibernateDaoSupport
- DaoException est un type d’exceptions non contrôlées, lancées par la couche dao
Atelier 6 – Le Framework Spring Page
:
2/26


Voici la définition de IDao :
package dao;
import hibernate.personne.Personne;
import java.util.Collection;
public interface IDao {

Collection getAll();// liste de toutes les personnes
Personne getOne(java.lang.Integer id); // obtenir une personne particulière
void saveOne(Personne personne); // ajouter/modifier une personne
void deleteOne(java.lang.Integer id); // supprimer une personne
}


L’interface a quatre méthodes pour les quatre opérations que l’on souhaite faire sur le groupe de
personnes :
• getAll : pour obtenir une collection de personnes
• getOne : pour obtenir une personne ayant un id précis
• saveOne : pour ajouter une personne (id=-1) ou modifier une personne existante (id <> -1)
• deleteOne : pour supprimer une personne ayant un id précis
Voici une implémentation de l’interface IDao :
package dao;
import hibernate.personne.Personne;
import java.util.Collection;
import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class DaoImpl extends HibernateDaoSupport implements IDao {

public Collection getAll() {// liste des personnes
return getHibernateTemplate().loadAll(Personne.class);
}
// obtenir une personne en particulier
public Personne getOne(java.lang.Integer id) {
// on cherche la personne
List list=getHibernateTemplate().find("from Personne where id=?",id);
return (Personne) list.get(0);
}
// ajouter ou modifier une personne
public void saveOne(Personne personne) {
getHibernateTemplate().saveOrUpdate(personne);
}
// suppression d'une personne
public void deleteOne(java.lang.Integer id) {
Personne p = getOne(id);
getHibernateTemplate().delete(p);
}
}

Atelier 6 – Le Framework Spring Page
:
2/26


Cette implémentation étend la classe HibernateDaoSupport pour pouvoir utiliser un objet de type
HibernateTemplate. Cette classe facilite le code d’accès aux données
Notons qu’il faut configurer au préalable la SessionFactory avec la data source relative à notre base
de données dans le fichier applicationContext.xml.
D’abord complétez la définition de la data source donnée :
<bean id="dataSource" class="org.springframework.jdbc.datasource.
DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

Par :
<bean id="dataSource" class="org.springframework.jdbc.datasource.
DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/SpringDB"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</bean>

Rajoutez ensuite les balises suivantes :
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.
LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource"/>
</property>
<property name="mappingResources">
<list> <value>hibernate/personne/Personne.hbm.xml</value> </list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cglib.use_reflection_optimizer">false</prop>
</props>
</property>
</bean>
<bean id="hibernateDaoSupport" class="org.springframework.orm.hibernate3.
support.HibernateDaoSupport" abstract="true">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<!-- implémentation de la couche [dao] -->
<bean id="dao" class="dao.DaoImpl" init-method="init"
parent="hibernateDaoSupport"/>

Nous voyons dans ces balises :
Atelier 6 – Le Framework Spring Page
:
2/26


- La définition d’une SessionFactory utilisant le bean datasource localement défini et le
fichier de mapping hibernate Personne.hbm.xml
- La définition d’un bean HibernateDaoSupport qui utilise la SessionFactory ainsi créée
- La déclaration de notre implémentation de l’interface IDao et précision qu’elle est fille du
bean HibernateDaoSupport
Ces beans vont être initialisés par Spring IoC.
La couche Dao est susceptible de lancer des exceptions de type DaoException. Voici le code de
cette classe :
package dao;
public class DaoException extends RuntimeException {
private int code; // code erreur

public int getCode() { return code; }
public DaoException(String message,int code) { // constructeur
super(message);
this.code=code;
}
}

La classe DaoException dérivant de RuntimeException est un type d’exception non contrôlée : le
compilateur ne nous oblige pas à :
- gérer ce type d’exceptions avec un try / catch lorsqu’on appelle une méthode pouvant la
lancer
- mettre le marqueur " throws DaoException " dans la signature d’une méthode susceptible de
lancer l’exception
Cette technique nous évite d’avoir à signer les méthodes de l’interface IDao avec des exceptions
d’un type particulier. Toute implémentation lançant des exceptions non contrôlées sera alors
acceptable amenant ainsi de la souplesse dans l’architecture.


La couche service
La couche service est constituée des classes et interfaces suivantes :
- IService est l’interface présentée par la couche service
- ServiceImpl est une implémentation de celle-ci
L’interface est identique à IDao puisque dans notre exemple nous ne faisons pas de traitements
métier mais nous nous contentons de faire des opérations élémentaires sur des enregistrements de
base de données. Voici donc le code de IService :
Atelier 6 – Le Framework Spring Page
:
2/26


package metier;
import hibernate.personne.Personne;
import java.util.Collection;
public interface IService {
Collection getAll();// liste de toutes les personnes
Personne getOne(java.lang.Integer id); // obtenir une personne particulière
void saveOne(Personne personne); // ajouter/modifier une personne
void deleteOne(java.lang.Integer id); // supprimer une personne
}
Voici l’implémentation de IService :
package metier;
import dao.IDao;
import hibernate.personne.Personne;
import java.util.Collection;
public class ServiceImpl implements IService {
/* l’attribut de type IDao est une référence sur la couche dao. Il sera initialisé par Spring
IoC*/
private IDao dao;
public IDao getDao() { return dao; }
public void setDao(IDao dao) { this.dao = dao; }
// liste des personnes
public synchronized Collection getAll() { return dao.getAll(); }
// obtenir une personne en particulier
public synchronized Personne getOne(java.lang.Integer id) {
return dao.getOne(id);
}
// ajouter ou modifier une personne
public synchronized void saveOne(Personne personne) {
dao.saveOne(personne);
}
// suppression d'une personne
public synchronized void deleteOne(java.lang.Integer id) {
dao.deleteOne(id);
}
}

Les méthodes appelées ne font que déléguer la demande à la couche Dao.
Toutes les méthodes sont synchronisées (mot clé synchronized) assurant qu’un seul thread à la fois
pourra utiliser la couche service et donc la couche dao.
La classe fait référence au bean de la couche Dao créé par le container, et donc pour respecter l’IoC
il faut rajouter la balise suivante dans applicationContext.xml :

Atelier 6 – Le Framework Spring Page
:
2/26


<!-- implémentation de la couche service -->
<bean id="service" class="metier.ServiceImpl">
<property name="dao">
<ref local="dao"/>
</property>
</bean>

La configuration de l’application
Le contrôleur principal DispatcherServlet fait exécuter l'action demandée par l'utilisateur par une
classe implémentant l'interface : org.springframework.web.servlet. mvc.Controller.
Il faut donc écrire le fichier personnes-servlet.xml sous le répertoire WEB-INF pour préciser à
DispatcherServlet quel contrôleur traite quelle url :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<!-- les mappings de l'application-->
< !-- SimpleUrlHandlerMapping fait la correspondance entre les urls transmises par la
servlet et les controllers adéquats. -->
<bean
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/list.html">Personnes.ListController</prop>
<prop key="/delete.html">Personnes.DeleteController</prop>
<prop key="/edit.html">Personnes.EditController</prop>
</props>
</property>
</bean>
<!-- LES CONTROLEURS -->

<!-- le bean service est instancié par applicationContext.xml qui est chargé par
ContextLoaderListener avant l'instanciation de DispatcherServlet -->
<bean id="Personnes.ListController" class="web.ListPersonnes">
<property name="service">
<ref bean="service"/>
</property>
</bean>
<bean id="Personnes.DeleteController" class="web.DeletePersonne">
<property name="service">
<ref bean="service"/>
</property>
</bean>
<bean id="Personnes.EditController" class="web.EditPersonne">
<property name="sessionForm">
<value>true</value>
</property>
<property name="commandName">
<value>personne</value>
Atelier 6 – Le Framework Spring Page
:
2/26


</property>
<property name="validator">
<ref bean="Personnes.Validator"/>
</property>
<property name="formView">
<value>edit</value>
</property>
<property name="service">
<ref bean="service"/>
</property>
</bean>
<!-- le validateur -->
<bean id="Personnes.Validator" class="web.ValidatePersonne"/>

<!-- le résolveur de vues -->
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename">
<value>vues</value>
</property>
</bean>
<!-- le gestionnaire d'exceptions -->
<bean
class="org.springframework.web.servlet.handler. SimpleMappingExceptionResolver">
<property name="exceptionAttribute">
<value>exception</value>
</property>
<property name="defaultStatusCode"> <value>200</value>
</property>
<property name="defaultErrorView">
<value>exception</value>
</property>
</bean>
<!-- le fichier des messages -->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
<value>messages</value>
</property>
</bean>
</beans>


Les vues de l’application
Pour gérer les vues, nous définissons un fichier vues.properties dans le default package des sources
packages. Son contenu est le suivant :
Atelier 6 – Le Framework Spring Page
:
2/26


#list
list.class=org.springframework.web.servlet.view.JstlView
list.url=/WEB-INF/vues/list.jsp

#r-list
r-list.class=org.springframework.web.servlet.view.RedirectView
r-list.url=/list.html
r-list.contextRelative=true
r-list.http10Compatible=false

#edit
edit.class=org.springframework.web.servlet.view.JstlView
edit.url=/WEB-INF/vues/edit.jsp

#exception
exception.class=org.springframework.web.servlet.view.JstlView
exception.url=/WEB-INF/vues/exception.jsp

La classe JstlView permet d'afficher un modèle Map au moyen d'une page JSP utilisant ou non des
balises JSTL.
RedirectView permet d'envoyer en réponse au client, un ordre de redirection vers une URL donnée.
Sous le répertoire WEB-INF nous créons un dossier « vues » qui contiendra nos pages JSP.
Les contrôleurs jouent un rôle important dans la mise en place du contenu de ces JSP.
La page list.jsp :
Cette page va lister les enregistrements de la base de données dans un tableau en mettant un lien de
suppression ou de modification pour chaque ligne et un lien d’ajout d’une nouvelle personne en bas
du tableau.
Elle reçoit en paramètre le map défini par le contrôleur ListPersonnes. Voici son code :
Atelier 6 – Le Framework Spring Page
:
2/26


<%@ page language="java" pageEncoding="ISO-8859-1"
contentType="text/html;charset=ISO-8859-1"%>
<%@ taglib uri="/WEB-INF/tld/c.tld" prefix="c" %>
<%@ page isELIgnored="false" %>
<html>
<head>
<title>Spring MVC - personnes</title>
</head>
<body >
<h2>Liste des personnes</h2>
<table border="1">
<tr>
<th>Id</th> <th>Pr&eacute;nom</th> <th>Nom</th>
<th>Date de naissance</th> <th>Nombre d'enfants</th> <th></th>
</tr>
<c:forEach var="personne" items="${personnes}">
<tr>
<td><c:out value="${personne.id}"/></td>
<td><c:out value="${personne.prenom}"/></td>
<td><c:out value="${personne.nom}"/></td>
<td><dt:format
pattern="dd/MM/yyyy">${personne.dateNaissance.time}</dt:format></td>
<td><c:out value="${personne.nbEnfants}"/></td>
<td><a href="<c:url
value="/edit.html?id=${personne.id}"/>">Modifier</a></td>
<td><a href="<c:url
value="/delete.html?id=${personne.id}"/>">Supprimer</a></td>
</tr>
</c:forEach>
</table>
<br>
<a href="<c:url value="/edit.html?id=-1"/>">Ajout</a>
</body>
</html>

On remarque la redirection vers edit.html par le lien Modifier et delete.html par le lien Supprimer. A
chaque fois, l’id de l’objet personne concerné est passé en paramètre de la requête.
Le lien Ajout appellera la même ressource edit.html mais avec un id = -1 pour faire la distinction
avec la modification.
La page edit.jsp :
Cette page correspond à un formulaire qui sera rempli ou modifié par l’utilisateur selon la nature de
l’opération.
Elle reçoit en paramètre un objet personne provenant du contrôleur EditPersonnes, contenant les
informations relatives à la personne dans le cas d’une modification ou une personne vide dans le cas
d’un ajout.

Atelier 6 – Le Framework Spring Page
:
2/26


<%@ page language="java" pageEncoding="ISO-8859-1" contentType="text/html;charset=ISO-8859-
1"%>
<%@ taglib uri="/WEB-INF/tld/c.tld" prefix="c" %>
<%@ taglib uri="/WEB-INF/tld/spring.tld" prefix="spring" %>
<%@ page isELIgnored="false" %>
<html>
<head>
<title>Spring-mvc : Personnes</title>
</head>
<body>
<h2>Ajout/Modification d'une personne</h2>
<spring:bind path="personne">
<c:if test="${status.error}">
<h3>Les erreurs suivantes se sont produites :</h3>
<ul>
<c:forEach items="${status.errorMessages}" var="erreur">
<li><c:out value="${erreur}"/></li>
</c:forEach>
</ul>
<hr>
</c:if>
</spring:bind>
<form method="post" action="<c:url value="/edit.html"/>">
<table border="1">
<tr>
<td>Id</td>
<td>${personne.id}</td>
</tr>
<tr>
<td>Pr&eacute;nom</td>
<spring:bind path="personne.prenom">
<td>
<input type="text" value="${status.value}" name="${status.expression}" size="20">
</td>
<td>${status.errorMessage}</td>
</spring:bind>
</tr>
<tr>
<td>Nom</td>
<spring:bind path="personne.nom">
<td>
<input type="text" value="${status.value}" name="${status.expression}" size="20">
</td>
<td>${status.errorMessage}</td>
</spring:bind>
</tr>
<tr>
<td>Date de naissance (JJ/MM/AAAA)</td>
<spring:bind path="personne.dateNaissance">
<td>
<input type="text" value="${status.value}" name="${status.expression}">
</td>
<td>${status.errorMessage}</td>
</spring:bind>
</tr>
Atelier 6 – Le Framework Spring Page
:
2/26



<tr>
<td>Nombre d'enfants</td>
<spring:bind path="personne.nbEnfants">
<td>
<input type="text" value="${status.value}" name="${status.expression}">
</td>
<td>${status.errorMessage}</td>
</spring:bind>
</tr>
</table>
<br>
<input type="hidden" value="${personne.id}" name="id">
<input type="submit" value="Valider">
<a href="<c:url value="/list.html"/>">Annuler</a>
</form>
</body>
</html>


La page exception.jsp
L’utilisateur sera redirigé vers cette page dans le cas d’une erreur qui s’est produite en effectuant une
opération qu’il a demandée. Son but est de préciser à l’utilisateur à quel niveau, l’erreur s’est
produite. Voici son code :
<%@ page language="java" pageEncoding="ISO-8859-1"
contentType="text/html;charset=ISO-8859-1"%>
<%@ taglib uri="/WEB-INF/tld/c.tld" prefix="c" %>
<%@ page isELIgnored="false" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html> <head> <title>Spring MVC - personnes</title> </head>
<body>
<h2>Erreur</h2>
L'exception suivante s'est produite :
<c:out value="${exception.message}"/>
<br><br>
<a href="<c:url value="/list.html"/>">Retour à la liste</a>
</body>
</html>

Atelier 6 – Le Framework Spring Page
:
2/26



Les contrôleurs de l’application
Les contrôleurs seront placés dans le package web des sources packages comme suit :

Le contrôleur ListPersonnes.java :
Ce contrôleur concerne la JSP qui liste les personnes instanciées dans la base de données. Il est donc
simple et n’a besoin que d’implémenter l’interface Controller. Voici son code :
package web;
import java.util.HashMap;
import java.util.Map;
import metier.IService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class ListPersonnes implements Controller {

IService service; // service déclaré dans applicationContext.xml
public IService getService() { return service; }
public void setService(IService service) {this.service = service; }

// gestion de la requête
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
Map model = new HashMap();// le modèle de la vue list
/*Récupération de la collection de personnes à l'aide de service.getAll() et passage à la vue */
model.put("personnes", service.getAll());
// résultat
return new ModelAndView("list", model);
}
}

La résolution des vues dans Spring est flexible. Une implémentation de Controller peut écrire une
vue directement dans la réponse (en retournant un ModelAndView).
Une instance de ModelAndView consiste en un nom de vue et un model Map qui contient les noms
des beans (personnes) et les objets correspondants (la collection retournée par service.getAll() ).
Le model Map peut simplement être transformée en un format approprié, comme des attributs
d’une requête JSP.
Atelier 6 – Le Framework Spring Page
:
2/26


Le contrôleur EditPersonnes:
Ce contrôleur va servir à traiter les données provenant des formulaires d’ajout ou de modification
d’une personne. Il étend donc la classe SimpleFormController.
SimpleFormController est un contrôleur de formulaire qui facilite la manipulation d’un formulaire et
de son objet commande correspondant. Il permet de spécifier un objet commande, le nom d’une
vue pour le formulaire, le nom d’une vue pour la page à montrer à l’utilisateur en cas de réussite,
etc…
import java.text.SimpleDateFormat;
import dao.DaoException;
import hibernate.personne.Personne;
import metier.IService;

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

import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.validation.BindException;
import org.springframework.web.bind.RequestUtils;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.view.RedirectView;

public class EditPersonne extends SimpleFormController {
IService service; // service
public IService getService() {return service; }
public void setService(IService service) {this.service = service; }
// enregistrement d'éditeurs de propriétés
protected void initBinder(HttpServletRequest request,
ServletRequestDataBinder binder) throws Exception {
// format attendu pour la date e naissance
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
// format strict
dateFormat.setLenient(false);
// on enregistre un éditeur de propriétés String (dd/MM/yyyy) -> Date
// CustomDateEditor est fourni par Spring - il sera utilisé par Spring
// pour transformer
// la chaîne saisie dans le formulaire en type java.util.Date
// la date ne pourra être vide (2ième paramètre de CustomDateEditor)
binder.registerCustomEditor(java.util.Date.class, null,
new CustomDateEditor(dateFormat, false));
}
// préparation [Personne] à afficher
protected Object formBackingObject(HttpServletRequest request) {
// on récupère l'id de la personne
int id = ServletRequestUtils.getIntParameter(request, "id", -1);
java.lang.Integer i = new java.lang.Integer(id);
// ajout ou modification ?
Personne personne = null;
System.out.println("id ="+id);
Atelier 6 – Le Framework Spring Page
:
2/26


if (id != -1) { // modification - on récupère la personne à modifier
personne = service.getOne(i);
}else{ // ajout - on crée une personne vide
personne = new Personne();
java.util.Random r = new java.util.Random(new java.util.Date().getTime());
personne.setId(new java.lang.Integer(Math.abs(r.nextInt())));
personne.setDateNaissance(new java.util.Date());
personne.setNbEnfants(0);
personne.setNom("");
personne.setPrenom("");
}
// on rend l'objet [Personne]
return personne;
}

// exécution de la commande
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse
response, Object
command, BindException errors) throws Exception {
// sauvegarde la personne ajoutée ou modifiée
Personne personne = (Personne) command;

try {
// sauvegarde de la personne
service.saveOne(personne);
// on redirige vers la liste des personnes
return new ModelAndView("r-list");
} catch (DaoException ex) {
int idPersonne = personne.getId().intValue();// on note l'erreur
ex.printStackTrace();
String message=idPersonne==-1 ? "personne.ajout.echec" :
"personne.modification.echec";
errors.reject(message,new Object[]{ex.getMessage()},"Echec de la mise à jour: {0}");
// on réaffiche le formulaire
return showForm(request,response, errors);
}
}

}


Atelier 6 – Le Framework Spring Page
:
2/26


Le contrôleur DeletePersonne :

Ce contrôleur contient le même code que ListPersonnes, la seule différence réside dans le traitement
fait par la méthode handleRequest.
Il faut alors remplacer son contenu par :
public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse
response) throws Exception {
// on récupère l'id de la personne à supprimer
int id = ServletRequestUtils.getIntParameter(request, "id", 0);
java.lang.Integer i = new java.lang.Integer(id);
// on supprime la personne
service.deleteOne(i);
// on redirige vers la liste des personnes
return new ModelAndView("r-list");
}


Le validator ValidatePersonnes :
ValidatePersonnes implémente l’interface org.springframework.validation.Validator. Cette interface
est complètement séparée de toute infrastructure ou contexte. Elle est utilisée pour valider n’importe
quel type d’objet dans la couche web, la couche d’accès aux données ou autre.
Voici son code :

package web;
import hibernate.personne.Personne;
import org.springframework.validation.Errors;
public class ValidatePersonne implements org.springframework.validation.Validator {

public boolean supports(Class classe) { return classe.isAssignableFrom(Personne.class); }
public void validate(Object obj, Errors erreurs) {
Personne personne = (Personne) obj; // on récupère la personne postée
String prénom = personne.getPrenom();// on vérifie le prénom
if (prénom==null || prénom.trim().length() == 0) {
erreurs.rejectValue("prenom", "Le prénom est nécessaire !");
}
String nom = personne.getNom();// on vérifie le nom
if (nom==null || nom.trim().length() == 0) {
erreurs.rejectValue("nom", "personne.nom.necessaire", "Le nom est nécessaire !");
}
int nbEnfants = personne.getNbEnfants();// on vérifie le nombre d'enfants
if (nbEnfants < 0) {
erreurs.rejectValue("nbEnfants", "personne.nbEnfants.invalide",
"Donnée incorrecte !");
}
}
}

Atelier 6 – Le Framework Spring Page
:
2/26



Exemple d'exécution :
Avant de tester l'application, créer la base de données MySQL de persistance SpringDB et initialiser
la table personnes par quelques lignes. Vous pouvez utiliser un client d'administration MySQL telque
SQL yog ou bien MySQL ControlCenter, ou même NetBeans ou bien encore Eclipse WTP.

Voici le script de création de la table personnes

CREATE TABLE `personnes` (
`num_personne` int(11) NOT NULL default '0',
`nom` varchar(30) default NULL,
`prenom` varchar(30) default NULL,
`date_naissance` date NOT NULL default '0000-00-00',
`nb_enfants` int(11) default NULL,
PRIMARY KEY (`num_personne`)
) TYPE=MyISAM

Revenons maintenant à l'IDE Générer l'application et la déployer sous Tomcat.
Lancer le navigateur et se connecter sur l'URL http://localhost:8080/SpringMVCPersonne/


La page de démarrage par défaut est index.jsp, mais cette pase renvoie sur la la page list.jsp donnant
la liste des personnes inscrites dans la base de données. Voici un aperçu de cette page :


Nous pouvons par exemple modifier chacune des entités, la supprimer ou rajouter de nouvelles entrées.
Atelier 6 – Le Framework Spring Page
:
2/26



Une fois la validation activée, la liste des entités mise à jour est affichée.