Download - TP3-Passage vers Spring.pdf
[email protected] Page 1
Passage vers Spring
Cycle de Formations Technologique avancées : Framework : Spring
M. Belhassen OUESLATI
Ingénieur Java/J2EE
Travaux pratique TP N°4 Passage vers Spring
Objectifs Développer un premier exemple de composants liés Détecter le besoin d'Ioc
Pré-requis
TP N°2 : HIBERNATE : RECHERCHE D’UN OBJECT DANS LA SESSION
[email protected] Page 2
Passage vers Spring
1. Cas pratique : « Gestion des contacts » (cahier technique)
1.1 Sujet
Le but de cet exercice est de créer une application permettant de gérer une
liste de contacts.
On doit pouvoir lister, ajouter, supprimer, modifier, rechercher ces contacts.
1.2 Analyse
Dans un premier temps, avant l’écriture des premières lignes de codes, nous
allons définir les entités et les fonctionnalités requises pour notre application.
1.2.1 Définition des entités
D’après le sujet, on a besoin de "gérer une liste de contacts".
Cela signifie donc que l’on doit créer une classe Contact qui aura pour
attributs toutes les informations d’un contact : nom, prénom, …
1.2.2 Définition des fonctionnalités
On a besoin d’ajouter, lister, supprimer nos contacts.
Cas d’utilisation « Ajouter un contact »
1. Entrée des informations du contact.
2. Validation des entrées.
a. Vérification de la conformité des informations (nom, prénom, …).
i. Si les données sont conformes, le programme ajoute le contact et
indique un message positif au client.
ii. Si les données ne sont pas conformes, le programme renvoie une
erreur à l’utilisateur.
[email protected] Page 3
Passage vers Spring
Cas d’utilisation « Lister les contacts »
1. Récupération de l’ensemble des informations du support de stockage.
a. Si la récupération s’est bien passée :
i. S’il existe au moins un contact dans le support de stockage, le
programme affiche la liste des contacts (nom, prénom, adresse,
email…).
ii. S’il n’existe aucun contact dans la base de données, le programme
affiche un message indiquant qu’aucun contact n’a été trouvé.
b. Si la récupération s’est mal passée, le programme renvoie au client un
message d’erreur logicielle.
Cas d’utilisation « Supprimer un contact »
1. Liste des contacts affichée dans la console avec le numéro Id
correspondant.
2. Choix du numéro Id du contact à supprimer.
3. Le programme vérifie que le contact existe bien :
o Si le contact existe bien, le programme tente de supprimer le contact
demandé :
Si la suppression a échoué, le programme renvoie à l’utilisateur
une erreur lui indiquant une erreur logicielle.
Si la suppression a réussi, le programme renvoie à l’utilisateur un
message de confirmation de suppression du contact.
o Si le contact n’existe pas, le programme renvoie un message indiquant
l’absence de ce contact dans le support de stockage.
[email protected] Page 4
Passage vers Spring
2. Architecture technique
Nous allons séparer au maximum les différents types de traitement de
l’application en tenant compte des explications du cours (Présentation,
métiers/Service, Dao, Persistance).
2.1 Table contact
Table contact
CREATE TABLE "DEV"."CONTACT" ( "NUM_MAT_CNT" VARCHAR2(10 BYTE) NOT NULL ENABLE, "NOM_NOM_CNT" VARCHAR2(120 BYTE) NOT NULL ENABLE, "NOM_PRN_CNT" VARCHAR2(120 BYTE) NOT NULL ENABLE, "NUM_GSM_CNT" VARCHAR2(8 BYTE) NOT NULL ENABLE, "ADR_EMAIL_CNT" VARCHAR2(120 BYTE) NOT NULL ENABLE, CONSTRAINT "CONTACT__PK" PRIMARY KEY ("NUM_MAT_CNT") ENABLE ) ;
2.2 Nouveau projet de type Dynamic Web : TP_SPRING
Créer un nouveau projet de type dynamic web qui porte le nom : TP_SPRING
2.3 Configuration de la connexion
Voir TP N°2
2.4 Couche Objets persistance : Classe Contact
Cette couche est composée d'objets Java simples qui représentent les
données persistantes de l'application comme par exemple un client ou une
facture.
Pour cette partie, nous utilisons la technologie Hibernate qui va permettre de
mapper ces objets avec la base de données.
Nous y ajoutons la classe Contact avec, pour variables d’instances :
o String nomNomCnt;
o String nomPrnCnt;
o ….
Ces variables doivent évidemment être déclarées en privées et des
getter/setter sont implémentés.
[email protected] Page 5
Passage vers Spring
Implémentation de la classe persistante Contact
Utiliser la méthode de génération de code avec la perspective Hibernate (Voir TP N°2)
package com.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "CONTACT") public class Contact implements java.io.Serializable { private String numMatCnt; private String nomNomCnt; private String nomPrnCnt; private String numGsmCnt; private String adrEmailCnt; public Contact() { } public Contact(String numMatCnt, String nomNomCnt, String nomPrnCnt, String numGsmCnt, String adrEmailCnt) { this.numMatCnt = numMatCnt; this.nomNomCnt = nomNomCnt; this.nomPrnCnt = nomPrnCnt; this.numGsmCnt = numGsmCnt; this.adrEmailCnt = adrEmailCnt;
} + getter/setter
}
Note : Hibernate permet une certaine indépendance vis à vis du SGBD qu'on
souhaite utiliser avec l'application développée.
[email protected] Page 6
Passage vers Spring
2.5 Couche Dao : Classe ContactDaoImp
Cette couche a pour objectif d'encapsuler et d'abstraire l'accès aux données.
Concrètement, les développeurs vont utiliser cette couche pour récupérer,
mettre à jour, supprimer ou insérer des nouvelles données. L'utilité de cette
couche est que le développeur va utiliser des fonctions simples qui vont
masquer toute la complexité sous jacente.
Le développeur utilisateur de ces fonctions n'aura même pas à connaitre les
détails de l'implémentation, il ne saura même pas si la technologie utilisée est
Hibernate, SQL ou EJB3. Il ne verra que de simples fonctions Java.
Nous ajoutons par ailleurs l’interface GenericDao
Interface GenericDao package com.dao; import java.io.Serializable; import java.util.List; import org.hibernate.criterion.Criterion; public interface GenericDao { public void saveOrUpdate(Object entity); public void delete(Object entity); public List<Object> findAll(Class clazz); public List findByCriteria(Class clazz, Criterion critere); public Object findById(Class clazz, Serializable id); }
[email protected] Page 7
Passage vers Spring
Nous ajoutons par ailleurs la classe GenericDaoImp
Implémentation de l’interface GenericDao package com.dao.impl; // import… public class GenericDaoImpl implements GenericDao { private Session hibernateSession; private Transaction tx; public GenericDaoImpl() { hibernateSession = HibernateUtil.currentSession(); } @Override public void saveOrUpdate(Object entity) { try { startOperation(); hibernateSession.saveOrUpdate(entity); tx.commit(); } catch (HibernateException e) { handleException(e); } finally { hibernateSession.close(); } } @Override public void delete(Object entity) { try { startOperation(); hibernateSession.delete(entity); tx.commit(); } catch (HibernateException e) { handleException(e); } finally { hibernateSession.close(); } } @Override public List<Object> findAll(Class clazz) { List objects = null; try { startOperation(); Query query = hibernateSession.createQuery("from " + clazz.getName());
[email protected] Page 8
Passage vers Spring
objects = query.list(); } catch (HibernateException e) { handleException(e); } finally { hibernateSession.close(); } return objects; } @Override public List findByCriteria(Class clazz, Criterion critere) { List objects = null; try { startOperation(); Criteria crit = hibernateSession.createCriteria(clazz).add(critere); objects = crit.list(); } catch (HibernateException e) { handleException(e); } finally { hibernateSession.close(); } return objects; } @Override public Object findById(Class clazz, Serializable id) { Object obj = null; try { startOperation(); obj = hibernateSession.load(clazz, id); } catch (HibernateException e) { handleException(e); } finally { hibernateSession.close(); } return obj; } protected void startOperation() throws HibernateException { hibernateSession = HibernateUtil.currentSession(); tx = hibernateSession.beginTransaction(); } protected void handleException(HibernateException e) throws DataAccessLayerException { tx.rollback(); throw new DataAccessLayerException(e); } }
[email protected] Page 9
Passage vers Spring
Classe DataAccessLayerException
package com.dao.impl; public class DataAccessLayerException extends RuntimeException { public DataAccessLayerException() { } public DataAccessLayerException(String message) { super(message); } public DataAccessLayerException(Throwable cause) { super(cause); } public DataAccessLayerException(String message, Throwable cause) { super(message, cause); } }
Nous ajoutons par ailleurs l’interface ContactDao implémentée par la classe
ContactDaoImp.
Interface ContactDao
package com.dao; public interface ContactDao extends GenericDao { }
Implémentation de l’interface ContactDao
package com.dao.impl; import com.dao.ContactDao; public class ContactDaoImp extends GenericDaoImpl implements ContactDao { }
Note : Comme vous vous en doutez, les développeurs ne verront jamais
l'implémentation, ils se contenteront d'utiliser l'interface ContactDAO.
En cas de changement de technologie, il suffira de réécrire seulement
l'implémentation, tout le reste du code n'aura pas à être migré.
[email protected] Page 10
Passage vers Spring
2.6 Couche Business : Classe ContactBusiness
Cette couche contient le logique métier de l'application.
Voici un exemple qui illustre la différence entre couche DAO et couche
service :
Dans la couche DAO, la méthode delete(Object entity) supprime un
contact quel qu’il soit.
Dans la couche business, la méthode supprimerContact(String numero)
ajoute le code qui va gérer les règles particulières de l'application, par
exemple, nous allons peut être tester que le contact n'est pas un
administrateur, dans le cas où s'en est un, nous allons déclencher une
exception qui indiquera qu'une règle interdit la suppression de cet
utilisateur particulier.
Ce qu'il faut bien saisir avec cet exemple, c'est que les DAO se chargent de
gérer la persistance des données de manière basique, la couche business
elle y ajoute la logique liée au métier.
Interface ContactBusiness: package com.business; import java.util.List; import org.hibernate.criterion.Criterion; import com.model.Contact; public interface ContactBusiness { public void ajouterContact(Contact contact); public Contact recupererContactByCriteria(Criterion critere); public void supprimerContact(String numero); public List<Contact> recupererListContacts(); }
[email protected] Page 11
Passage vers Spring
Implémentation de l’interface ContactBusiness package com.business.impl; // import … public class ContactBusinessImp implements ContactBusiness { ContactDao ctDAO = new ContactDaoImp(); @Override public void ajouterContact(Contact contact) { if (contact != null) { ctDAO.saveOrUpdate(contact); } } @Override public Contact recupererContactByCriteria(Criterion criterion) { Session session = HibernateUtil.currentSession(); Criteria crit = session.createCriteria(Contact.class); crit.add(criterion); crit.setMaxResults(1); List<Contact> result = crit.list(); Contact ct = result.get(0); session.close(); return ct; } @Override Public void supprimerContact(String numero) { Contact ct = (Contact) ctDAO.findById(Contact.class, numero); ctDAO.delete(ct); } @Override public List<Contact> recupererListContacts() { List result = ctDAO.findAll(Contact.class); return result; } }
[email protected] Page 12
Passage vers Spring
2.7 Réaliser l'exemple
Exécuter la classe TestPassageVersSpring.java
Implémentation de la classe TestPassageVersSpring package com.util; // import …. public class TestPassageVersSpring { public static void main(String[] args) { ContactBusiness ctBusiness = new ContactBusinessImp(); // création d'un nouveau Contact Contact ct = new Contact(); ct.setNumMatCnt("4822"); ct.setNomNomCnt("Mhamed"); ct.setNomPrnCnt("Ben Saleh"); ct.setNumGsmCnt("99731434"); ct.setAdrEmailCnt("[email protected]"); ctBusiness.ajouterContact(ct); // Suppression d'un Contact Criterion criterion = Restrictions.like("nomNomCnt", "Mohamed%"); ctBusiness.recupererContactByCriteria(criterion); Contact ct = ctBusiness.recupererContactByCriteria(criterion); List<Contact> results = new ArrayList(); results.add(ct); displayList(results); ctBusiness.supprimerContact(ct.getNumMatCnt()); // Recuperation de ts ls Contact List results = ctBusiness.recupererListContacts(); displayList(results); } static public void displayList(List list) { Iterator iter = list.iterator(); if (!iter.hasNext()) { System.out.println("La lsite est vide"); return; } while (iter.hasNext()) { Contact ct = (Contact) iter.next(); System.out.println("Matricule :" + ct.getNumMatCnt() + " Nom :" + ct.getNomNomCnt() + " Prénom :" + ct.getNomPrnCnt()); } } }
[email protected] Page 13
Passage vers Spring
2.8 Question ?
Qu'est ce qu'on remarque ?
Si on veut utiliser une autre implémentation de ContactDao, qu'est ce qu'il faut
faire?