Skip to content

16. Application web MVC dans une architecture 3tier – Exemple 2

16.1. Introduction

Nous avons écrit l'application [personnes-01] ayant la structure suivante :

La couche [dao] implémentait la liste des personnes gérée à l'aide d'un objet [ArrayList]. Cela nous a permis de ne pas nous apesantir sur les couches [dao] et [service] pour nous concentrer sur la couche [web]. Nous souhaitons faire évoluer l'application vers un environnement plus réaliste où la liste des personnes serait mémorisée dans une table de bases de données. Cela va nous amener à changer la couche [dao]. Cela va impacter les deux autres couches. Pour profiter de l'indépendance des couches amenée par Spring IoC, nous allons reprendre l'application [personnes-01] et la configurer avec Spring IoC :

La nouvelle application s'appellera [personnes-02]. Une fois qu'elle aura été écrite, nous savons que nous pourrons changer les couches [dao] et [service] sans changement du code de la couche [web]. C'est cela que nous recherchons.

Nous créons un nouveau projet Eclipse [personnes-02] par copier / coller du projet [personnes-01] comme il a été expliqué au paragraphe 6.2 :

En [1], nous voyons apparaître le fichier de configuration dans lequel nous allons définir les beans des couches [dao] et [service]. Son contenu est le suivant :


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!-- la classe dao -->
    <bean id="dao" class="istia.st.mvc.personnes.dao.DaoImpl" init-method="init"/>
    <!-- la classe service -->
    <bean id="service" class="istia.st.mvc.personnes.service.ServiceImpl">
        <property name="dao">
            <ref local="dao" />
        </property>
    </bean>
</beans>
  • ligne 5 : définit le bean nommé [dao] comme une instance de la classe [DaoImpl]. Après instanciation, la méthode [init] de l'instance est exécutée.
  • lignes 7-10 : définissent le bean nommé [service] comme une instance de la classe [ServiceImpl].
  • lignes 8-10 : la propriété [dao] de l'instance [DaoImpl] est initialisée avec la référence de la couche [dao] créée ligne 5. Rappelons que la classe [ServiceImpl] a bien la propriété [dao] et le setter qui va avec :
public class ServiceImpl implements IService {

    // la couche [dao]
    private IDao dao;

    public IDao getDao() {
        return dao;
    }

    public void setDao(IDao dao) {
        this.dao = dao;
    }
...

Seul ce fichier ne fait rien bien sûr. Le contrôleur [Application] va l'utiliser dans sa méthode [init] pour instancier la couche [service]. Rappelons la version précédente de la méthode [init] du contrôleur :

@SuppressWarnings("serial")
public class Application extends HttpServlet {
...
    // service
    ServiceImpl service = null;

    // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
...
        // instanciation de la couche [dao]
        DaoImpl dao = new DaoImpl();
        dao.init();
        // instanciation de la couche [service]
        service = new ServiceImpl();
        service.setDao(dao);
    }

En ligne 5, nous avions été obligés de nommer explicitement la classe d'implémentation de la couche [service] et en ligne 12, celle de la couche [dao]. Avec Spring IoC, la méthode [init] devient la suivante :

@SuppressWarnings("serial")
public class Application extends HttpServlet {
    // paramètres d'instance
    ...

    // service
    private IService service = null;

    // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
    ...
        // instanciation de la couche [service]
        service = (IService) new XmlBeanFactory(new ClassPathResource("spring-config.xml")).getBean("service");
    }
  • ligne 7 : le champ privé [service] n'est plus de type [ServiceImpl] mais de type [IService], c.a.d. du type de l'interface de la couche [service]. La couche [web] n'est donc plus liée à une implémentation particulière de cette interface.
  • ligne 14 : initialisation du champ [service] à partir du fichier de configuration [spring-config.xml].

Ce sont les seules modifications à faire. Intégrons cette nouvelle application dans Tomcat, lançons celui-ci puis demandons l'Url [http://localhost:8080/personnes-02] :

Image

16.2. Mise en archives de l’application web

Nous avons développé un projet Eclipse / Tomcat d’une application 3tier :

Dans une version à venir, le groupe de personnes va être placée dans une table de base de données.

  • Cela va induire une réécriture de la couche [dao]. Cela, on peut aisément le comprendre.
  • La couche [service] va être également modifiée. Actuellement, son unique rôle est d’assurer un accès synchronisé aux données gérées par la couche [dao]. Dans ce but, nous avons synchronisé toutes les méthodes de la couche [service]. Nous avons expliqué pourquoi cette synchronisation était placée dans cette couche plutôt que dans la couche [dao]. Dans la nouvelle version, la couche [service] aura encore l’unique rôle de synchronisation des accès mais celle-ci sera assurée par des transactions de base de données plutôt que par une synchronisation de méthodes Java.
  • La couche [web] va elle rester inchangée.

Afin de faciliter le passage d’une version à l’autre, nous créons un nouveau projet Eclipse [mvc-personnes-02B], copie du projet précédent [mvc-personnes-02] mais où les couches [web, service, dao, entites] ont été mises dans des archives .jar :

Le dossier [src] ne contient désormais que le fichier de configuration Spring [spring-config.xml]. Il contenait auparavant également le code source des classes Java. Ces éléments ont disparu, remplacés par leurs éléments compilés mis dans les archives [personnes-*.jar] montrés en [1] :

Le projet [mvc-personnes-02B] a été configuré pour inclure les archives [personnes-*.jar ] dans son ClassPath.

Nous déployons le projet web [mvc-personnes-02B] au sein de Tomcat :

Pour tester le projet, nous lançons Tomcat puis demandons l’url [http://localhost:8080/personnes02B] :

Image

Le lecteur est invité à faire des tests complémentaires.

Dans la version avec base de données, nous allons changer les couches [service] et [dao]. Nous voulons montrer qu’il suffira alors, de remplacer dans le projet précédent les archives [personnes-dao.jar] et [personnes-service.jar] par les nouvelles archives pour que notre application fonctionne désormais avec une base de données. Nous n’aurons pas à toucher aux archives de la couche [web] et de la couche [entites].